Merge remote-tracking branch 'origin/master' into jme3-vr-dev

fix-456
jseinturier 8 years ago
commit f7a852b755
  1. 4
      README.md
  2. 7
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/TextureHelper.java
  3. 8
      jme3-bullet/src/main/java/com/jme3/bullet/collision/shapes/CompoundCollisionShape.java
  4. 73
      jme3-core/src/main/java/com/jme3/animation/Bone.java
  5. 106
      jme3-core/src/main/java/com/jme3/animation/SkeletonControl.java
  6. 13
      jme3-core/src/main/java/com/jme3/math/Transform.java
  7. 41
      jme3-core/src/main/java/com/jme3/scene/Mesh.java
  8. 129
      jme3-core/src/main/java/com/jme3/scene/Spatial.java
  9. 1
      jme3-core/src/main/java/com/jme3/scene/debug/SkeletonInterBoneWire.java
  10. 1
      jme3-core/src/main/java/com/jme3/scene/debug/SkeletonPoints.java
  11. 27
      jme3-core/src/main/java/com/jme3/scene/instancing/InstancedGeometry.java
  12. 2
      jme3-core/src/main/java/com/jme3/system/AppSettings.java
  13. 3
      jme3-core/src/main/resources/Common/MatDefs/Misc/Unshaded.j3md
  14. 7
      jme3-core/src/main/resources/Common/MatDefs/Misc/Unshaded.vert
  15. 13
      jme3-core/src/main/resources/Common/ShaderLib/Instancing.glsllib
  16. 2
      jme3-core/src/main/resources/Common/ShaderLib/Skinning.glsllib
  17. 2
      jme3-core/src/plugins/java/com/jme3/texture/plugins/DDSLoader.java
  18. 2
      jme3-examples/src/main/java/jme3test/light/TestSpotLightTerrain.java
  19. 3
      jme3-examples/src/main/java/jme3test/model/anim/TestAnimBlendBug.java
  20. 127
      jme3-examples/src/main/java/jme3test/model/anim/TestAttachmentsNode.java
  21. 1
      jme3-examples/src/main/java/jme3test/model/anim/TestOgreComplexAnim.java
  22. 62
      jme3-examples/src/main/java/jme3test/scene/instancing/TestInstanceNodeWithLight.java
  23. 28
      jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwMouseInput.java
  24. 127
      jme3-lwjgl3/src/main/java/com/jme3/util/LWJGLBufferAllocator.java
  25. 23
      jme3-terrain/src/main/java/com/jme3/terrain/geomipmap/TerrainPatch.java
  26. 8
      jme3-terrain/src/main/resources/Common/MatDefs/Terrain/SPTerrainLighting.frag
  27. 8
      jme3-terrain/src/main/resources/Common/MatDefs/Terrain/TerrainLighting.frag
  28. 22
      jme3-terrain/src/main/resources/Common/MatDefs/Terrain/TerrainLighting.j3md

@ -3,11 +3,11 @@ jMonkeyEngine
[![Build Status](https://travis-ci.org/jMonkeyEngine/jmonkeyengine.svg?branch=master)](https://travis-ci.org/jMonkeyEngine/jmonkeyengine)
jMonkeyEngine is a 3D game engine for adventurous Java developers. It’s open source, cross platform and cutting edge. And it is all beautifully documented. The 3.0 branch is the latest stable version of the jMonkeyEngine 3 SDK, a complete game development suite. We'll be frequently submitting stable 3.0.x updates until the major 3.1 version arrives.
jMonkeyEngine is a 3D game engine for adventurous Java developers. It’s open-source, cross-platform, and cutting-edge. 3.1.0 is the latest stable version of the jMonkeyEngine 3 SDK, a complete game development suite. We'll release 3.1.x updates until the major 3.2 release arrives.
The engine is used by several commercial game studios and computer-science courses. Here's a taste:
![jME3 Games Mashup](http://i.imgur.com/hBehW2i.jpg)
![jME3 Games Mashup](https://i.imgur.com/nF8WOW6.jpg)
- [jME powered games on IndieDB](http://www.indiedb.com/engines/jmonkeyengine/games)
- [Maker's Tale](http://steamcommunity.com/sharedfiles/filedetails/?id=93461954t)

@ -42,6 +42,7 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.asset.AssetInfo;
import com.jme3.asset.AssetLoadException;
import com.jme3.asset.AssetManager;
import com.jme3.asset.AssetNotFoundException;
import com.jme3.asset.BlenderKey;
@ -486,7 +487,7 @@ public class TextureHelper extends AbstractBlenderHelper {
key.setGenerateMips(generateMipmaps);
result = assetManager.loadTexture(key);
result.setKey(key);
} catch (AssetNotFoundException e) {
} catch (AssetNotFoundException | AssetLoadException e) {
LOGGER.fine(e.getLocalizedMessage());
}
} else {
@ -522,7 +523,7 @@ public class TextureHelper extends AbstractBlenderHelper {
// If texture is found return it;
return result;
}
} catch (AssetNotFoundException e) {
} catch (AssetNotFoundException | AssetLoadException e) {
LOGGER.fine(e.getLocalizedMessage());
}
}
@ -532,7 +533,7 @@ public class TextureHelper extends AbstractBlenderHelper {
try {
TextureKey key = new TextureKey(name);
assetManager.loadTexture(key);
} catch (AssetNotFoundException e) {
} catch (AssetNotFoundException | AssetLoadException e) {
LOGGER.fine(e.getLocalizedMessage());
}
}

@ -119,14 +119,6 @@ public class CompoundCollisionShape extends CollisionShape {
return children;
}
/**
* WARNING - CompoundCollisionShape scaling has no effect.
*/
@Override
public void setScale(Vector3f scale) {
Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "CompoundCollisionShape cannot be scaled");
}
private native long createShape();
private native long addChildShape(long objectId, long childId, Vector3f location, Matrix3f rotation);

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009-2012 jMonkeyEngine
* Copyright (c) 2009-2017 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -33,7 +33,11 @@ package com.jme3.animation;
import com.jme3.export.*;
import com.jme3.math.*;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.util.SafeArrayList;
import com.jme3.util.TempVars;
import com.jme3.util.clone.JmeCloneable;
import com.jme3.util.clone.Cloner;
@ -80,7 +84,10 @@ public final class Bone implements Savable, JmeCloneable {
* The attachment node.
*/
private Node attachNode;
/**
* A geometry animated by this node, used when updating the attachments node.
*/
private Geometry targetGeometry = null;
/**
* Bind transform is the local bind transform of this bone. (local space)
*/
@ -187,7 +194,8 @@ public final class Bone implements Savable, JmeCloneable {
this.children = cloner.clone(children);
this.attachNode = cloner.clone(attachNode);
this.targetGeometry = cloner.clone(targetGeometry);
this.bindPos = cloner.clone(bindPos);
this.bindRot = cloner.clone(bindRot);
this.bindScale = cloner.clone(bindScale);
@ -505,9 +513,39 @@ public final class Bone implements Savable, JmeCloneable {
}
if (attachNode != null) {
updateAttachNode();
}
}
/**
* Update the local transform of the attachments node.
*/
private void updateAttachNode() {
Node attachParent = attachNode.getParent();
if (attachParent == null || targetGeometry == null
|| targetGeometry.getParent() == attachParent
&& targetGeometry.getLocalTransform().isIdentity()) {
/*
* The animated meshes are in the same coordinate system as the
* attachments node: no further transforms are needed.
*/
attachNode.setLocalTranslation(modelPos);
attachNode.setLocalRotation(modelRot);
attachNode.setLocalScale(modelScale);
} else {
Spatial loopSpatial = targetGeometry;
Transform combined = new Transform(modelPos, modelRot, modelScale);
/*
* Climb the scene graph applying local transforms until the
* attachments node's parent is reached.
*/
while (loopSpatial != attachParent && loopSpatial != null) {
Transform localTransform = loopSpatial.getLocalTransform();
combined.combineWithParent(localTransform);
loopSpatial = loopSpatial.getParent();
}
attachNode.setLocalTransform(combined);
}
}
@ -661,15 +699,32 @@ public final class Bone implements Savable, JmeCloneable {
}
/**
* Returns the attachment node.
* Attach models and effects to this node to make
* them follow this bone's motions.
*/
Node getAttachmentsNode() {
* Access the attachments node of this bone. If this bone doesn't already
* have an attachments node, create one. Models and effects attached to the
* attachments node will follow this bone's motions.
*
* @param boneIndex this bone's index in its skeleton (≥0)
* @param targets a list of geometries animated by this bone's skeleton (not
* null, unaffected)
*/
Node getAttachmentsNode(int boneIndex, SafeArrayList<Geometry> targets) {
targetGeometry = null;
/*
* Search for a geometry animated by this particular bone.
*/
for (Geometry geometry : targets) {
Mesh mesh = geometry.getMesh();
if (mesh != null && mesh.isAnimatedByBone(boneIndex)) {
targetGeometry = geometry;
break;
}
}
if (attachNode == null) {
attachNode = new Node(name + "_attachnode");
attachNode.setUserData("AttachedBone", this);
}
return attachNode;
}
@ -823,6 +878,7 @@ public final class Bone implements Savable, JmeCloneable {
}
attachNode = (Node) input.readSavable("attachNode", null);
targetGeometry = (Geometry) input.readSavable("targetGeometry", null);
localPos.set(bindPos);
localRot.set(bindRot);
@ -845,6 +901,7 @@ public final class Bone implements Savable, JmeCloneable {
output.write(name, "name", null);
output.write(attachNode, "attachNode", null);
output.write(targetGeometry, "targetGeometry", null);
output.write(bindPos, "bindPos", null);
output.write(bindRot, "bindRot", null);
output.write(bindScale, "bindScale", new Vector3f(1.0f, 1.0f, 1.0f));

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009-2012 jMonkeyEngine
* Copyright (c) 2009-2017 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -52,7 +52,6 @@ import java.io.IOException;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
@ -71,10 +70,12 @@ public class SkeletonControl extends AbstractControl implements Cloneable, JmeCl
* The skeleton of the model.
*/
private Skeleton skeleton;
/**
* List of targets which this controller effects.
* List of geometries affected by this control.
*/
private SafeArrayList<Mesh> targets = new SafeArrayList<Mesh>(Mesh.class);
private SafeArrayList<Geometry> targets = new SafeArrayList<Geometry>(Geometry.class);
/**
* Used to track when a mesh was updated. Meshes are only updated if they
* are visible in at least one camera.
@ -124,8 +125,9 @@ public class SkeletonControl extends AbstractControl implements Cloneable, JmeCl
for (Material m : materials) {
m.setInt("NumberOfBones", numBones);
}
for (Mesh mesh : targets) {
if (mesh.isAnimated()) {
for (Geometry geometry : targets) {
Mesh mesh = geometry.getMesh();
if (mesh != null && mesh.isAnimated()) {
mesh.prepareForAnim(false);
}
}
@ -137,8 +139,9 @@ public class SkeletonControl extends AbstractControl implements Cloneable, JmeCl
m.clearParam("NumberOfBones");
}
}
for (Mesh mesh : targets) {
if (mesh.isAnimated()) {
for (Geometry geometry : targets) {
Mesh mesh = geometry.getMesh();
if (mesh != null && mesh.isAnimated()) {
mesh.prepareForAnim(true);
}
}
@ -210,15 +213,22 @@ public class SkeletonControl extends AbstractControl implements Cloneable, JmeCl
this.skeleton = skeleton;
}
/**
* If specified the geometry has an animated mesh, add its mesh and material
* to the lists of animation targets.
*/
private void findTargets(Geometry geometry) {
Mesh mesh = geometry.getMesh();
if (mesh != null && mesh.isAnimated()) {
targets.add(geometry);
materials.add(geometry.getMaterial());
}
}
private void findTargets(Node node) {
for (Spatial child : node.getChildren()) {
if (child instanceof Geometry) {
Geometry geom = (Geometry) child;
Mesh mesh = geom.getMesh();
if (mesh.isAnimated()) {
targets.add(mesh);
materials.add(geom.getMaterial());
}
findTargets((Geometry) child);
} else if (child instanceof Node) {
findTargets((Node) child);
}
@ -236,10 +246,11 @@ public class SkeletonControl extends AbstractControl implements Cloneable, JmeCl
offsetMatrices = skeleton.computeSkinningMatrices();
for (Mesh mesh : targets) {
// NOTE: This assumes that code higher up
// Already ensured those targets are animated
// otherwise a crash will happen in skin update
for (Geometry geometry : targets) {
Mesh mesh = geometry.getMesh();
// NOTE: This assumes code higher up has
// already ensured this mesh is animated.
// Otherwise a crash will happen in skin update.
softwareSkinUpdate(mesh, offsetMatrices);
}
}
@ -313,8 +324,9 @@ public class SkeletonControl extends AbstractControl implements Cloneable, JmeCl
//only do this for software updates
void resetToBind() {
for (Mesh mesh : targets) {
if (mesh.isAnimated()) {
for (Geometry geometry : targets) {
Mesh mesh = geometry.getMesh();
if (mesh != null && mesh.isAnimated()) {
Buffer bwBuff = mesh.getBuffer(Type.BoneWeight).getData();
Buffer biBuff = mesh.getBuffer(Type.BoneIndex).getData();
if (!biBuff.hasArray() || !bwBuff.hasArray()) {
@ -432,9 +444,13 @@ public class SkeletonControl extends AbstractControl implements Cloneable, JmeCl
}
/**
* Access the attachments node of the named bone. If the bone doesn't
* already have an attachments node, create one and attach it to the scene
* graph. Models and effects attached to the attachments node will follow
* the bone's motions.
*
* @param boneName the name of the bone
* @return the node attached to this bone
* @return the attachments node of the bone
*/
public Node getAttachmentsNode(String boneName) {
Bone b = skeleton.getBone(boneName);
@ -443,9 +459,20 @@ public class SkeletonControl extends AbstractControl implements Cloneable, JmeCl
+ "in the skeleton.");
}
Node n = b.getAttachmentsNode();
Node model = (Node) spatial;
model.attachChild(n);
updateTargetsAndMaterials(spatial);
int boneIndex = skeleton.getBoneIndex(b);
Node n = b.getAttachmentsNode(boneIndex, targets);
/*
* Select a node to parent the attachments node.
*/
Node parent;
if (spatial instanceof Node) {
parent = (Node) spatial; // the usual case
} else {
parent = spatial.getParent();
}
parent.attachChild(n);
return n;
}
@ -459,12 +486,20 @@ public class SkeletonControl extends AbstractControl implements Cloneable, JmeCl
}
/**
* returns a copy of array of the targets meshes of this control
* Enumerate the target meshes of this control.
*
* @return
* @return a new array
*/
public Mesh[] getTargets() {
return targets.toArray(new Mesh[targets.size()]);
public Mesh[] getTargets() {
Mesh[] result = new Mesh[targets.size()];
int i = 0;
for (Geometry geometry : targets) {
Mesh mesh = geometry.getMesh();
result[i] = mesh;
i++;
}
return result;
}
/**
@ -758,12 +793,19 @@ public class SkeletonControl extends AbstractControl implements Cloneable, JmeCl
skeleton = (Skeleton) in.readSavable("skeleton", null);
}
/**
* Update the lists of animation targets.
*
* @param spatial the controlled spatial
*/
private void updateTargetsAndMaterials(Spatial spatial) {
targets.clear();
materials.clear();
if (spatial != null && spatial instanceof Node) {
Node node = (Node) spatial;
findTargets(node);
materials.clear();
if (spatial instanceof Node) {
findTargets((Node) spatial);
} else if (spatial instanceof Geometry) {
findTargets((Geometry) spatial);
}
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009-2012 jMonkeyEngine
* Copyright (c) 2009-2017 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -288,6 +288,17 @@ public final class Transform implements Savable, Cloneable, java.io.Serializable
rot.set(0, 0, 0, 1);
}
/**
* Test for exact identity.
*
* @return true if exactly equal to {@link #IDENTITY}, otherwise false
*/
public boolean isIdentity() {
return translation.x == 0f && translation.y == 0f && translation.z == 0f
&& scale.x == 1f && scale.y == 1f && scale.z == 1f
&& rot.w == 1f && rot.x == 0f && rot.y == 0f && rot.z == 0f;
}
@Override
public int hashCode() {
int hash = 7;

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009-2012 jMonkeyEngine
* Copyright (c) 2009-2017 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -1408,6 +1408,45 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
getBuffer(Type.HWBoneIndex) != null;
}
/**
* Test whether the specified bone animates this mesh.
*
* @param boneIndex the bone's index in its skeleton
* @return true if the specified bone animates this mesh, otherwise false
*/
public boolean isAnimatedByBone(int boneIndex) {
VertexBuffer biBuf = getBuffer(VertexBuffer.Type.BoneIndex);
VertexBuffer wBuf = getBuffer(VertexBuffer.Type.BoneWeight);
if (biBuf == null || wBuf == null) {
return false; // no bone animation data
}
ByteBuffer boneIndexBuffer = (ByteBuffer) biBuf.getData();
boneIndexBuffer.rewind();
int numBoneIndices = boneIndexBuffer.remaining();
assert numBoneIndices % 4 == 0 : numBoneIndices;
int numVertices = boneIndexBuffer.remaining() / 4;
FloatBuffer weightBuffer = (FloatBuffer) wBuf.getData();
weightBuffer.rewind();
int numWeights = weightBuffer.remaining();
assert numWeights == numVertices * 4 : numWeights;
/*
* Test each vertex to determine whether the bone affects it.
*/
byte biByte = (byte) boneIndex; // bone indices wrap after 127
for (int vIndex = 0; vIndex < numVertices; vIndex++) {
for (int wIndex = 0; wIndex < 4; wIndex++) {
byte bIndex = boneIndexBuffer.get();
float weight = weightBuffer.get();
if (wIndex < maxNumWeights && bIndex == biByte && weight != 0f) {
return true;
}
}
}
return false;
}
/**
* Sets the count of vertices used for each tessellation patch
* @param patchVertexCount

@ -141,7 +141,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
protected SafeArrayList<MatParamOverride> localOverrides;
protected SafeArrayList<MatParamOverride> worldOverrides;
/**
/**
* This spatial's name.
*/
protected String name;
@ -170,60 +170,6 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
*/
protected transient int refreshFlags = 0;
public void refreshFlagOr(int flag){
refreshFlags |= flag;
//logger.warning("Changing refresh flags for spatial " + getName()+", flags: "+getRefreshFlagsDescription());
}
public void refreshFlagAnd(int flag){
refreshFlags &= flag;
//logger.warning("Changing refresh flags for spatial " + getName()+", flags: "+getRefreshFlagsDescription());
}
public int refreshFlagGetAnd(int flag){
return (refreshFlags & flag);
}
public int getRefreshFlags(){
return refreshFlags;
}
public String getRefreshFlagsDescription(){
String str = "";
if (refreshFlags == 0){
str += "OK";
} else {
// need light resort + combine transforms
if ((refreshFlags & RF_TRANSFORM) == RF_TRANSFORM){
str += "RF_TRANSFORM ";
}
// need light resort + combine transforms
if ((refreshFlags & RF_BOUND) == RF_BOUND){
str += "RF_BOUND ";
}
// changes in light lists
if ((refreshFlags & RF_LIGHTLIST) == RF_LIGHTLIST){
str += "RF_LIGHTLIST ";
}
// some child need geometry update
if ((refreshFlags & RF_CHILD_LIGHTLIST) == RF_CHILD_LIGHTLIST){
str += "RF_CHILD_LIGHTLIST ";
}
// some child need geometry update
if ((refreshFlags & RF_MATPARAM_OVERRIDE) == RF_MATPARAM_OVERRIDE){
str += "RF_MATPARAM_OVERRIDE ";
}
}
return str;
}
/**
* Set to true if a subclass requires updateLogicalState() even
* if it doesn't have any controls. Defaults to true thus implementing
@ -263,7 +209,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
localOverrides = new SafeArrayList<>(MatParamOverride.class);
worldOverrides = new SafeArrayList<>(MatParamOverride.class);
refreshFlagOr(RF_BOUND);
refreshFlags |= RF_BOUND;
}
public void setKey(AssetKey key) {
@ -326,35 +272,35 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
* a refresh is required.
*/
protected void setTransformRefresh() {
refreshFlagOr(RF_TRANSFORM);
refreshFlags |= RF_TRANSFORM;
setBoundRefresh();
}
protected void setLightListRefresh() {
refreshFlagOr(RF_LIGHTLIST);
refreshFlags |= RF_LIGHTLIST;
// Make sure next updateGeometricState() visits this branch
// to update lights.
Spatial p = parent;
while (p != null) {
if ((p.refreshFlagGetAnd(RF_CHILD_LIGHTLIST)) != 0) {
if ((p.refreshFlags & RF_CHILD_LIGHTLIST) != 0) {
// The parent already has this flag,
// so must all ancestors.
return;
}
p.refreshFlagOr(RF_CHILD_LIGHTLIST);
p.refreshFlags |= RF_CHILD_LIGHTLIST;
p = p.parent;
}
}
protected void setMatParamOverrideRefresh() {
refreshFlagOr(RF_MATPARAM_OVERRIDE);
refreshFlags |= RF_MATPARAM_OVERRIDE;
Spatial p = parent;
while (p != null) {
if ((p.refreshFlagGetAnd(RF_MATPARAM_OVERRIDE)) != 0) {
if ((p.refreshFlags & RF_MATPARAM_OVERRIDE) != 0) {
return;
}
p.refreshFlagOr(RF_MATPARAM_OVERRIDE);
p.refreshFlags |= RF_MATPARAM_OVERRIDE;
p = p.parent;
}
}
@ -364,15 +310,15 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
* a refresh is required.
*/
protected void setBoundRefresh() {
refreshFlagOr(RF_BOUND);
refreshFlags |= RF_BOUND;
Spatial p = parent;
while (p != null) {
if ((p.refreshFlagGetAnd(RF_BOUND)) != 0) {
if ((p.refreshFlags & RF_BOUND) != 0) {
return;
}
p.refreshFlagOr(RF_BOUND);
p.refreshFlags |= RF_BOUND;
p = p.parent;
}
}
@ -407,14 +353,11 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
* (should be rendered), false if outside.
*/
public boolean checkCulling(Camera cam) {
if (getRefreshFlags() != 0) {
/*
if (refreshFlags != 0) {
throw new IllegalStateException("Scene graph is not properly updated for rendering.\n"
+ "State was changed after rootNode.updateGeometricState() call. \n"
+ "Make sure you do not modify the scene from another thread!\n"
+ "Problem spatial name: " + getName()+", flags: "+getRefreshFlagsDescription());
*/
logger.warning("Invalid refresh flags for spatial " + getName()+", flags: "+getRefreshFlagsDescription());
+ "Problem spatial name: " + getName());
}
CullHint cm = getCullHint();
@ -628,28 +571,28 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
// for a node, the world bound is a combination of all it's children
// bounds
// -> handled by subclass
refreshFlagAnd(~RF_BOUND);
refreshFlags &= ~RF_BOUND;
}
protected void updateWorldLightList() {
if (parent == null) {
worldLights.update(localLights, null);
refreshFlagAnd(~RF_LIGHTLIST);
refreshFlags &= ~RF_LIGHTLIST;
} else {
assert (parent.refreshFlagGetAnd(RF_LIGHTLIST)) == 0;
assert (parent.refreshFlags & RF_LIGHTLIST) == 0;
worldLights.update(localLights, parent.worldLights);
refreshFlagAnd(~RF_LIGHTLIST);
refreshFlags &= ~RF_LIGHTLIST;
}
}
protected void updateMatParamOverrides() {
refreshFlagAnd(~RF_MATPARAM_OVERRIDE);
refreshFlags &= ~RF_MATPARAM_OVERRIDE;
worldOverrides.clear();
if (parent == null) {
worldOverrides.addAll(localOverrides);
} else {
assert (parent.refreshFlagGetAnd(RF_MATPARAM_OVERRIDE)) == 0;
assert (parent.refreshFlags & RF_MATPARAM_OVERRIDE) == 0;
worldOverrides.addAll(parent.worldOverrides);
worldOverrides.addAll(localOverrides);
}
@ -700,13 +643,13 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
protected void updateWorldTransforms() {
if (parent == null) {
worldTransform.set(localTransform);
refreshFlagAnd(~RF_TRANSFORM);
refreshFlags &= ~RF_TRANSFORM;
} else {
// check if transform for parent is updated
assert ((parent.refreshFlagGetAnd(RF_TRANSFORM)) == 0);
assert ((parent.refreshFlags & RF_TRANSFORM) == 0);
worldTransform.set(localTransform);
worldTransform.combineWithParent(parent.worldTransform);
refreshFlagAnd(~RF_TRANSFORM);
refreshFlags &= ~RF_TRANSFORM;
}
}
@ -715,13 +658,13 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
* efficient manner possible.
*/
void checkDoTransformUpdate() {
if ((refreshFlagGetAnd(RF_TRANSFORM)) == 0) {
if ((refreshFlags & RF_TRANSFORM) == 0) {
return;
}
if (parent == null) {
worldTransform.set(localTransform);
refreshFlagAnd(~RF_TRANSFORM);
refreshFlags &= ~RF_TRANSFORM;
} else {
TempVars vars = TempVars.get();
@ -732,14 +675,14 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
Spatial hisParent = rootNode.parent;
if (hisParent == null) {
rootNode.worldTransform.set(rootNode.localTransform);
rootNode.refreshFlagAnd(~RF_TRANSFORM);
rootNode.refreshFlags &= ~RF_TRANSFORM;
i--;
break;
}
stack[i] = rootNode;
if ((hisParent.refreshFlagGetAnd(RF_TRANSFORM)) == 0) {
if ((hisParent.refreshFlags & RF_TRANSFORM) == 0) {
break;
}
@ -764,7 +707,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
* manner possible.
*/
void checkDoBoundUpdate() {
if ((refreshFlagGetAnd(RF_BOUND)) == 0) {
if ((refreshFlags & RF_BOUND) == 0) {
return;
}
@ -954,20 +897,19 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
// NOTE: Update world transforms first because
// bound transform depends on them.
if ((refreshFlagGetAnd(RF_LIGHTLIST)) != 0) {
if ((refreshFlags & RF_LIGHTLIST) != 0) {
updateWorldLightList();
}
if ((refreshFlagGetAnd(RF_TRANSFORM)) != 0) {
if ((refreshFlags & RF_TRANSFORM) != 0) {
updateWorldTransforms();
}
if ((refreshFlagGetAnd(RF_BOUND)) != 0) {
if ((refreshFlags & RF_BOUND) != 0) {
updateWorldBound();
}
if ((refreshFlagGetAnd(RF_MATPARAM_OVERRIDE)) != 0) {
if ((refreshFlags & RF_MATPARAM_OVERRIDE) != 0) {
updateMatParamOverrides();
}
assert getRefreshFlags() == 0;
assert refreshFlags == 0;
}
/**
@ -1185,8 +1127,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
}
/**
* <code>addLight</code> adds the given light to the Spatial; causing
all
* <code>addLight</code> adds the given light to the Spatial; causing all
* child Spatials to be affected by it.
*
* @param light The light to add.
@ -1909,4 +1850,4 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
}
protected abstract void breadthFirstTraversal(SceneGraphVisitor visitor, Queue<Spatial> queue);
}
}

@ -73,7 +73,6 @@ public class SkeletonInterBoneWire extends Mesh {
}
this.setMode(Mode.Points);
this.setPointSize(1);
this.boneLengths = boneLengths;
VertexBuffer pb = new VertexBuffer(Type.Position);

@ -84,7 +84,6 @@ public class SkeletonPoints extends Mesh {
pb.setupData(Usage.Stream, 3, Format.Float, fpb);
this.setBuffer(pb);
this.setPointSize(7);
this.updateCounts();
}

@ -31,6 +31,7 @@
*/
package com.jme3.scene.instancing;
import com.jme3.bounding.BoundingVolume;
import com.jme3.export.InputCapsule;
import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
@ -309,6 +310,7 @@ public class InstancedGeometry extends Geometry {
} else {
// Deleting element in the middle
}
setBoundRefresh();
}
public void addInstance(Geometry geometry) {
@ -327,6 +329,31 @@ public class InstancedGeometry extends Geometry {
geometries[freeIndex] = geometry;
InstancedNode.setGeometryStartIndex2(geometry, freeIndex);
setBoundRefresh();
}
@Override
protected void updateWorldBound() {
refreshFlags &= ~RF_BOUND;
BoundingVolume resultBound = null;
for (int i = 0; i < firstUnusedIndex; i++) {
Geometry geom = geometries[i];
if (geom != null) {
if (resultBound != null) {
// merge current world bound with child world bound
resultBound.mergeLocal(geom.getWorldBound());
} else {
// set world bound to first non-null child world bound
if (geom.getWorldBound() != null) {
resultBound = geom.getWorldBound().clone(this.worldBound);
}
}
}
}
this.worldBound = resultBound;
}
public Geometry[] getGeometries() {

@ -982,7 +982,7 @@ public final class AppSettings extends HashMap<String, Object> {
* size window.
*/
public void setResizable(boolean resizable) {
putBoolean("Resizable", true);
putBoolean("Resizable", resizable);
}
/**

@ -5,6 +5,7 @@ MaterialDef Unshaded {
Texture2D LightMap
Color Color (Color)
Boolean VertexColor (UseVertexColor)
Float PointSize : 1.0
Boolean SeparateTexCoord
// Texture of the glowing parts of the material
@ -71,6 +72,7 @@ MaterialDef Unshaded {
HAS_COLORMAP : ColorMap
HAS_LIGHTMAP : LightMap
HAS_VERTEXCOLOR : VertexColor
HAS_POINTSIZE : PointSize
HAS_COLOR : Color
NUM_BONES : NumberOfBones
DISCARD_ALPHA : AlphaDiscardThreshold
@ -176,6 +178,7 @@ MaterialDef Unshaded {
HAS_GLOWCOLOR : GlowColor
NUM_BONES : NumberOfBones
INSTANCING : UseInstancing
HAS_POINTSIZE : PointSize
}
}
}

@ -16,6 +16,9 @@ varying vec2 texCoord1;
varying vec2 texCoord2;
varying vec4 vertColor;
#ifdef HAS_POINTSIZE
uniform float m_PointSize;
#endif
void main(){
#ifdef NEED_TEXCOORD1
@ -30,6 +33,10 @@ void main(){
vertColor = inColor;
#endif
#ifdef HAS_POINTSIZE
gl_PointSize = m_PointSize;
#endif
vec4 modelSpacePos = vec4(inPosition, 1.0);
#ifdef NUM_BONES
Skinning_Compute(modelSpacePos);

@ -38,15 +38,16 @@ uniform mat3 g_NormalMatrix;
// 2 vertex attributes which now can be used for additional per-vertex data.
attribute mat4 inInstanceData;
// Extract the world matrix out of the instance data, leaving out the
// quaternion at the end.
mat4 worldMatrix = mat4(vec4(inInstanceData[0].xyz, 0.0),
vec4(inInstanceData[1].xyz, 0.0),
vec4(inInstanceData[2].xyz, 0.0),
vec4(inInstanceData[3].xyz, 1.0));
vec4 TransformWorld(vec4 position)
{
// Extract the world matrix out of the instance data, leaving out the
// quaternion at the end.
mat4 worldMatrix = mat4(vec4(inInstanceData[0].xyz, 0.0),
vec4(inInstanceData[1].xyz, 0.0),
vec4(inInstanceData[2].xyz, 0.0),
vec4(inInstanceData[3].xyz, 1.0));
return (worldMatrix * position);
}

@ -46,7 +46,7 @@ void Skinning_Compute(inout vec4 position, inout vec3 normal){
}
}
void Skinning_Compute(inout vec4 position, inout vec3 tangent, inout vec3 normal){
void Skinning_Compute(inout vec4 position, inout vec3 normal, inout vec3 tangent){
if (inHWBoneWeight.x != 0.0) {
#if NUM_WEIGHTS_PER_VERT == 1
position = m_BoneMatrices[int(inHWBoneIndex.x)] * position;

@ -204,7 +204,7 @@ public class DDSLoader implements AssetLoader {
if (!directx10) {
if (!is(caps1, DDSCAPS_TEXTURE)) {
throw new IOException("File is not a texture");
logger.warning("Texture is missing the DDSCAPS_TEXTURE-flag");
}
if (depth <= 0) {

@ -98,7 +98,7 @@ public class TestSpotLightTerrain extends SimpleApplication {
ambLight.setColor(ColorRGBA.Black);
rootNode.addLight(ambLight);
cam.setLocation(new Vector3f(-41.219646f, -84.8363f, -171.67267f));
cam.setLocation(new Vector3f(-41.219646f, 0.8363f, -171.67267f));
cam.setRotation(new Quaternion(-0.04562731f, 0.89917684f, -0.09668826f, -0.4243236f));
sl.setDirection(cam.getDirection());
sl.setPosition(cam.getLocation());

@ -115,7 +115,8 @@ public class TestAnimBlendBug extends SimpleApplication implements ActionListene
SkeletonDebugger skeletonDebug = new SkeletonDebugger("skeleton1", control1.getSkeleton());
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.getAdditionalRenderState().setWireframe(true);
mat.setColor("Color", ColorRGBA.Green);
mat.setColor("Color", ColorRGBA.Red);
mat.setFloat("PointSize", 7f);
mat.getAdditionalRenderState().setDepthTest(false);
skeletonDebug.setMaterial(mat);
model1.attachChild(skeletonDebug);

@ -0,0 +1,127 @@
/*
* Copyright (c) 2009-2017 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jme3test.model.anim;
import com.jme3.animation.AnimChannel;
import com.jme3.animation.AnimControl;
import com.jme3.animation.AnimEventListener;
import com.jme3.animation.LoopMode;
import com.jme3.animation.SkeletonControl;
import com.jme3.app.SimpleApplication;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Box;
/**
* Simple application to an test attachments node on the Jaime model.
*
* Derived from {@link jme3test.model.anim.TestOgreAnim}.
*/
public class TestAttachmentsNode extends SimpleApplication
implements AnimEventListener, ActionListener {
public static void main(String[] args) {
TestAttachmentsNode app = new TestAttachmentsNode();
app.start();
}
private AnimChannel channel;
private AnimControl control;
@Override
public void simpleInitApp() {
flyCam.setMoveSpeed(10f);
cam.setLocation(new Vector3f(6.4f, 7.5f, 12.8f));
cam.setRotation(new Quaternion(-0.060740203f, 0.93925786f, -0.2398315f, -0.2378785f));
DirectionalLight dl = new DirectionalLight();
dl.setDirection(new Vector3f(-0.1f, -0.7f, -1).normalizeLocal());
dl.setColor(ColorRGBA.White);
rootNode.addLight(dl);
Spatial model = assetManager.loadModel("Models/Jaime/Jaime.j3o");
control = model.getControl(AnimControl.class);
SkeletonControl skeletonControl = model.getControl(SkeletonControl.class);
model.center();
model.setLocalScale(5f);
control.addListener(this);
channel = control.createChannel();
channel.setAnim("Idle");
Box box = new Box(0.3f, 0.02f, 0.02f);
Geometry saber = new Geometry("saber", box);
saber.move(0.4f, 0.05f, 0.01f);
Material red = assetManager.loadMaterial("Common/Materials/RedColor.j3m");
saber.setMaterial(red);
Node n = skeletonControl.getAttachmentsNode("hand.R");
n.attachChild(saber);
rootNode.attachChild(model);
inputManager.addListener(this, "Attack");
inputManager.addMapping("Attack", new KeyTrigger(KeyInput.KEY_SPACE));
}
@Override
public void onAnimCycleDone(AnimControl control, AnimChannel channel, String animName) {
if (animName.equals("Punches")) {
channel.setAnim("Idle", 0.5f);
channel.setLoopMode(LoopMode.DontLoop);
channel.setSpeed(1f);
}
}
@Override
public void onAnimChange(AnimControl control, AnimChannel channel, String animName) {
}
@Override
public void onAction(String binding, boolean value, float tpf) {
if (binding.equals("Attack") && value) {
if (!channel.getAnimationName().equals("Punches")) {
channel.setAnim("Punches", 0.5f);
channel.setLoopMode(LoopMode.Cycle);
channel.setSpeed(0.5f);
}
}
}
}

@ -106,6 +106,7 @@ public class TestOgreComplexAnim extends SimpleApplication {
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.getAdditionalRenderState().setWireframe(true);
mat.setColor("Color", ColorRGBA.Green);
mat.setFloat("PointSize", 7f);
mat.getAdditionalRenderState().setDepthTest(false);
skeletonDebug.setMaterial(mat);

@ -0,0 +1,62 @@
package jme3test.scene.instancing;
import com.jme3.app.SimpleApplication;
import com.jme3.light.PointLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.instancing.InstancedNode;
import com.jme3.scene.shape.Box;
public class TestInstanceNodeWithLight extends SimpleApplication {
// Try to test with different offset
private static float offset = 12;
public static void main(String[] args) {
TestInstanceNodeWithLight app = new TestInstanceNodeWithLight();
app.start();
}
Geometry box;
PointLight pointLight;
@Override
public void simpleInitApp() {
InstancedNode instancedNode = new InstancedNode("testInstancedNode");
rootNode.attachChild(instancedNode);
box = new Geometry("Box", new Box(0.5f, 0.5f, 0.5f));
Material material = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
material.setBoolean("UseInstancing", true);
material.setColor("Diffuse", ColorRGBA.Red);
material.setBoolean("UseMaterialColors", true);
box.setMaterial(material);
instancedNode.attachChild(box);
instancedNode.instance();
pointLight = new PointLight();
pointLight.setColor(ColorRGBA.White);
pointLight.setRadius(10f);
rootNode.addLight(pointLight);
box.setLocalTranslation(new Vector3f(offset, 0, 0));
pointLight.setPosition(new Vector3f(offset - 3f, 0, 0));
cam.setLocation(new Vector3f(offset - 5f, 0, 0));
cam.lookAtDirection(Vector3f.UNIT_X, Vector3f.UNIT_Y);
}
@Override
public void simpleUpdate(float tpf) {
offset += tpf;
System.err.println(offset);
box.setLocalTranslation(new Vector3f(offset, 0, 0));
pointLight.setPosition(new Vector3f(offset - 3f, 0, 0));
cam.setLocation(new Vector3f(offset - 5f, 0, 0));
cam.lookAtDirection(Vector3f.UNIT_X, Vector3f.UNIT_Y);
}
}

@ -238,17 +238,35 @@ public class GlfwMouseInput implements MouseInput {
return (long) (glfwGetTime() * 1000000000);
}
private long createGlfwCursor(JmeCursor jmeCursor) {
GLFWImage glfwImage = new GLFWImage(BufferUtils.createByteBuffer(GLFWImage.SIZEOF));
private ByteBuffer transformCursorImage(IntBuffer imageData, int w, int h) {
ByteBuffer buf = BufferUtils.createByteBuffer(imageData.capacity() * 4);
// Transform image: ARGB -> RGBA, vertical flip
for (int y = h-1; y >= 0; --y) {
for (int x = 0; x < w; ++x) {
int pixel = imageData.get(y*w + x);
buf.put((byte) ((pixel >> 16) & 0xFF)); // red
buf.put((byte) ((pixel >> 8) & 0xFF)); // green
buf.put((byte) ( pixel & 0xFF)); // blue
buf.put((byte) ((pixel >> 24) & 0xFF)); // alpha
}
}
buf.flip();
return buf;
}
private long createGlfwCursor(JmeCursor jmeCursor) {
// TODO: currently animated cursors are not supported
IntBuffer imageData = jmeCursor.getImagesData();
ByteBuffer buf = BufferUtils.createByteBuffer(imageData.capacity() * 4);
buf.asIntBuffer().put(imageData);
ByteBuffer buf = transformCursorImage(imageData, jmeCursor.getWidth(), jmeCursor.getHeight());
GLFWImage glfwImage = new GLFWImage(BufferUtils.createByteBuffer(GLFWImage.SIZEOF));
glfwImage.set(jmeCursor.getWidth(), jmeCursor.getHeight(), buf);
return glfwCreateCursor(glfwImage, jmeCursor.getXHotSpot(), jmeCursor.getYHotSpot());
int hotspotX = jmeCursor.getXHotSpot();
int hotspotY = jmeCursor.getHeight() - jmeCursor.getYHotSpot();
return glfwCreateCursor(glfwImage, hotspotX, hotspotY);
}
public void setNativeCursor(JmeCursor jmeCursor) {

@ -2,8 +2,12 @@ package com.jme3.util;
import org.lwjgl.system.MemoryUtil;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.nio.*;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;
/**
* The implementation of the {@link BufferAllocator} which use {@link MemoryUtil} to manage memory.
@ -12,13 +16,130 @@ import java.nio.ByteBuffer;
*/
public class LWJGLBufferAllocator implements BufferAllocator {
private static final Logger LOGGER = Logger.getLogger(LWJGLBufferAllocator.class.getName());
/**
* The reference queue.
*/
private static final ReferenceQueue<Buffer> DUMMY_QUEUE = new ReferenceQueue<Buffer>();
/**
* The LWJGL byte buffer deallocator.
*/
private static class Deallocator extends PhantomReference<ByteBuffer> {
/**
* The address of LWJGL byte buffer.
*/
private volatile Long address;
Deallocator(final ByteBuffer referent, final ReferenceQueue<? super ByteBuffer> queue, final Long address) {
super(referent, queue);
this.address = address;
}
/**
* @param address the address of LWJGL byte buffer.
*/
void setAddress(final Long address) {
this.address = address;
}
/**
* Free memory.
*/
void free() {
if (address == null) return;
MemoryUtil.nmemFree(address);
DEALLOCATORS.remove(address);
}
}
/**
* The cleaner thread.
*/
private static final Thread CLEAN_THREAD = new Thread(LWJGLBufferAllocator::freeByteBuffers);
/**
* The map with created deallocators.
*/
private static final Map<Long, Deallocator> DEALLOCATORS = new ConcurrentHashMap<>();
static {
CLEAN_THREAD.setDaemon(true);
CLEAN_THREAD.setName("Thread to free LWJGL byte buffers");
CLEAN_THREAD.start();
}
/**
* Free unnecessary LWJGL byte buffers.
*/
private static void freeByteBuffers() {
try {
for (; ; ) {
final Deallocator deallocator = (Deallocator) DUMMY_QUEUE.remove();
deallocator.free();
}
} catch (final InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void destroyDirectBuffer(final Buffer buffer) {
final long address = getAddress(buffer);
if (address == -1) {
LOGGER.warning("Not found address of the " + buffer);
return;
}
// disable deallocator
final Deallocator deallocator = DEALLOCATORS.remove(address);
if (deallocator == null) {
LOGGER.warning("Not found a deallocator for address " + address);
return;
}
deallocator.setAddress(null);
MemoryUtil.memFree(buffer);
}
/**
* Get memory address of the buffer.
*
* @param buffer the buffer.
* @return the address or -1.
*/
private long getAddress(final Buffer buffer) {
if (buffer instanceof ByteBuffer) {
return MemoryUtil.memAddress((ByteBuffer) buffer, 0);
} else if (buffer instanceof ShortBuffer) {
return MemoryUtil.memAddress((ShortBuffer) buffer, 0);
} else if (buffer instanceof CharBuffer) {
return MemoryUtil.memAddress((CharBuffer) buffer, 0);
} else if (buffer instanceof IntBuffer) {
return MemoryUtil.memAddress((IntBuffer) buffer, 0);
} else if (buffer instanceof FloatBuffer) {
return MemoryUtil.memAddress((FloatBuffer) buffer, 0);
} else if (buffer instanceof LongBuffer) {
return MemoryUtil.memAddress((LongBuffer) buffer, 0);
} else if (buffer instanceof DoubleBuffer) {
return MemoryUtil.memAddress((DoubleBuffer) buffer, 0);
}
return -1;
}
@Override
public ByteBuffer allocate(final int size) {
return MemoryUtil.memAlloc(size);
final Long address = MemoryUtil.nmemAlloc(size);
final ByteBuffer byteBuffer = MemoryUtil.memByteBuffer(address, size);
DEALLOCATORS.put(address, new Deallocator(byteBuffer, DUMMY_QUEUE, address));
return byteBuffer;
}
}

@ -303,22 +303,29 @@ public class TerrainPatch extends Geometry {
protected void setHeight(List<LocationHeight> locationHeights, boolean overrideHeight) {
final float[] heightArray = geomap.getHeightArray();
final VertexBuffer vertexBuffer = mesh.getBuffer(Type.Position);
final FloatBuffer floatBuffer = mesh.getFloatBuffer(Type.Position);
for (LocationHeight lh : locationHeights) {
if (lh.x < 0 || lh.z < 0 || lh.x >= size || lh.z >= size)
if (lh.x < 0 || lh.z < 0 || lh.x >= size || lh.z >= size) {
continue;
}
int idx = lh.z * size + lh.x;
if (overrideHeight) {
geomap.getHeightArray()[idx] = lh.h;
heightArray[idx] = lh.h;
} else {
float h = getMesh().getFloatBuffer(Type.Position).get(idx*3+1);
geomap.getHeightArray()[idx] = h+lh.h;
float currentHeight = floatBuffer.get(idx * 3 + 1);
heightArray[idx] = currentHeight + lh.h;
}
}
FloatBuffer newVertexBuffer = geomap.writeVertexArray(null, stepScale, false);
getMesh().clearBuffer(Type.Position);
getMesh().setBuffer(Type.Position, 3, newVertexBuffer);
floatBuffer.clear();
geomap.writeVertexArray(floatBuffer, stepScale, false);
vertexBuffer.setUpdateNeeded();
}
/**

@ -150,6 +150,7 @@ varying vec2 texCoord;
vec4 calculateDiffuseBlend(in vec2 texCoord) {
vec4 alphaBlend = texture2D( m_AlphaMap, texCoord.xy );
vec4 diffuseColor = vec4(1.0);
#ifdef ALPHAMAP_1
vec4 alphaBlend1 = texture2D( m_AlphaMap_1, texCoord.xy );
@ -157,9 +158,10 @@ varying vec2 texCoord;
#ifdef ALPHAMAP_2
vec4 alphaBlend2 = texture2D( m_AlphaMap_2, texCoord.xy );
#endif
vec4 diffuseColor = texture2D(m_DiffuseMap, texCoord * m_DiffuseMap_0_scale);
diffuseColor *= alphaBlend.r;
#ifdef DIFFUSEMAP
diffuseColor = texture2D(m_DiffuseMap, texCoord * m_DiffuseMap_0_scale);
diffuseColor *= alphaBlend.r;
#endif
#ifdef DIFFUSEMAP_1
vec4 diffuseColor1 = texture2D(m_DiffuseMap_1, texCoord * m_DiffuseMap_1_scale);
diffuseColor = mix( diffuseColor, diffuseColor1, alphaBlend.g );

@ -151,6 +151,7 @@ varying vec3 lightVec;
vec4 calculateDiffuseBlend(in vec2 texCoord) {
vec4 alphaBlend = texture2D( m_AlphaMap, texCoord.xy );
vec4 diffuseColor = vec4(1.0);
#ifdef ALPHAMAP_1
vec4 alphaBlend1 = texture2D( m_AlphaMap_1, texCoord.xy );
@ -158,9 +159,10 @@ varying vec3 lightVec;
#ifdef ALPHAMAP_2
vec4 alphaBlend2 = texture2D( m_AlphaMap_2, texCoord.xy );
#endif
vec4 diffuseColor = texture2D(m_DiffuseMap, texCoord * m_DiffuseMap_0_scale);
diffuseColor *= alphaBlend.r;
#ifdef DIFFUSEMAP
diffuseColor = texture2D(m_DiffuseMap, texCoord * m_DiffuseMap_0_scale);
diffuseColor *= alphaBlend.r;
#endif
#ifdef DIFFUSEMAP_1
vec4 diffuseColor1 = texture2D(m_DiffuseMap_1, texCoord * m_DiffuseMap_1_scale);
diffuseColor = mix( diffuseColor, diffuseColor1, alphaBlend.g );

@ -272,29 +272,7 @@ MaterialDef Terrain Lighting {
}
Technique GBuf {
VertexShader GLSL100: Common/MatDefs/Light/GBuf.vert
FragmentShader GLSL100: Common/MatDefs/Light/GBuf.frag
WorldParameters {
WorldViewProjectionMatrix
WorldMatrix
}
Defines {
VERTEX_COLOR : UseVertexColor
MATERIAL_COLORS : UseMaterialColors
V_TANGENT : VTangent
MINNAERT : Minnaert
WARDISO : WardIso
DIFFUSEMAP : DiffuseMap
NORMALMAP : NormalMap
SPECULARMAP : SpecularMap
PARALLAXMAP : ParallaxMap
}
}
Technique Glow {

Loading…
Cancel
Save