Merge pull request #1 from jMonkeyEngine/master
update to jMonkeyEngine master
This commit is contained in:
commit
e67cb0b0a9
1
.gitignore
vendored
1
.gitignore
vendored
@ -43,3 +43,4 @@
|
|||||||
!/jme3-vr/src/main/resources/**/*.so.dbg
|
!/jme3-vr/src/main/resources/**/*.so.dbg
|
||||||
!/jme3-vr/src/main/resources/**/*.dll
|
!/jme3-vr/src/main/resources/**/*.dll
|
||||||
!/jme3-vr/src/main/resources/**/*.pdb
|
!/jme3-vr/src/main/resources/**/*.pdb
|
||||||
|
/buildMaven.bat
|
||||||
|
|||||||
@ -529,24 +529,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
|
|||||||
checkSetParam(type, name);
|
checkSetParam(type, name);
|
||||||
MatParamTexture val = getTextureParam(name);
|
MatParamTexture val = getTextureParam(name);
|
||||||
if (val == null) {
|
if (val == null) {
|
||||||
MatParamTexture paramDef = (MatParamTexture) def.getMaterialParam(name);
|
checkTextureParamColorSpace(name, value);
|
||||||
if (paramDef.getColorSpace() != null && paramDef.getColorSpace() != value.getImage().getColorSpace()) {
|
|
||||||
value.getImage().setColorSpace(paramDef.getColorSpace());
|
|
||||||
logger.log(Level.FINE, "Material parameter {0} needs a {1} texture, "
|
|
||||||
+ "texture {2} was switched to {3} color space.",
|
|
||||||
new Object[]{name, paramDef.getColorSpace().toString(),
|
|
||||||
value.getName(),
|
|
||||||
value.getImage().getColorSpace().name()});
|
|
||||||
} else if (paramDef.getColorSpace() == null && value.getName() != null && value.getImage().getColorSpace() == ColorSpace.Linear) {
|
|
||||||
logger.log(Level.WARNING,
|
|
||||||
"The texture {0} has linear color space, but the material "
|
|
||||||
+ "parameter {2} specifies no color space requirement, this may "
|
|
||||||
+ "lead to unexpected behavior.\nCheck if the image "
|
|
||||||
+ "was not set to another material parameter with a linear "
|
|
||||||
+ "color space, or that you did not set the ColorSpace to "
|
|
||||||
+ "Linear using texture.getImage.setColorSpace().",
|
|
||||||
new Object[]{value.getName(), value.getImage().getColorSpace().name(), name});
|
|
||||||
}
|
|
||||||
paramValues.put(name, new MatParamTexture(type, name, value, null));
|
paramValues.put(name, new MatParamTexture(type, name, value, null));
|
||||||
} else {
|
} else {
|
||||||
val.setTextureValue(value);
|
val.setTextureValue(value);
|
||||||
@ -560,6 +543,27 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
|
|||||||
sortingId = -1;
|
sortingId = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkTextureParamColorSpace(String name, Texture value) {
|
||||||
|
MatParamTexture paramDef = (MatParamTexture) def.getMaterialParam(name);
|
||||||
|
if (paramDef.getColorSpace() != null && paramDef.getColorSpace() != value.getImage().getColorSpace()) {
|
||||||
|
value.getImage().setColorSpace(paramDef.getColorSpace());
|
||||||
|
logger.log(Level.FINE, "Material parameter {0} needs a {1} texture, "
|
||||||
|
+ "texture {2} was switched to {3} color space.",
|
||||||
|
new Object[]{name, paramDef.getColorSpace().toString(),
|
||||||
|
value.getName(),
|
||||||
|
value.getImage().getColorSpace().name()});
|
||||||
|
} else if (paramDef.getColorSpace() == null && value.getName() != null && value.getImage().getColorSpace() == ColorSpace.Linear) {
|
||||||
|
logger.log(Level.WARNING,
|
||||||
|
"The texture {0} has linear color space, but the material "
|
||||||
|
+ "parameter {2} specifies no color space requirement, this may "
|
||||||
|
+ "lead to unexpected behavior.\nCheck if the image "
|
||||||
|
+ "was not set to another material parameter with a linear "
|
||||||
|
+ "color space, or that you did not set the ColorSpace to "
|
||||||
|
+ "Linear using texture.getImage.setColorSpace().",
|
||||||
|
new Object[]{value.getName(), value.getImage().getColorSpace().name(), name});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pass a texture to the material shader.
|
* Pass a texture to the material shader.
|
||||||
*
|
*
|
||||||
@ -1062,6 +1066,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
|
|||||||
if (texVal.getTextureValue() == null || texVal.getTextureValue().getImage() == null) {
|
if (texVal.getTextureValue() == null || texVal.getTextureValue().getImage() == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
checkTextureParamColorSpace(texVal.getName(), texVal.getTextureValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (im.getFormatVersion() == 0 && param.getName().startsWith("m_")) {
|
if (im.getFormatVersion() == 0 && param.getName().startsWith("m_")) {
|
||||||
|
|||||||
@ -506,6 +506,7 @@ public class Geometry extends Spatial {
|
|||||||
/**
|
/**
|
||||||
* The old clone() method that did not use the new Cloner utility.
|
* The old clone() method that did not use the new Cloner utility.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public Geometry oldClone(boolean cloneMaterial) {
|
public Geometry oldClone(boolean cloneMaterial) {
|
||||||
Geometry geomClone = (Geometry) super.clone(cloneMaterial);
|
Geometry geomClone = (Geometry) super.clone(cloneMaterial);
|
||||||
|
|
||||||
|
|||||||
@ -63,8 +63,7 @@ import java.util.ArrayList;
|
|||||||
* All visible elements in a scene are represented by meshes.
|
* All visible elements in a scene are represented by meshes.
|
||||||
* Meshes may contain three types of geometric primitives:
|
* Meshes may contain three types of geometric primitives:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>Points - Every vertex represents a single point in space,
|
* <li>Points - Every vertex represents a single point in space.
|
||||||
* the size of each point is specified via {@link Mesh#setPointSize(float) }.
|
|
||||||
* Points can also be used for {@link RenderState#setPointSprite(boolean) point
|
* Points can also be used for {@link RenderState#setPointSprite(boolean) point
|
||||||
* sprite} mode.</li>
|
* sprite} mode.</li>
|
||||||
* <li>Lines - 2 vertices represent a line segment, with the width specified
|
* <li>Lines - 2 vertices represent a line segment, with the width specified
|
||||||
@ -82,8 +81,8 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
|
|||||||
*/
|
*/
|
||||||
public enum Mode {
|
public enum Mode {
|
||||||
/**
|
/**
|
||||||
* A primitive is a single point in space. The size of the points
|
* A primitive is a single point in space. The size of {@link Mode#Points points} are
|
||||||
* can be specified with {@link Mesh#setPointSize(float) }.
|
* determined via the vertex shader's <code>gl_PointSize</code> output.
|
||||||
*/
|
*/
|
||||||
Points(true),
|
Points(true),
|
||||||
|
|
||||||
|
|||||||
@ -121,17 +121,23 @@ public class LodControl extends AbstractControl implements Cloneable, JmeCloneab
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSpatial(Spatial spatial) {
|
public void setSpatial(Spatial spatial) {
|
||||||
if (!(spatial instanceof Geometry)) {
|
if (spatial != null && !(spatial instanceof Geometry)) {
|
||||||
throw new IllegalArgumentException("LodControl can only be attached to Geometry!");
|
throw new IllegalArgumentException("LodControl can only be attached to Geometry!");
|
||||||
}
|
}
|
||||||
|
|
||||||
super.setSpatial(spatial);
|
super.setSpatial(spatial);
|
||||||
Geometry geom = (Geometry) spatial;
|
|
||||||
Mesh mesh = geom.getMesh();
|
if(spatial != null) {
|
||||||
numLevels = mesh.getNumLodLevels();
|
Geometry geom = (Geometry) spatial;
|
||||||
numTris = new int[numLevels];
|
Mesh mesh = geom.getMesh();
|
||||||
for (int i = numLevels - 1; i >= 0; i--) {
|
numLevels = mesh.getNumLodLevels();
|
||||||
numTris[i] = mesh.getTriangleCount(i);
|
numTris = new int[numLevels];
|
||||||
|
for (int i = numLevels - 1; i >= 0; i--) {
|
||||||
|
numTris[i] = mesh.getTriangleCount(i);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
numLevels = 0;
|
||||||
|
numTris = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -31,12 +31,13 @@
|
|||||||
*/
|
*/
|
||||||
package com.jme3.scene.debug;
|
package com.jme3.scene.debug;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import com.jme3.animation.Skeleton;
|
import com.jme3.animation.Skeleton;
|
||||||
import com.jme3.renderer.queue.RenderQueue.Bucket;
|
import com.jme3.renderer.queue.RenderQueue.Bucket;
|
||||||
import com.jme3.scene.Geometry;
|
import com.jme3.scene.Geometry;
|
||||||
import com.jme3.scene.Node;
|
import com.jme3.scene.Node;
|
||||||
|
import com.jme3.util.clone.Cloner;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The class that creates a mesh to display how bones behave.
|
* The class that creates a mesh to display how bones behave.
|
||||||
@ -122,4 +123,13 @@ public class SkeletonDebugger extends Node {
|
|||||||
public SkeletonInterBoneWire getInterBoneWires() {
|
public SkeletonInterBoneWire getInterBoneWires() {
|
||||||
return interBoneWires;
|
return interBoneWires;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cloneFields(Cloner cloner, Object original) {
|
||||||
|
super.cloneFields(cloner, original);
|
||||||
|
|
||||||
|
this.wires = cloner.clone(wires);
|
||||||
|
this.points = cloner.clone(points);
|
||||||
|
this.interBoneWires = cloner.clone(interBoneWires);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -40,11 +40,8 @@ import com.jme3.math.FastMath;
|
|||||||
import com.jme3.math.Vector3f;
|
import com.jme3.math.Vector3f;
|
||||||
import com.jme3.scene.Mesh;
|
import com.jme3.scene.Mesh;
|
||||||
import com.jme3.scene.VertexBuffer.Type;
|
import com.jme3.scene.VertexBuffer.Type;
|
||||||
import com.jme3.scene.mesh.IndexBuffer;
|
|
||||||
import com.jme3.util.BufferUtils;
|
import com.jme3.util.BufferUtils;
|
||||||
import static com.jme3.util.BufferUtils.*;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.FloatBuffer;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple cylinder, defined by it's height and radius.
|
* A simple cylinder, defined by it's height and radius.
|
||||||
@ -127,10 +124,10 @@ public class Cylinder extends Mesh {
|
|||||||
* mapped to texture coordinates (0.5, 1), bottom to (0.5, 0). Thus you need
|
* mapped to texture coordinates (0.5, 1), bottom to (0.5, 0). Thus you need
|
||||||
* a suited distorted texture.
|
* a suited distorted texture.
|
||||||
*
|
*
|
||||||
* @param axisSamples
|
* @param axisSamples The number of vertices samples along the axis. It is equal to the number of segments + 1; so
|
||||||
* Number of triangle samples along the axis.
|
* that, for instance, 4 samples mean the cylinder will be made of 3 segments.
|
||||||
* @param radialSamples
|
* @param radialSamples The number of triangle samples along the radius. For instance, 4 means that the sides of the
|
||||||
* Number of triangle samples along the radial.
|
* cylinder are made of 4 rectangles, and the top and bottom are made of 4 triangles.
|
||||||
* @param radius
|
* @param radius
|
||||||
* The radius of the cylinder.
|
* The radius of the cylinder.
|
||||||
* @param height
|
* @param height
|
||||||
@ -201,194 +198,225 @@ public class Cylinder extends Mesh {
|
|||||||
/**
|
/**
|
||||||
* Rebuilds the cylinder based on a new set of parameters.
|
* Rebuilds the cylinder based on a new set of parameters.
|
||||||
*
|
*
|
||||||
* @param axisSamples the number of samples along the axis.
|
* @param axisSamples The number of vertices samples along the axis. It is equal to the number of segments + 1; so
|
||||||
* @param radialSamples the number of samples around the radial.
|
* that, for instance, 4 samples mean the cylinder will be made of 3 segments.
|
||||||
* @param radius the radius of the bottom of the cylinder.
|
* @param radialSamples The number of triangle samples along the radius. For instance, 4 means that the sides of the
|
||||||
* @param radius2 the radius of the top of the cylinder.
|
* cylinder are made of 4 rectangles, and the top and bottom are made of 4 triangles.
|
||||||
|
* @param topRadius the radius of the top of the cylinder.
|
||||||
|
* @param bottomRadius the radius of the bottom of the cylinder.
|
||||||
* @param height the cylinder's height.
|
* @param height the cylinder's height.
|
||||||
* @param closed should the cylinder have top and bottom surfaces.
|
* @param closed should the cylinder have top and bottom surfaces.
|
||||||
* @param inverted is the cylinder is meant to be viewed from the inside.
|
* @param inverted is the cylinder is meant to be viewed from the inside.
|
||||||
*/
|
*/
|
||||||
public void updateGeometry(int axisSamples, int radialSamples,
|
public void updateGeometry(int axisSamples, int radialSamples,
|
||||||
float radius, float radius2, float height, boolean closed, boolean inverted) {
|
float topRadius, float bottomRadius, float height, boolean closed, boolean inverted) {
|
||||||
|
// Ensure there's at least two axis samples and 3 radial samples, and positive dimensions.
|
||||||
|
if( axisSamples < 2
|
||||||
|
|| radialSamples < 3
|
||||||
|
|| topRadius <= 0
|
||||||
|
|| bottomRadius <= 0
|
||||||
|
|| height <= 0 ) {
|
||||||
|
throw new IllegalArgumentException("Cylinders must have at least 2 axis samples and 3 radial samples, and positive dimensions.");
|
||||||
|
}
|
||||||
|
|
||||||
this.axisSamples = axisSamples;
|
this.axisSamples = axisSamples;
|
||||||
this.radialSamples = radialSamples;
|
this.radialSamples = radialSamples;
|
||||||
this.radius = radius;
|
this.radius = bottomRadius;
|
||||||
this.radius2 = radius2;
|
this.radius2 = topRadius;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
this.closed = closed;
|
this.closed = closed;
|
||||||
this.inverted = inverted;
|
this.inverted = inverted;
|
||||||
|
|
||||||
// VertexBuffer pvb = getBuffer(Type.Position);
|
// Vertices : One per radial sample plus one duplicate for texture closing around the sides.
|
||||||
// VertexBuffer nvb = getBuffer(Type.Normal);
|
int verticesCount = axisSamples * (radialSamples +1);
|
||||||
// VertexBuffer tvb = getBuffer(Type.TexCoord);
|
// Triangles: Two per side rectangle, which is the product of numbers of samples.
|
||||||
axisSamples += (closed ? 2 : 0);
|
int trianglesCount = axisSamples * radialSamples * 2 ;
|
||||||
|
if( closed ) {
|
||||||
|
// If there are caps, add two additional rims and two summits.
|
||||||
|
verticesCount += 2 + 2 * (radialSamples +1);
|
||||||
|
// Add one triangle per radial sample, twice, to form the caps.
|
||||||
|
trianglesCount += 2 * radialSamples ;
|
||||||
|
}
|
||||||
|
|
||||||
// Vertices
|
// Compute the points along a unit circle:
|
||||||
int vertCount = axisSamples * (radialSamples + 1) + (closed ? 2 : 0);
|
float[][] circlePoints = new float[radialSamples+1][2];
|
||||||
|
for (int circlePoint = 0; circlePoint < radialSamples; circlePoint++) {
|
||||||
setBuffer(Type.Position, 3, createVector3Buffer(getFloatBuffer(Type.Position), vertCount));
|
float angle = FastMath.TWO_PI / radialSamples * circlePoint;
|
||||||
|
circlePoints[circlePoint][0] = FastMath.cos(angle);
|
||||||
// Normals
|
circlePoints[circlePoint][1] = FastMath.sin(angle);
|
||||||
setBuffer(Type.Normal, 3, createVector3Buffer(getFloatBuffer(Type.Normal), vertCount));
|
}
|
||||||
|
// Add an additional point for closing the texture around the side of the cylinder.
|
||||||
// Texture co-ordinates
|
circlePoints[radialSamples][0] = circlePoints[0][0];
|
||||||
setBuffer(Type.TexCoord, 2, createVector2Buffer(vertCount));
|
circlePoints[radialSamples][1] = circlePoints[0][1];
|
||||||
|
|
||||||
int triCount = ((closed ? 2 : 0) + 2 * (axisSamples - 1)) * radialSamples;
|
|
||||||
|
|
||||||
setBuffer(Type.Index, 3, createShortBuffer(getShortBuffer(Type.Index), 3 * triCount));
|
// Calculate normals.
|
||||||
|
//
|
||||||
// generate geometry
|
// A---------B
|
||||||
float inverseRadial = 1.0f / radialSamples;
|
// \ |
|
||||||
float inverseAxisLess = 1.0f / (closed ? axisSamples - 3 : axisSamples - 1);
|
// \ |
|
||||||
float inverseAxisLessTexture = 1.0f / (axisSamples - 1);
|
// \ |
|
||||||
float halfHeight = 0.5f * height;
|
// D-----C
|
||||||
|
//
|
||||||
// Generate points on the unit circle to be used in computing the mesh
|
// Let be B and C the top and bottom points of the axis, and A and D the top and bottom edges.
|
||||||
// points on a cylinder slice.
|
// The normal in A and D is simply orthogonal to AD, which means we can get it once per sample.
|
||||||
float[] sin = new float[radialSamples + 1];
|
//
|
||||||
float[] cos = new float[radialSamples + 1];
|
Vector3f[] circleNormals = new Vector3f[radialSamples+1];
|
||||||
|
for (int circlePoint = 0; circlePoint < radialSamples+1; circlePoint++) {
|
||||||
for (int radialCount = 0; radialCount < radialSamples; radialCount++) {
|
// The normal is the orthogonal to the side, which can be got without trigonometry.
|
||||||
float angle = FastMath.TWO_PI * inverseRadial * radialCount;
|
// The edge direction is oriented so that it goes up by Height, and out by the radius difference; let's use
|
||||||
cos[radialCount] = FastMath.cos(angle);
|
// those values in reverse order.
|
||||||
sin[radialCount] = FastMath.sin(angle);
|
Vector3f normal = new Vector3f(height * circlePoints[circlePoint][0], height * circlePoints[circlePoint][1], bottomRadius - topRadius );
|
||||||
}
|
circleNormals[circlePoint] = normal.normalizeLocal();
|
||||||
sin[radialSamples] = sin[0];
|
|
||||||
cos[radialSamples] = cos[0];
|
|
||||||
|
|
||||||
// calculate normals
|
|
||||||
Vector3f[] vNormals = null;
|
|
||||||
Vector3f vNormal = Vector3f.UNIT_Z;
|
|
||||||
|
|
||||||
if ((height != 0.0f) && (radius != radius2)) {
|
|
||||||
vNormals = new Vector3f[radialSamples];
|
|
||||||
Vector3f vHeight = Vector3f.UNIT_Z.mult(height);
|
|
||||||
Vector3f vRadial = new Vector3f();
|
|
||||||
|
|
||||||
for (int radialCount = 0; radialCount < radialSamples; radialCount++) {
|
|
||||||
vRadial.set(cos[radialCount], sin[radialCount], 0.0f);
|
|
||||||
Vector3f vRadius = vRadial.mult(radius);
|
|
||||||
Vector3f vRadius2 = vRadial.mult(radius2);
|
|
||||||
Vector3f vMantle = vHeight.subtract(vRadius2.subtract(vRadius));
|
|
||||||
Vector3f vTangent = vRadial.cross(Vector3f.UNIT_Z);
|
|
||||||
vNormals[radialCount] = vMantle.cross(vTangent).normalize();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FloatBuffer nb = getFloatBuffer(Type.Normal);
|
float[] vertices = new float[verticesCount * 3];
|
||||||
FloatBuffer pb = getFloatBuffer(Type.Position);
|
float[] normals = new float[verticesCount * 3];
|
||||||
FloatBuffer tb = getFloatBuffer(Type.TexCoord);
|
float[] textureCoords = new float[verticesCount * 2];
|
||||||
|
int currentIndex = 0;
|
||||||
// generate the cylinder itself
|
|
||||||
Vector3f tempNormal = new Vector3f();
|
// Add a circle of points for each axis sample.
|
||||||
for (int axisCount = 0, i = 0; axisCount < axisSamples; axisCount++, i++) {
|
for(int axisSample = 0; axisSample < axisSamples; axisSample++ ) {
|
||||||
float axisFraction;
|
float currentHeight = -height / 2 + height * axisSample / (axisSamples-1);
|
||||||
float axisFractionTexture;
|
float currentRadius = bottomRadius + (topRadius - bottomRadius) * axisSample / (axisSamples-1);
|
||||||
int topBottom = 0;
|
|
||||||
if (!closed) {
|
for (int circlePoint = 0; circlePoint < radialSamples + 1; circlePoint++) {
|
||||||
axisFraction = axisCount * inverseAxisLess; // in [0,1]
|
// Position, by multipliying the position on a unit circle with the current radius.
|
||||||
axisFractionTexture = axisFraction;
|
vertices[currentIndex*3] = circlePoints[circlePoint][0] * currentRadius;
|
||||||
} else {
|
vertices[currentIndex*3 +1] = circlePoints[circlePoint][1] * currentRadius;
|
||||||
if (axisCount == 0) {
|
vertices[currentIndex*3 +2] = currentHeight;
|
||||||
topBottom = -1; // bottom
|
|
||||||
axisFraction = 0;
|
// Normal
|
||||||
axisFractionTexture = inverseAxisLessTexture;
|
Vector3f currentNormal = circleNormals[circlePoint];
|
||||||
} else if (axisCount == axisSamples - 1) {
|
normals[currentIndex*3] = currentNormal.x;
|
||||||
topBottom = 1; // top
|
normals[currentIndex*3+1] = currentNormal.y;
|
||||||
axisFraction = 1;
|
normals[currentIndex*3+2] = currentNormal.z;
|
||||||
axisFractionTexture = 1 - inverseAxisLessTexture;
|
|
||||||
} else {
|
// Texture
|
||||||
axisFraction = (axisCount - 1) * inverseAxisLess;
|
// The X is the angular position of the point.
|
||||||
axisFractionTexture = axisCount * inverseAxisLessTexture;
|
textureCoords[currentIndex *2] = (float) circlePoint / radialSamples;
|
||||||
}
|
// Depending on whether there is a cap, the Y is either the height scaled to [0,1], or the radii of
|
||||||
|
// the cap count as well.
|
||||||
|
if (closed)
|
||||||
|
textureCoords[currentIndex *2 +1] = (bottomRadius + height / 2 + currentHeight) / (bottomRadius + height + topRadius);
|
||||||
|
else
|
||||||
|
textureCoords[currentIndex *2 +1] = height / 2 + currentHeight;
|
||||||
|
|
||||||
|
currentIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute center of slice
|
|
||||||
float z = -halfHeight + height * axisFraction;
|
|
||||||
Vector3f sliceCenter = new Vector3f(0, 0, z);
|
|
||||||
|
|
||||||
// compute slice vertices with duplication at end point
|
|
||||||
int save = i;
|
|
||||||
for (int radialCount = 0; radialCount < radialSamples; radialCount++, i++) {
|
|
||||||
float radialFraction = radialCount * inverseRadial; // in [0,1)
|
|
||||||
tempNormal.set(cos[radialCount], sin[radialCount], 0.0f);
|
|
||||||
|
|
||||||
if (vNormals != null) {
|
|
||||||
vNormal = vNormals[radialCount];
|
|
||||||
} else if (radius == radius2) {
|
|
||||||
vNormal = tempNormal;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (topBottom == 0) {
|
|
||||||
if (!inverted)
|
|
||||||
nb.put(vNormal.x).put(vNormal.y).put(vNormal.z);
|
|
||||||
else
|
|
||||||
nb.put(-vNormal.x).put(-vNormal.y).put(-vNormal.z);
|
|
||||||
} else {
|
|
||||||
nb.put(0).put(0).put(topBottom * (inverted ? -1 : 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
tempNormal.multLocal((radius - radius2) * axisFraction + radius2)
|
|
||||||
.addLocal(sliceCenter);
|
|
||||||
pb.put(tempNormal.x).put(tempNormal.y).put(tempNormal.z);
|
|
||||||
|
|
||||||
tb.put((inverted ? 1 - radialFraction : radialFraction))
|
|
||||||
.put(axisFractionTexture);
|
|
||||||
}
|
|
||||||
|
|
||||||
BufferUtils.copyInternalVector3(pb, save, i);
|
|
||||||
BufferUtils.copyInternalVector3(nb, save, i);
|
|
||||||
|
|
||||||
tb.put((inverted ? 0.0f : 1.0f))
|
|
||||||
.put(axisFractionTexture);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If closed, add duplicate rims on top and bottom, with normals facing up and down.
|
||||||
if (closed) {
|
if (closed) {
|
||||||
pb.put(0).put(0).put(-halfHeight); // bottom center
|
// Bottom
|
||||||
nb.put(0).put(0).put(-1 * (inverted ? -1 : 1));
|
for (int circlePoint = 0; circlePoint < radialSamples + 1; circlePoint++) {
|
||||||
tb.put(0.5f).put(0);
|
vertices[currentIndex*3] = circlePoints[circlePoint][0] * bottomRadius;
|
||||||
pb.put(0).put(0).put(halfHeight); // top center
|
vertices[currentIndex*3 +1] = circlePoints[circlePoint][1] * bottomRadius;
|
||||||
nb.put(0).put(0).put(1 * (inverted ? -1 : 1));
|
vertices[currentIndex*3 +2] = -height/2;
|
||||||
tb.put(0.5f).put(1);
|
|
||||||
|
normals[currentIndex*3] = 0;
|
||||||
|
normals[currentIndex*3+1] = 0;
|
||||||
|
normals[currentIndex*3+2] = -1;
|
||||||
|
|
||||||
|
textureCoords[currentIndex *2] = (float) circlePoint / radialSamples;
|
||||||
|
textureCoords[currentIndex *2 +1] = bottomRadius / (bottomRadius + height + topRadius);
|
||||||
|
|
||||||
|
currentIndex++;
|
||||||
|
}
|
||||||
|
// Top
|
||||||
|
for (int circlePoint = 0; circlePoint < radialSamples + 1; circlePoint++) {
|
||||||
|
vertices[currentIndex*3] = circlePoints[circlePoint][0] * topRadius;
|
||||||
|
vertices[currentIndex*3 +1] = circlePoints[circlePoint][1] * topRadius;
|
||||||
|
vertices[currentIndex*3 +2] = height/2;
|
||||||
|
|
||||||
|
normals[currentIndex*3] = 0;
|
||||||
|
normals[currentIndex*3+1] = 0;
|
||||||
|
normals[currentIndex*3+2] = 1;
|
||||||
|
|
||||||
|
textureCoords[currentIndex *2] = (float) circlePoint / radialSamples;
|
||||||
|
textureCoords[currentIndex *2 +1] = (bottomRadius + height) / (bottomRadius + height + topRadius);
|
||||||
|
|
||||||
|
currentIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the centers of the caps.
|
||||||
|
vertices[currentIndex*3] = 0;
|
||||||
|
vertices[currentIndex*3 +1] = 0;
|
||||||
|
vertices[currentIndex*3 +2] = -height/2;
|
||||||
|
|
||||||
|
normals[currentIndex*3] = 0;
|
||||||
|
normals[currentIndex*3+1] = 0;
|
||||||
|
normals[currentIndex*3+2] = -1;
|
||||||
|
|
||||||
|
textureCoords[currentIndex *2] = 0.5f;
|
||||||
|
textureCoords[currentIndex *2+1] = 0f;
|
||||||
|
|
||||||
|
currentIndex++;
|
||||||
|
|
||||||
|
vertices[currentIndex*3] = 0;
|
||||||
|
vertices[currentIndex*3 +1] = 0;
|
||||||
|
vertices[currentIndex*3 +2] = height/2;
|
||||||
|
|
||||||
|
normals[currentIndex*3] = 0;
|
||||||
|
normals[currentIndex*3+1] = 0;
|
||||||
|
normals[currentIndex*3+2] = 1;
|
||||||
|
|
||||||
|
textureCoords[currentIndex *2] = 0.5f;
|
||||||
|
textureCoords[currentIndex *2+1] = 1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
IndexBuffer ib = getIndexBuffer();
|
// Add the triangles indexes.
|
||||||
int index = 0;
|
short[] indices = new short[trianglesCount * 3];
|
||||||
// Connectivity
|
currentIndex = 0;
|
||||||
for (int axisCount = 0, axisStart = 0; axisCount < axisSamples - 1; axisCount++) {
|
for (short axisSample = 0; axisSample < axisSamples - 1; axisSample++) {
|
||||||
int i0 = axisStart;
|
for (int circlePoint = 0; circlePoint < radialSamples; circlePoint++) {
|
||||||
int i1 = i0 + 1;
|
indices[currentIndex++] = (short) (axisSample * (radialSamples + 1) + circlePoint);
|
||||||
axisStart += radialSamples + 1;
|
indices[currentIndex++] = (short) (axisSample * (radialSamples + 1) + circlePoint + 1);
|
||||||
int i2 = axisStart;
|
indices[currentIndex++] = (short) ((axisSample + 1) * (radialSamples + 1) + circlePoint);
|
||||||
int i3 = i2 + 1;
|
|
||||||
for (int i = 0; i < radialSamples; i++) {
|
indices[currentIndex++] = (short) ((axisSample + 1) * (radialSamples + 1) + circlePoint);
|
||||||
if (closed && axisCount == 0) {
|
indices[currentIndex++] = (short) (axisSample * (radialSamples + 1) + circlePoint + 1);
|
||||||
if (!inverted) {
|
indices[currentIndex++] = (short) ((axisSample + 1) * (radialSamples + 1) + circlePoint + 1);
|
||||||
ib.put(index++, i0++);
|
}
|
||||||
ib.put(index++, vertCount - 2);
|
}
|
||||||
ib.put(index++, i1++);
|
// Add caps if needed.
|
||||||
} else {
|
if(closed) {
|
||||||
ib.put(index++, i0++);
|
short bottomCapIndex = (short) (verticesCount - 2);
|
||||||
ib.put(index++, i1++);
|
short topCapIndex = (short) (verticesCount - 1);
|
||||||
ib.put(index++, vertCount - 2);
|
|
||||||
}
|
int bottomRowOffset = (axisSamples) * (radialSamples +1 );
|
||||||
} else if (closed && axisCount == axisSamples - 2) {
|
int topRowOffset = (axisSamples+1) * (radialSamples +1 );
|
||||||
ib.put(index++, i2++);
|
|
||||||
ib.put(index++, inverted ? vertCount - 1 : i3++);
|
for (int circlePoint = 0; circlePoint < radialSamples; circlePoint++) {
|
||||||
ib.put(index++, inverted ? i3++ : vertCount - 1);
|
indices[currentIndex++] = (short) (bottomRowOffset + circlePoint +1);
|
||||||
} else {
|
indices[currentIndex++] = (short) (bottomRowOffset + circlePoint);
|
||||||
ib.put(index++, i0++);
|
indices[currentIndex++] = bottomCapIndex;
|
||||||
ib.put(index++, inverted ? i2 : i1);
|
|
||||||
ib.put(index++, inverted ? i1 : i2);
|
|
||||||
ib.put(index++, i1++);
|
indices[currentIndex++] = (short) (topRowOffset + circlePoint);
|
||||||
ib.put(index++, inverted ? i2++ : i3++);
|
indices[currentIndex++] = (short) (topRowOffset + circlePoint +1);
|
||||||
ib.put(index++, inverted ? i3++ : i2++);
|
indices[currentIndex++] = topCapIndex;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If inverted, the triangles and normals are all reverted.
|
||||||
|
if (inverted) {
|
||||||
|
for (int i = 0; i < indices.length / 2; i++) {
|
||||||
|
short temp = indices[i];
|
||||||
|
indices[i] = indices[indices.length - 1 - i];
|
||||||
|
indices[indices.length - 1 - i] = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i< normals.length; i++) {
|
||||||
|
normals[i] = -normals[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill in the buffers.
|
||||||
|
setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(vertices));
|
||||||
|
setBuffer(Type.Normal, 3, BufferUtils.createFloatBuffer(normals));
|
||||||
|
setBuffer(Type.TexCoord, 2, BufferUtils.createFloatBuffer(textureCoords));
|
||||||
|
setBuffer(Type.Index, 3, BufferUtils.createShortBuffer(indices));
|
||||||
|
|
||||||
updateBound();
|
updateBound();
|
||||||
setStatic();
|
setStatic();
|
||||||
}
|
}
|
||||||
@ -418,6 +446,4 @@ public class Cylinder extends Mesh {
|
|||||||
capsule.write(closed, "closed", false);
|
capsule.write(closed, "closed", false);
|
||||||
capsule.write(inverted, "inverted", false);
|
capsule.write(inverted, "inverted", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -243,7 +243,7 @@ public class Glsl100ShaderGenerator extends ShaderGenerator {
|
|||||||
//all variables fed with a matparam or world param are replaced but the matparam itself
|
//all variables fed with a matparam or world param are replaced but the matparam itself
|
||||||
//it avoids issue with samplers that have to be uniforms, and it optimize a but the shader code.
|
//it avoids issue with samplers that have to be uniforms, and it optimize a but the shader code.
|
||||||
if (isWorldOrMaterialParam(mapping.getRightVariable())) {
|
if (isWorldOrMaterialParam(mapping.getRightVariable())) {
|
||||||
nodeSource = replace(nodeSource, mapping.getLeftVariable(), mapping.getRightVariable().getName());
|
nodeSource = replace(nodeSource, mapping.getLeftVariable(), mapping.getRightVariable().getPrefix() + mapping.getRightVariable().getName());
|
||||||
} else {
|
} else {
|
||||||
if (mapping.getLeftVariable().getType().startsWith("sampler")) {
|
if (mapping.getLeftVariable().getType().startsWith("sampler")) {
|
||||||
throw new IllegalArgumentException("a Sampler must be a uniform");
|
throw new IllegalArgumentException("a Sampler must be a uniform");
|
||||||
@ -338,6 +338,7 @@ public class Glsl100ShaderGenerator extends ShaderGenerator {
|
|||||||
source.append(var.getNameSpace());
|
source.append(var.getNameSpace());
|
||||||
source.append("_");
|
source.append("_");
|
||||||
}
|
}
|
||||||
|
source.append(var.getPrefix());
|
||||||
source.append(var.getName());
|
source.append(var.getName());
|
||||||
if (var.getMultiplicity() != null) {
|
if (var.getMultiplicity() != null) {
|
||||||
source.append("[");
|
source.append("[");
|
||||||
|
|||||||
@ -45,6 +45,7 @@ import java.io.IOException;
|
|||||||
*/
|
*/
|
||||||
public class ShaderNodeVariable implements Savable, Cloneable {
|
public class ShaderNodeVariable implements Savable, Cloneable {
|
||||||
|
|
||||||
|
private String prefix = "";
|
||||||
private String name;
|
private String name;
|
||||||
private String type;
|
private String type;
|
||||||
private String nameSpace;
|
private String nameSpace;
|
||||||
@ -62,8 +63,7 @@ public class ShaderNodeVariable implements Savable, Cloneable {
|
|||||||
this.name = name;
|
this.name = name;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* creates a ShaderNodeVariable
|
* creates a ShaderNodeVariable
|
||||||
*
|
*
|
||||||
@ -80,6 +80,22 @@ public class ShaderNodeVariable implements Savable, Cloneable {
|
|||||||
this.multiplicity = multiplicity;
|
this.multiplicity = multiplicity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* creates a ShaderNodeVariable
|
||||||
|
*
|
||||||
|
* @param type the glsl type of the variable
|
||||||
|
* @param nameSpace the nameSpace (can be the name of the shaderNode or
|
||||||
|
* Global,Attr,MatParam,WorldParam)
|
||||||
|
* @param name the name of the variable
|
||||||
|
* @param multiplicity the number of element if this variable is an array. Can be an Int of a declared material parameter
|
||||||
|
* @param prefix the variable prefix to append at generation times. This is mostly to add the g_ and m_ for uniforms
|
||||||
|
*/
|
||||||
|
public ShaderNodeVariable(String type, String nameSpace, String name, String multiplicity, String prefix) {
|
||||||
|
this(type, nameSpace, name, multiplicity);
|
||||||
|
this.prefix = prefix;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* creates a ShaderNodeVariable
|
* creates a ShaderNodeVariable
|
||||||
*
|
*
|
||||||
@ -138,6 +154,22 @@ public class ShaderNodeVariable implements Savable, Cloneable {
|
|||||||
return nameSpace;
|
return nameSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the variable prefix
|
||||||
|
*/
|
||||||
|
public String getPrefix() {
|
||||||
|
return prefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the variable prefix (m_ or g_)
|
||||||
|
*
|
||||||
|
* @param prefix
|
||||||
|
*/
|
||||||
|
public void setPrefix(String prefix) {
|
||||||
|
this.prefix = prefix;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sets the nameSpace (can be the name of the shaderNode or
|
* sets the nameSpace (can be the name of the shaderNode or
|
||||||
* Global,Attr,MatParam,WorldParam)
|
* Global,Attr,MatParam,WorldParam)
|
||||||
@ -153,6 +185,7 @@ public class ShaderNodeVariable implements Savable, Cloneable {
|
|||||||
int hash = 7;
|
int hash = 7;
|
||||||
hash = 29 * hash + (name != null?name.hashCode():0);
|
hash = 29 * hash + (name != null?name.hashCode():0);
|
||||||
hash = 29 * hash + (type != null?type.hashCode():0);
|
hash = 29 * hash + (type != null?type.hashCode():0);
|
||||||
|
hash = 29 * hash + (prefix != null ? prefix.hashCode() : 0);
|
||||||
hash = 29 * hash + (nameSpace != null?nameSpace.hashCode():0);
|
hash = 29 * hash + (nameSpace != null?nameSpace.hashCode():0);
|
||||||
hash = 29 * hash + (condition != null?condition.hashCode():0);
|
hash = 29 * hash + (condition != null?condition.hashCode():0);
|
||||||
hash = 29 * hash + (multiplicity != null?multiplicity.hashCode():0);
|
hash = 29 * hash + (multiplicity != null?multiplicity.hashCode():0);
|
||||||
@ -174,6 +207,9 @@ public class ShaderNodeVariable implements Savable, Cloneable {
|
|||||||
if ((this.type == null) ? (other.type != null) : !this.type.equals(other.type)) {
|
if ((this.type == null) ? (other.type != null) : !this.type.equals(other.type)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if ((this.prefix == null) ? (other.prefix != null) : !this.prefix.equals(other.prefix)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if ((this.nameSpace == null) ? (other.nameSpace != null) : !this.nameSpace.equals(other.nameSpace)) {
|
if ((this.nameSpace == null) ? (other.nameSpace != null) : !this.nameSpace.equals(other.nameSpace)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -197,6 +233,7 @@ public class ShaderNodeVariable implements Savable, Cloneable {
|
|||||||
OutputCapsule oc = (OutputCapsule) ex.getCapsule(this);
|
OutputCapsule oc = (OutputCapsule) ex.getCapsule(this);
|
||||||
oc.write(name, "name", "");
|
oc.write(name, "name", "");
|
||||||
oc.write(type, "type", "");
|
oc.write(type, "type", "");
|
||||||
|
oc.write(prefix, "prefix", "");
|
||||||
oc.write(nameSpace, "nameSpace", "");
|
oc.write(nameSpace, "nameSpace", "");
|
||||||
oc.write(condition, "condition", null);
|
oc.write(condition, "condition", null);
|
||||||
oc.write(shaderOutput, "shaderOutput", false);
|
oc.write(shaderOutput, "shaderOutput", false);
|
||||||
@ -215,6 +252,7 @@ public class ShaderNodeVariable implements Savable, Cloneable {
|
|||||||
InputCapsule ic = (InputCapsule) im.getCapsule(this);
|
InputCapsule ic = (InputCapsule) im.getCapsule(this);
|
||||||
name = ic.readString("name", "");
|
name = ic.readString("name", "");
|
||||||
type = ic.readString("type", "");
|
type = ic.readString("type", "");
|
||||||
|
prefix = ic.readString("pefix", "");
|
||||||
nameSpace = ic.readString("nameSpace", "");
|
nameSpace = ic.readString("nameSpace", "");
|
||||||
condition = ic.readString("condition", null);
|
condition = ic.readString("condition", null);
|
||||||
shaderOutput = ic.readBoolean("shaderOutput", false);
|
shaderOutput = ic.readBoolean("shaderOutput", false);
|
||||||
|
|||||||
@ -193,6 +193,7 @@ public class ShaderNodeLoaderDelegate {
|
|||||||
shaderNodeDefinition = new ShaderNodeDefinition();
|
shaderNodeDefinition = new ShaderNodeDefinition();
|
||||||
getNodeDefinitions().put(name, shaderNodeDefinition);
|
getNodeDefinitions().put(name, shaderNodeDefinition);
|
||||||
shaderNodeDefinition.setName(name);
|
shaderNodeDefinition.setName(name);
|
||||||
|
shaderNodeDefinition.setPath(key.getName());
|
||||||
readShaderNodeDefinition(statement.getContents(), key);
|
readShaderNodeDefinition(statement.getContents(), key);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -231,40 +232,52 @@ public class ShaderNodeLoaderDelegate {
|
|||||||
protected void readShaderNodeDefinition(List<Statement> statements, ShaderNodeDefinitionKey key) throws IOException {
|
protected void readShaderNodeDefinition(List<Statement> statements, ShaderNodeDefinitionKey key) throws IOException {
|
||||||
boolean isLoadDoc = key instanceof ShaderNodeDefinitionKey && ((ShaderNodeDefinitionKey) key).isLoadDocumentation();
|
boolean isLoadDoc = key instanceof ShaderNodeDefinitionKey && ((ShaderNodeDefinitionKey) key).isLoadDocumentation();
|
||||||
for (Statement statement : statements) {
|
for (Statement statement : statements) {
|
||||||
String[] split = statement.getLine().split("[ \\{]");
|
try {
|
||||||
String line = statement.getLine();
|
String[] split = statement.getLine().split("[ \\{]");
|
||||||
|
String line = statement.getLine();
|
||||||
|
|
||||||
if (line.startsWith("Type")) {
|
if (line.startsWith("Type")) {
|
||||||
String type = line.substring(line.lastIndexOf(':') + 1).trim();
|
String type = line.substring(line.lastIndexOf(':') + 1).trim();
|
||||||
shaderNodeDefinition.setType(Shader.ShaderType.valueOf(type));
|
shaderNodeDefinition.setType(Shader.ShaderType.valueOf(type));
|
||||||
} else if (line.startsWith("Shader ")) {
|
} else if (line.startsWith("Shader ")) {
|
||||||
readShaderStatement(statement);
|
readShaderStatement(statement);
|
||||||
shaderNodeDefinition.getShadersLanguage().add(shaderLanguage);
|
shaderNodeDefinition.getShadersLanguage().add(shaderLanguage);
|
||||||
shaderNodeDefinition.getShadersPath().add(shaderName);
|
shaderNodeDefinition.getShadersPath().add(shaderName);
|
||||||
} else if (line.startsWith("Documentation")) {
|
} else if (line.startsWith("Documentation")) {
|
||||||
if (isLoadDoc) {
|
if (isLoadDoc) {
|
||||||
String doc = "";
|
String doc = "";
|
||||||
|
for (Statement statement1 : statement.getContents()) {
|
||||||
|
doc += "\n" + statement1.getLine();
|
||||||
|
}
|
||||||
|
shaderNodeDefinition.setDocumentation(doc);
|
||||||
|
}
|
||||||
|
} else if (line.startsWith("Input")) {
|
||||||
|
varNames = "";
|
||||||
for (Statement statement1 : statement.getContents()) {
|
for (Statement statement1 : statement.getContents()) {
|
||||||
doc += "\n" + statement1.getLine();
|
try {
|
||||||
|
shaderNodeDefinition.getInputs().add(readVariable(statement1));
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
throw new MatParseException(e.getMessage(), statement1, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
shaderNodeDefinition.setDocumentation(doc);
|
} else if (line.startsWith("Output")) {
|
||||||
}
|
varNames = "";
|
||||||
} else if (line.startsWith("Input")) {
|
for (Statement statement1 : statement.getContents()) {
|
||||||
varNames = "";
|
try {
|
||||||
for (Statement statement1 : statement.getContents()) {
|
if (statement1.getLine().trim().equals("None")) {
|
||||||
shaderNodeDefinition.getInputs().add(readVariable(statement1));
|
shaderNodeDefinition.setNoOutput(true);
|
||||||
}
|
} else {
|
||||||
} else if (line.startsWith("Output")) {
|
shaderNodeDefinition.getOutputs().add(readVariable(statement1));
|
||||||
varNames = "";
|
}
|
||||||
for (Statement statement1 : statement.getContents()) {
|
} catch (RuntimeException e) {
|
||||||
if(statement1.getLine().trim().equals("None")){
|
throw new MatParseException(e.getMessage(), statement1, e);
|
||||||
shaderNodeDefinition.setNoOutput(true);
|
}
|
||||||
}else{
|
|
||||||
shaderNodeDefinition.getOutputs().add(readVariable(statement1));
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
throw new MatParseException("one of Type, Shader, Documentation, Input, Output", split[0], statement);
|
||||||
}
|
}
|
||||||
} else {
|
} catch (RuntimeException e) {
|
||||||
throw new MatParseException("one of Type, Shader, Documentation, Input, Output", split[0], statement);
|
throw new MatParseException(e.getMessage(), statement, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -279,6 +292,9 @@ public class ShaderNodeLoaderDelegate {
|
|||||||
protected ShaderNodeVariable readVariable(Statement statement) throws IOException {
|
protected ShaderNodeVariable readVariable(Statement statement) throws IOException {
|
||||||
String line = statement.getLine().trim().replaceAll("\\s*\\[", "[");
|
String line = statement.getLine().trim().replaceAll("\\s*\\[", "[");
|
||||||
String[] splitVar = line.split("\\s");
|
String[] splitVar = line.split("\\s");
|
||||||
|
if (splitVar.length != 2) {
|
||||||
|
throw new MatParseException("2 arguments", splitVar.length + "", statement);
|
||||||
|
}
|
||||||
String varName = splitVar[1];
|
String varName = splitVar[1];
|
||||||
String varType = splitVar[0];
|
String varType = splitVar[0];
|
||||||
String multiplicity = null;
|
String multiplicity = null;
|
||||||
@ -541,11 +557,13 @@ public class ShaderNodeLoaderDelegate {
|
|||||||
*/
|
*/
|
||||||
protected boolean updateRightFromUniforms(UniformBinding param, VariableMapping mapping, Map<String, DeclaredVariable> map) {
|
protected boolean updateRightFromUniforms(UniformBinding param, VariableMapping mapping, Map<String, DeclaredVariable> map) {
|
||||||
ShaderNodeVariable right = mapping.getRightVariable();
|
ShaderNodeVariable right = mapping.getRightVariable();
|
||||||
String name = "g_" + param.toString();
|
String name = param.toString();
|
||||||
|
|
||||||
DeclaredVariable dv = map.get(name);
|
DeclaredVariable dv = map.get(name);
|
||||||
if (dv == null) {
|
if (dv == null) {
|
||||||
right.setType(param.getGlslType());
|
right.setType(param.getGlslType());
|
||||||
right.setName(name);
|
right.setName(name);
|
||||||
|
right.setPrefix("g_");
|
||||||
dv = new DeclaredVariable(right);
|
dv = new DeclaredVariable(right);
|
||||||
map.put(right.getName(), dv);
|
map.put(right.getName(), dv);
|
||||||
dv.addNode(shaderNode);
|
dv.addNode(shaderNode);
|
||||||
@ -569,10 +587,11 @@ public class ShaderNodeLoaderDelegate {
|
|||||||
*/
|
*/
|
||||||
public boolean updateRightFromUniforms(MatParam param, VariableMapping mapping, Map<String, DeclaredVariable> map, Statement statement) throws MatParseException {
|
public boolean updateRightFromUniforms(MatParam param, VariableMapping mapping, Map<String, DeclaredVariable> map, Statement statement) throws MatParseException {
|
||||||
ShaderNodeVariable right = mapping.getRightVariable();
|
ShaderNodeVariable right = mapping.getRightVariable();
|
||||||
DeclaredVariable dv = map.get(param.getPrefixedName());
|
DeclaredVariable dv = map.get(param.getName());
|
||||||
if (dv == null) {
|
if (dv == null) {
|
||||||
right.setType(param.getVarType().getGlslType());
|
right.setType(param.getVarType().getGlslType());
|
||||||
right.setName(param.getPrefixedName());
|
right.setName(param.getName());
|
||||||
|
right.setPrefix("m_");
|
||||||
if(mapping.getLeftVariable().getMultiplicity() != null){
|
if(mapping.getLeftVariable().getMultiplicity() != null){
|
||||||
if(!param.getVarType().name().endsWith("Array")){
|
if(!param.getVarType().name().endsWith("Array")){
|
||||||
throw new MatParseException(param.getName() + " is not of Array type", statement);
|
throw new MatParseException(param.getName() + " is not of Array type", statement);
|
||||||
@ -942,7 +961,6 @@ public class ShaderNodeLoaderDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (ShaderNodeDefinition definition : defs) {
|
for (ShaderNodeDefinition definition : defs) {
|
||||||
definition.setPath(defLine[2].trim());
|
|
||||||
if (defName.equals(definition.getName())) {
|
if (defName.equals(definition.getName())) {
|
||||||
def = definition;
|
def = definition;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -302,6 +302,12 @@ public class DDSLoader implements AssetLoader {
|
|||||||
bpp = 64;
|
bpp = 64;
|
||||||
pixelFormat = Image.Format.RGBA16F;
|
pixelFormat = Image.Format.RGBA16F;
|
||||||
break;
|
break;
|
||||||
|
case 111:
|
||||||
|
compressed = false;
|
||||||
|
bpp = 16;
|
||||||
|
pixelFormat = Format.Luminance16F;
|
||||||
|
grayscaleOrAlpha = true;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IOException("Unknown fourcc: " + string(fourcc) + ", " + Integer.toHexString(fourcc));
|
throw new IOException("Unknown fourcc: " + string(fourcc) + ", " + Integer.toHexString(fourcc));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.jme3.scene;
|
||||||
|
|
||||||
|
import com.jme3.collision.CollisionResults;
|
||||||
|
import com.jme3.math.FastMath;
|
||||||
|
import com.jme3.math.Ray;
|
||||||
|
import com.jme3.math.Vector3f;
|
||||||
|
import com.jme3.scene.shape.Cylinder;
|
||||||
|
import java.util.Random;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensures that geometries behave correctly, by casting rays and ensure they don't break.
|
||||||
|
*
|
||||||
|
* @author Christophe Carpentier
|
||||||
|
*/
|
||||||
|
public class ShapeGeometryTest {
|
||||||
|
|
||||||
|
protected static final int NUMBER_OF_TRIES = 1000;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCylinders() {
|
||||||
|
Random random = new Random();
|
||||||
|
|
||||||
|
// Create a cylinder, cast a random ray, and ensure everything goes well.
|
||||||
|
Node scene = new Node("Scene Node");
|
||||||
|
|
||||||
|
for (int i = 0; i < NUMBER_OF_TRIES; i++) {
|
||||||
|
scene.detachAllChildren();
|
||||||
|
|
||||||
|
Cylinder cylinder = new Cylinder(2, 8, 1, 1, true);
|
||||||
|
Geometry geometry = new Geometry("cylinder", cylinder);
|
||||||
|
geometry.rotate(FastMath.HALF_PI, 0, 0);
|
||||||
|
scene.attachChild(geometry);
|
||||||
|
|
||||||
|
// Cast a random ray, and count successes and IndexOutOfBoundsExceptions.
|
||||||
|
Vector3f randomPoint = new Vector3f(random.nextFloat(), random.nextFloat(), random.nextFloat());
|
||||||
|
Vector3f randomDirection = new Vector3f(random.nextFloat(), random.nextFloat(), random.nextFloat());
|
||||||
|
randomDirection.normalizeLocal();
|
||||||
|
|
||||||
|
Ray ray = new Ray(randomPoint, randomDirection);
|
||||||
|
CollisionResults collisionResults = new CollisionResults();
|
||||||
|
|
||||||
|
// If the geometry is invalid, this should throw various exceptions.
|
||||||
|
scene.collideWith(ray, collisionResults);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -254,6 +254,16 @@ public class LodGenerator {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a LodGenerator for the given mesh
|
||||||
|
*
|
||||||
|
* @param mesh the mesh to consider to generate de Lods.
|
||||||
|
*/
|
||||||
|
public LodGenerator(Mesh mesh) {
|
||||||
|
this.mesh = mesh;
|
||||||
|
build();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a LodGenerator for the given geometry
|
* Construct a LodGenerator for the given geometry
|
||||||
*
|
*
|
||||||
|
|||||||
@ -52,7 +52,7 @@ import java.util.ArrayList;
|
|||||||
* There are 2 mode : Scene and Objects.<br>
|
* There are 2 mode : Scene and Objects.<br>
|
||||||
* Scene mode extracts the bright parts of the scene to make them glow<br>
|
* Scene mode extracts the bright parts of the scene to make them glow<br>
|
||||||
* Object mode make objects glow according to their material's glowMap or their GlowColor<br>
|
* Object mode make objects glow according to their material's glowMap or their GlowColor<br>
|
||||||
* @see <a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:bloom_and_glow">advanced:bloom_and_glow</a> for more details
|
* @see <a href="http://jmonkeyengine.github.io/wiki/jme3/advanced/bloom_and_glow.html">advanced:bloom_and_glow</a> for more details
|
||||||
*
|
*
|
||||||
* @author Rémy Bouquet aka Nehon
|
* @author Rémy Bouquet aka Nehon
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -31,10 +31,9 @@ public class TestShaderNodes extends SimpleApplication {
|
|||||||
mat.selectTechnique(TechniqueDef.DEFAULT_TECHNIQUE_NAME, renderManager);
|
mat.selectTechnique(TechniqueDef.DEFAULT_TECHNIQUE_NAME, renderManager);
|
||||||
Technique t = mat.getActiveTechnique();
|
Technique t = mat.getActiveTechnique();
|
||||||
|
|
||||||
// for (Shader.ShaderSource shaderSource : t.getShader().getSources()) {
|
for (Shader.ShaderSource shaderSource : t.getDef().getShader(assetManager, renderer.getCaps(), t.getDynamicDefines()).getSources()) {
|
||||||
// System.out.println(shaderSource.getSource());
|
System.out.println(shaderSource.getSource());
|
||||||
// }
|
}
|
||||||
|
|
||||||
|
|
||||||
mat.setColor("Color", ColorRGBA.Yellow);
|
mat.setColor("Color", ColorRGBA.Yellow);
|
||||||
mat.setTexture("ColorMap", tex);
|
mat.setTexture("ColorMap", tex);
|
||||||
|
|||||||
@ -241,7 +241,7 @@ public class VRAppState extends AbstractAppState {
|
|||||||
return application.getViewPort();
|
return application.getViewPort();
|
||||||
}
|
}
|
||||||
|
|
||||||
return environment.getVRViewManager().getLeftViewport();
|
return environment.getVRViewManager().getLeftViewPort();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -253,7 +253,7 @@ public class VRAppState extends AbstractAppState {
|
|||||||
if( environment.getVRViewManager() == null ){
|
if( environment.getVRViewManager() == null ){
|
||||||
return application.getViewPort();
|
return application.getViewPort();
|
||||||
}
|
}
|
||||||
return environment.getVRViewManager().getRightViewport();
|
return environment.getVRViewManager().getRightViewPort();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -263,12 +263,12 @@ public class VRAppState extends AbstractAppState {
|
|||||||
public void setBackgroundColors(ColorRGBA clr) {
|
public void setBackgroundColors(ColorRGBA clr) {
|
||||||
if( environment.getVRViewManager() == null ) {
|
if( environment.getVRViewManager() == null ) {
|
||||||
application.getViewPort().setBackgroundColor(clr);
|
application.getViewPort().setBackgroundColor(clr);
|
||||||
} else if( environment.getVRViewManager().getLeftViewport() != null ) {
|
} else if( environment.getVRViewManager().getLeftViewPort() != null ) {
|
||||||
|
|
||||||
environment.getVRViewManager().getLeftViewport().setBackgroundColor(clr);
|
environment.getVRViewManager().getLeftViewPort().setBackgroundColor(clr);
|
||||||
|
|
||||||
if( environment.getVRViewManager().getRightViewport() != null ){
|
if( environment.getVRViewManager().getRightViewPort() != null ){
|
||||||
environment.getVRViewManager().getRightViewport().setBackgroundColor(clr);
|
environment.getVRViewManager().getRightViewPort().setBackgroundColor(clr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -254,7 +254,7 @@ public abstract class VRApplication implements Application, SystemListener {
|
|||||||
dummyCam = new Camera();
|
dummyCam = new Camera();
|
||||||
|
|
||||||
initStateManager();
|
initStateManager();
|
||||||
|
|
||||||
// Create the GUI manager.
|
// Create the GUI manager.
|
||||||
guiManager = new VRGuiManager(null);
|
guiManager = new VRGuiManager(null);
|
||||||
|
|
||||||
@ -1085,7 +1085,7 @@ public abstract class VRApplication implements Application, SystemListener {
|
|||||||
*/
|
*/
|
||||||
public ViewPort getLeftViewPort() {
|
public ViewPort getLeftViewPort() {
|
||||||
if( viewmanager == null ) return getViewPort();
|
if( viewmanager == null ) return getViewPort();
|
||||||
return viewmanager.getLeftViewport();
|
return viewmanager.getLeftViewPort();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1095,7 +1095,7 @@ public abstract class VRApplication implements Application, SystemListener {
|
|||||||
*/
|
*/
|
||||||
public ViewPort getRightViewPort() {
|
public ViewPort getRightViewPort() {
|
||||||
if( viewmanager == null ) return getViewPort();
|
if( viewmanager == null ) return getViewPort();
|
||||||
return viewmanager.getRightViewport();
|
return viewmanager.getRightViewPort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1106,9 +1106,9 @@ public abstract class VRApplication implements Application, SystemListener {
|
|||||||
public void setBackgroundColors(ColorRGBA clr) {
|
public void setBackgroundColors(ColorRGBA clr) {
|
||||||
if( viewmanager == null ) {
|
if( viewmanager == null ) {
|
||||||
getViewPort().setBackgroundColor(clr);
|
getViewPort().setBackgroundColor(clr);
|
||||||
} else if( viewmanager.getLeftViewport() != null ) {
|
} else if( viewmanager.getLeftViewPort() != null ) {
|
||||||
viewmanager.getLeftViewport().setBackgroundColor(clr);
|
viewmanager.getLeftViewPort().setBackgroundColor(clr);
|
||||||
if( viewmanager.getRightViewport() != null ) viewmanager.getRightViewport().setBackgroundColor(clr);
|
if( viewmanager.getRightViewPort() != null ) viewmanager.getRightViewPort().setBackgroundColor(clr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import com.jme3.app.state.AppState;
|
|||||||
import com.jme3.input.vr.OSVR;
|
import com.jme3.input.vr.OSVR;
|
||||||
import com.jme3.input.vr.OpenVR;
|
import com.jme3.input.vr.OpenVR;
|
||||||
import com.jme3.input.vr.VRAPI;
|
import com.jme3.input.vr.VRAPI;
|
||||||
|
import com.jme3.input.vr.VRBounds;
|
||||||
import com.jme3.input.vr.VRInputAPI;
|
import com.jme3.input.vr.VRInputAPI;
|
||||||
import com.jme3.renderer.Camera;
|
import com.jme3.renderer.Camera;
|
||||||
import com.jme3.scene.Spatial;
|
import com.jme3.scene.Spatial;
|
||||||
@ -28,6 +29,8 @@ public class VREnvironment {
|
|||||||
private VRMouseManager mouseManager = null;
|
private VRMouseManager mouseManager = null;
|
||||||
private VRViewManager viewmanager = null;
|
private VRViewManager viewmanager = null;
|
||||||
|
|
||||||
|
private VRBounds bounds = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The underlying system VR API. By default set to {@link VRConstants#SETTING_VRAPI_OPENVR_VALUE}.
|
* The underlying system VR API. By default set to {@link VRConstants#SETTING_VRAPI_OPENVR_VALUE}.
|
||||||
*/
|
*/
|
||||||
@ -65,7 +68,6 @@ public class VREnvironment {
|
|||||||
|
|
||||||
private boolean initialized = false;
|
private boolean initialized = false;
|
||||||
|
|
||||||
private boolean attached = false;
|
|
||||||
|
|
||||||
public VREnvironment(AppSettings settings){
|
public VREnvironment(AppSettings settings){
|
||||||
|
|
||||||
@ -73,7 +75,8 @@ public class VREnvironment {
|
|||||||
|
|
||||||
guiManager = new VRGuiManager(this);
|
guiManager = new VRGuiManager(this);
|
||||||
mouseManager = new VRMouseManager(this);
|
mouseManager = new VRMouseManager(this);
|
||||||
// dummyCam = new Camera(settings.getWidth(), settings.getHeight());
|
|
||||||
|
bounds = new VRBounds();
|
||||||
|
|
||||||
processSettings();
|
processSettings();
|
||||||
}
|
}
|
||||||
@ -86,6 +89,14 @@ public class VREnvironment {
|
|||||||
return hardware;
|
return hardware;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the VR bounds.
|
||||||
|
* @return the VR bounds.
|
||||||
|
*/
|
||||||
|
public VRBounds getVRBounds(){
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the VR dedicated input.
|
* Get the VR dedicated input.
|
||||||
* @return the VR dedicated input.
|
* @return the VR dedicated input.
|
||||||
@ -347,7 +358,12 @@ public class VREnvironment {
|
|||||||
if (application.getCamera() != null){
|
if (application.getCamera() != null){
|
||||||
dummyCam = application.getCamera().clone();
|
dummyCam = application.getCamera().clone();
|
||||||
} else {
|
} else {
|
||||||
return new Camera(settings.getWidth(), settings.getHeight());
|
|
||||||
|
if ((settings != null) && (settings.getWidth() != 0) && (settings.getHeight() != 0)){
|
||||||
|
dummyCam = new Camera(settings.getWidth(), settings.getHeight());
|
||||||
|
} else {
|
||||||
|
dummyCam = new Camera();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalStateException("VR environment is not attached to any application.");
|
throw new IllegalStateException("VR environment is not attached to any application.");
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -5,6 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.jme3.input.vr;
|
package com.jme3.input.vr;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
@ -183,28 +184,50 @@ public class OpenVRInput implements VRInputAPI {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Vector3f getVelocity(int controllerIndex) {
|
public Vector3f getVelocity(int controllerIndex) {
|
||||||
int index = OpenVRInput.controllerIndex[controllerIndex];
|
|
||||||
if( needsNewVelocity[index] ) {
|
if (environment != null){
|
||||||
OpenVR.hmdTrackedDevicePoses[index].readField("vVelocity");
|
|
||||||
needsNewVelocity[index] = false;
|
if (environment.getVRHardware() instanceof OpenVR){
|
||||||
}
|
int index = OpenVRInput.controllerIndex[controllerIndex];
|
||||||
tempVel.x = OpenVR.hmdTrackedDevicePoses[index].vVelocity.v[0];
|
if( needsNewVelocity[index] ) {
|
||||||
tempVel.y = OpenVR.hmdTrackedDevicePoses[index].vVelocity.v[1];
|
((OpenVR)environment.getVRHardware()).hmdTrackedDevicePoses[index].readField("vVelocity");
|
||||||
tempVel.z = OpenVR.hmdTrackedDevicePoses[index].vVelocity.v[2];
|
needsNewVelocity[index] = false;
|
||||||
return tempVel;
|
}
|
||||||
|
tempVel.x = ((OpenVR)environment.getVRHardware()).hmdTrackedDevicePoses[index].vVelocity.v[0];
|
||||||
|
tempVel.y = ((OpenVR)environment.getVRHardware()).hmdTrackedDevicePoses[index].vVelocity.v[1];
|
||||||
|
tempVel.z = ((OpenVR)environment.getVRHardware()).hmdTrackedDevicePoses[index].vVelocity.v[2];
|
||||||
|
return tempVel;
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("VR hardware "+environment.getVRHardware().getClass().getSimpleName()+" is not a subclass of "+OpenVR.class.getSimpleName());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("VR input is not attached to a VR environment.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Vector3f getAngularVelocity(int controllerIndex) {
|
public Vector3f getAngularVelocity(int controllerIndex) {
|
||||||
int index = OpenVRInput.controllerIndex[controllerIndex];
|
|
||||||
if( needsNewAngVelocity[index] ) {
|
if (environment != null){
|
||||||
OpenVR.hmdTrackedDevicePoses[index].readField("vAngularVelocity");
|
|
||||||
needsNewAngVelocity[index] = false;
|
if (environment.getVRHardware() instanceof OpenVR){
|
||||||
}
|
|
||||||
tempVel.x = OpenVR.hmdTrackedDevicePoses[index].vAngularVelocity.v[0];
|
int index = OpenVRInput.controllerIndex[controllerIndex];
|
||||||
tempVel.y = OpenVR.hmdTrackedDevicePoses[index].vAngularVelocity.v[1];
|
if( needsNewAngVelocity[index] ) {
|
||||||
tempVel.z = OpenVR.hmdTrackedDevicePoses[index].vAngularVelocity.v[2];
|
((OpenVR)environment.getVRHardware()).hmdTrackedDevicePoses[index].readField("vAngularVelocity");
|
||||||
return tempVel;
|
needsNewAngVelocity[index] = false;
|
||||||
|
}
|
||||||
|
tempVel.x = ((OpenVR)environment.getVRHardware()).hmdTrackedDevicePoses[index].vAngularVelocity.v[0];
|
||||||
|
tempVel.y = ((OpenVR)environment.getVRHardware()).hmdTrackedDevicePoses[index].vAngularVelocity.v[1];
|
||||||
|
tempVel.z = ((OpenVR)environment.getVRHardware()).hmdTrackedDevicePoses[index].vAngularVelocity.v[2];
|
||||||
|
return tempVel;
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("VR hardware "+environment.getVRHardware().getClass().getSimpleName()+" is not a subclass of "+OpenVR.class.getSimpleName());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("VR input is not attached to a VR environment.");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -309,7 +332,16 @@ public class OpenVRInput implements VRInputAPI {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return OpenVR.hmdTrackedDevicePoses[controllerIndex[index]].bPoseIsValid != 0;
|
if (environment != null){
|
||||||
|
|
||||||
|
if (environment.getVRHardware() instanceof OpenVR){
|
||||||
|
return ((OpenVR)environment.getVRHardware()).hmdTrackedDevicePoses[controllerIndex[index]].bPoseIsValid != 0;
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("VR hardware "+environment.getVRHardware().getClass().getSimpleName()+" is not a subclass of "+OpenVR.class.getSimpleName());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("VR input is not attached to a VR environment.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -317,9 +349,19 @@ public class OpenVRInput implements VRInputAPI {
|
|||||||
if( isInputDeviceTracking(index) == false ){
|
if( isInputDeviceTracking(index) == false ){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
index = controllerIndex[index];
|
|
||||||
VRUtil.convertMatrix4toQuat(OpenVR.poseMatrices[index], rotStore[index]);
|
if (environment != null){
|
||||||
return rotStore[index];
|
|
||||||
|
if (environment.getVRHardware() instanceof OpenVR){
|
||||||
|
index = controllerIndex[index];
|
||||||
|
VRUtil.convertMatrix4toQuat(((OpenVR)environment.getVRHardware()).poseMatrices[index], rotStore[index]);
|
||||||
|
return rotStore[index];
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("VR hardware "+environment.getVRHardware().getClass().getSimpleName()+" is not a subclass of "+OpenVR.class.getSimpleName());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("VR input is not attached to a VR environment.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -328,12 +370,23 @@ public class OpenVRInput implements VRInputAPI {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// the hmdPose comes in rotated funny, fix that here
|
if (environment != null){
|
||||||
index = controllerIndex[index];
|
|
||||||
OpenVR.poseMatrices[index].toTranslationVector(posStore[index]);
|
if (environment.getVRHardware() instanceof OpenVR){
|
||||||
posStore[index].x = -posStore[index].x;
|
// the hmdPose comes in rotated funny, fix that here
|
||||||
posStore[index].z = -posStore[index].z;
|
index = controllerIndex[index];
|
||||||
return posStore[index];
|
((OpenVR)environment.getVRHardware()).poseMatrices[index].toTranslationVector(posStore[index]);
|
||||||
|
posStore[index].x = -posStore[index].x;
|
||||||
|
posStore[index].z = -posStore[index].z;
|
||||||
|
return posStore[index];
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("VR hardware "+environment.getVRHardware().getClass().getSimpleName()+" is not a subclass of "+OpenVR.class.getSimpleName());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("VR input is not attached to a VR environment.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -411,9 +464,9 @@ public class OpenVRInput implements VRInputAPI {
|
|||||||
if (environment != null){
|
if (environment != null){
|
||||||
controllerCount = 0;
|
controllerCount = 0;
|
||||||
for(int i=0;i<JOpenVRLibrary.k_unMaxTrackedDeviceCount;i++) {
|
for(int i=0;i<JOpenVRLibrary.k_unMaxTrackedDeviceCount;i++) {
|
||||||
int classCallback = ((OpenVR)environment.getVRHardware()).getVRSystem().GetTrackedDeviceClass.apply(i);
|
int classCallback = ((OpenVR)environment.getVRHardware()).getVRSystem().GetTrackedDeviceClass.apply(i);
|
||||||
if( classCallback == JOpenVRLibrary.ETrackedDeviceClass.ETrackedDeviceClass_TrackedDeviceClass_Controller || classCallback == JOpenVRLibrary.ETrackedDeviceClass.ETrackedDeviceClass_TrackedDeviceClass_GenericTracker) {
|
if( classCallback == JOpenVRLibrary.ETrackedDeviceClass.ETrackedDeviceClass_TrackedDeviceClass_Controller || classCallback == JOpenVRLibrary.ETrackedDeviceClass.ETrackedDeviceClass_TrackedDeviceClass_GenericTracker) {
|
||||||
|
|
||||||
String controllerName = "Unknown";
|
String controllerName = "Unknown";
|
||||||
String manufacturerName = "Unknown";
|
String manufacturerName = "Unknown";
|
||||||
try {
|
try {
|
||||||
@ -425,6 +478,12 @@ public class OpenVRInput implements VRInputAPI {
|
|||||||
|
|
||||||
controllerIndex[controllerCount] = i;
|
controllerIndex[controllerCount] = i;
|
||||||
|
|
||||||
|
// Adding tracked controller to control.
|
||||||
|
if (trackedControllers == null){
|
||||||
|
trackedControllers = new ArrayList<VRTrackedController>(JOpenVRLibrary.k_unMaxTrackedDeviceCount);
|
||||||
|
}
|
||||||
|
trackedControllers.add(new OpenVRTrackedController(i, this, controllerName, manufacturerName, environment));
|
||||||
|
|
||||||
// Send an Haptic pulse to the controller
|
// Send an Haptic pulse to the controller
|
||||||
triggerHapticPulse(controllerCount, 1.0f);
|
triggerHapticPulse(controllerCount, 1.0f);
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,93 @@
|
|||||||
|
package com.jme3.input.vr;
|
||||||
|
|
||||||
|
import com.jme3.app.VREnvironment;
|
||||||
|
import com.jme3.math.Matrix4f;
|
||||||
|
import com.jme3.math.Quaternion;
|
||||||
|
import com.jme3.math.Vector3f;
|
||||||
|
|
||||||
|
public class OpenVRTrackedController implements VRTrackedController{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The index of the controller within the unserlying VR API.
|
||||||
|
*/
|
||||||
|
private int controllerIndex = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The underlying VRAPI.
|
||||||
|
*/
|
||||||
|
private OpenVRInput hardware = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the controller.
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private VREnvironment environment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap a new VR tracked controller on an OpenVR system.
|
||||||
|
* @param controllerIndex the index of the controller within the underlying VR system.
|
||||||
|
* @param hardware the underlying VR system.
|
||||||
|
* @param name the name of the controller.
|
||||||
|
* @param manufacturer the manufacturer of the controller.
|
||||||
|
* @param environment the VR environment.
|
||||||
|
*/
|
||||||
|
public OpenVRTrackedController(int controllerIndex, OpenVRInput hardware, String name, String manufacturer, VREnvironment environment){
|
||||||
|
this.controllerIndex = controllerIndex;
|
||||||
|
this.hardware = hardware;
|
||||||
|
|
||||||
|
this.name = name;
|
||||||
|
this.manufacturer = manufacturer;
|
||||||
|
|
||||||
|
this.environment = environment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The manufacturer of the controller.
|
||||||
|
*/
|
||||||
|
private String manufacturer;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vector3f getPosition() {
|
||||||
|
if (hardware != null){
|
||||||
|
return hardware.getPosition(controllerIndex);
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("No underlying VR API.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Quaternion getOrientation() {
|
||||||
|
if (hardware != null){
|
||||||
|
return hardware.getOrientation(controllerIndex);
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("No underlying VR API.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Matrix4f getPose(){
|
||||||
|
|
||||||
|
if (environment != null){
|
||||||
|
if (hardware != null){
|
||||||
|
return ((OpenVR)environment.getVRHardware()).poseMatrices[controllerIndex];
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("No underlying VR API.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("VR tracked device is not attached to any environment.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getControllerName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getControllerManufacturer() {
|
||||||
|
return manufacturer;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -16,19 +16,19 @@ public class VRBounds {
|
|||||||
|
|
||||||
private static Logger logger = Logger.getLogger(VRBounds.class.getName());
|
private static Logger logger = Logger.getLogger(VRBounds.class.getName());
|
||||||
|
|
||||||
private static VR_IVRChaperone_FnTable vrChaperone;
|
private VR_IVRChaperone_FnTable vrChaperone;
|
||||||
private static Vector2f playSize;
|
private Vector2f playSize;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the VR bounds.
|
* Initialize the VR bounds.
|
||||||
* @return <code>true</code> if the initialization is a success and <code>false</code> otherwise.
|
* @return <code>true</code> if the initialization is a success and <code>false</code> otherwise.
|
||||||
*/
|
*/
|
||||||
public static boolean init() {
|
public boolean init(OpenVR api) {
|
||||||
|
|
||||||
logger.config("Initialize VR bounds...");
|
logger.config("Initialize VR bounds...");
|
||||||
|
|
||||||
if( vrChaperone == null ) {
|
if( vrChaperone == null ) {
|
||||||
vrChaperone = new VR_IVRChaperone_FnTable(JOpenVRLibrary.VR_GetGenericInterface(JOpenVRLibrary.IVRChaperone_Version, OpenVR.hmdErrorStore).getPointer());
|
vrChaperone = new VR_IVRChaperone_FnTable(JOpenVRLibrary.VR_GetGenericInterface(JOpenVRLibrary.IVRChaperone_Version, api.hmdErrorStore).getPointer());
|
||||||
if( vrChaperone != null ) {
|
if( vrChaperone != null ) {
|
||||||
vrChaperone.setAutoSynch(false);
|
vrChaperone.setAutoSynch(false);
|
||||||
vrChaperone.read();
|
vrChaperone.read();
|
||||||
@ -53,7 +53,7 @@ public class VRBounds {
|
|||||||
* Get the size of the VR world.
|
* Get the size of the VR world.
|
||||||
* @return the size of the VR world.
|
* @return the size of the VR world.
|
||||||
*/
|
*/
|
||||||
public static Vector2f getPlaySize() {
|
public Vector2f getPlaySize() {
|
||||||
return playSize;
|
return playSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,9 @@
|
|||||||
package com.jme3.input.vr;
|
package com.jme3.input.vr;
|
||||||
|
|
||||||
|
import com.jme3.math.Matrix4f;
|
||||||
|
import com.jme3.math.Quaternion;
|
||||||
|
import com.jme3.math.Vector3f;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* TODO
|
||||||
* @author Julien Seinturier - (c) 2016 - JOrigin project - <a href="http://www.jorigin.org">http:/www.jorigin.org</a>
|
* @author Julien Seinturier - (c) 2016 - JOrigin project - <a href="http://www.jorigin.org">http:/www.jorigin.org</a>
|
||||||
@ -7,4 +11,40 @@ package com.jme3.input.vr;
|
|||||||
*/
|
*/
|
||||||
public interface VRTrackedController {
|
public interface VRTrackedController {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the controller name.
|
||||||
|
* @return the controller name.
|
||||||
|
*/
|
||||||
|
public String getControllerName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the controller manufacturer.
|
||||||
|
* @return the controller manufacturer.
|
||||||
|
*/
|
||||||
|
public String getControllerManufacturer();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the position of the tracked device. This value is the translation component of the device {@link #getPose() pose}.
|
||||||
|
* @return the position of the tracked device.
|
||||||
|
* @see #getOrientation()
|
||||||
|
* @see #getPose()
|
||||||
|
*/
|
||||||
|
public Vector3f getPosition();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the orientation of the tracked device. This value is the rotation component of the device {@link #getPose() pose}.
|
||||||
|
* @return the orientation of the tracked device.
|
||||||
|
* @see #getPosition()
|
||||||
|
* @see #getPose()
|
||||||
|
*/
|
||||||
|
public Quaternion getOrientation();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the pose of the tracked device.
|
||||||
|
* The pose is a 4x4 matrix than combine the {@link #getPosition() position} and the {@link #getOrientation() orientation} of the device.
|
||||||
|
* @return the pose of the tracked device.
|
||||||
|
* @see #getPosition()
|
||||||
|
* @see #getOrientation()
|
||||||
|
*/
|
||||||
|
public Matrix4f getPose();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,18 +28,20 @@ public abstract class AbstractVRViewManager implements VRViewManager {
|
|||||||
protected VREnvironment environment = null;
|
protected VREnvironment environment = null;
|
||||||
|
|
||||||
protected Camera leftCamera;
|
protected Camera leftCamera;
|
||||||
protected ViewPort leftViewport;
|
protected ViewPort leftViewPort;
|
||||||
protected FilterPostProcessor leftPostProcessor;
|
protected FilterPostProcessor leftPostProcessor;
|
||||||
protected Texture2D leftEyeTexture;
|
protected Texture2D leftEyeTexture;
|
||||||
protected Texture2D leftEyeDepth;
|
protected Texture2D leftEyeDepth;
|
||||||
|
|
||||||
protected Camera rightCamera;
|
protected Camera rightCamera;
|
||||||
protected ViewPort rightViewport;
|
protected ViewPort rightViewPort;
|
||||||
protected FilterPostProcessor rightPostProcessor;
|
protected FilterPostProcessor rightPostProcessor;
|
||||||
protected Texture2D rightEyeTexture;
|
protected Texture2D rightEyeTexture;
|
||||||
protected Texture2D rightEyeDepth;
|
protected Texture2D rightEyeDepth;
|
||||||
|
|
||||||
private float resMult = 1f;
|
protected ViewPort mirrorViewPort;
|
||||||
|
|
||||||
|
private float resMult = 1f;
|
||||||
|
|
||||||
private float heightAdjustment;
|
private float heightAdjustment;
|
||||||
|
|
||||||
@ -54,15 +56,24 @@ public abstract class AbstractVRViewManager implements VRViewManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ViewPort getLeftViewport() {
|
public ViewPort getLeftViewPort() {
|
||||||
return leftViewport;
|
return leftViewPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ViewPort getRightViewport() {
|
public ViewPort getRightViewPort() {
|
||||||
return rightViewport;
|
return rightViewPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the {@link ViewPort view port} attached to the mirror display.
|
||||||
|
* @return the view port attached to the mirror display.
|
||||||
|
*/
|
||||||
|
public ViewPort getMirrorViewPort() {
|
||||||
|
return mirrorViewPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Texture2D getLeftTexture(){
|
public Texture2D getLeftTexture(){
|
||||||
return leftEyeTexture;
|
return leftEyeTexture;
|
||||||
@ -124,7 +135,7 @@ public abstract class AbstractVRViewManager implements VRViewManager {
|
|||||||
public void moveScreenProcessingToEyes() {
|
public void moveScreenProcessingToEyes() {
|
||||||
|
|
||||||
if (environment != null){
|
if (environment != null){
|
||||||
if( getRightViewport() == null ){
|
if( getRightViewPort() == null ){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,7 +161,7 @@ public abstract class AbstractVRViewManager implements VRViewManager {
|
|||||||
public void syncScreenProcessing(ViewPort sourceViewport) {
|
public void syncScreenProcessing(ViewPort sourceViewport) {
|
||||||
|
|
||||||
if (environment != null){
|
if (environment != null){
|
||||||
if( getRightViewport() == null ){
|
if( getRightViewPort() == null ){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,13 +174,13 @@ public abstract class AbstractVRViewManager implements VRViewManager {
|
|||||||
// clear out all filters & processors, to start from scratch
|
// clear out all filters & processors, to start from scratch
|
||||||
getRightPostProcessor().removeAllFilters();
|
getRightPostProcessor().removeAllFilters();
|
||||||
getLeftPostProcessor().removeAllFilters();
|
getLeftPostProcessor().removeAllFilters();
|
||||||
getLeftViewport().clearProcessors();
|
getLeftViewPort().clearProcessors();
|
||||||
getRightViewport().clearProcessors();
|
getRightViewPort().clearProcessors();
|
||||||
// if we have no processors to sync, don't add the FilterPostProcessor
|
// if we have no processors to sync, don't add the FilterPostProcessor
|
||||||
if( sourceViewport.getProcessors().isEmpty() ) return;
|
if( sourceViewport.getProcessors().isEmpty() ) return;
|
||||||
// add post processors we just made, which are empty
|
// add post processors we just made, which are empty
|
||||||
getLeftViewport().addProcessor(getLeftPostProcessor());
|
getLeftViewPort().addProcessor(getLeftPostProcessor());
|
||||||
getRightViewport().addProcessor(getRightPostProcessor());
|
getRightViewPort().addProcessor(getRightPostProcessor());
|
||||||
// go through all of the filters in the processors list
|
// go through all of the filters in the processors list
|
||||||
// add them to the left viewport processor & clone them to the right
|
// add them to the left viewport processor & clone them to the right
|
||||||
for(SceneProcessor sceneProcessor : sourceViewport.getProcessors()) {
|
for(SceneProcessor sceneProcessor : sourceViewport.getProcessors()) {
|
||||||
@ -202,8 +213,8 @@ public abstract class AbstractVRViewManager implements VRViewManager {
|
|||||||
VRDirectionalLightShadowRenderer dlsr = (VRDirectionalLightShadowRenderer) sceneProcessor;
|
VRDirectionalLightShadowRenderer dlsr = (VRDirectionalLightShadowRenderer) sceneProcessor;
|
||||||
VRDirectionalLightShadowRenderer dlsrRight = dlsr.clone();
|
VRDirectionalLightShadowRenderer dlsrRight = dlsr.clone();
|
||||||
dlsrRight.setLight(dlsr.getLight());
|
dlsrRight.setLight(dlsr.getLight());
|
||||||
getRightViewport().getProcessors().add(0, dlsrRight);
|
getRightViewPort().getProcessors().add(0, dlsrRight);
|
||||||
getLeftViewport().getProcessors().add(0, sceneProcessor);
|
getLeftViewPort().getProcessors().add(0, sceneProcessor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// make sure each has a translucent filter renderer
|
// make sure each has a translucent filter renderer
|
||||||
|
|||||||
@ -42,17 +42,25 @@ public interface VRViewManager {
|
|||||||
/**
|
/**
|
||||||
* Get the {@link ViewPort viewport} attached to the left eye.
|
* Get the {@link ViewPort viewport} attached to the left eye.
|
||||||
* @return the {@link ViewPort viewport} attached to the left eye.
|
* @return the {@link ViewPort viewport} attached to the left eye.
|
||||||
* @see #getRightViewport()
|
* @see #getRightViewPort()
|
||||||
*/
|
*/
|
||||||
public ViewPort getLeftViewport();
|
public ViewPort getLeftViewPort();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the {@link ViewPort viewport} attached to the right eye.
|
* Get the {@link ViewPort viewport} attached to the right eye.
|
||||||
* @return the {@link ViewPort viewport} attached to the right eye.
|
* @return the {@link ViewPort viewport} attached to the right eye.
|
||||||
* @see #getLeftViewport()
|
* @see #getLeftViewPort()
|
||||||
*/
|
*/
|
||||||
public ViewPort getRightViewport();
|
public ViewPort getRightViewPort();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the {@link ViewPort view port} attached to the mirror display.
|
||||||
|
* @return the view port attached to the mirror display.
|
||||||
|
* @see #getLeftViewPort()
|
||||||
|
* @see #getRightViewPort()
|
||||||
|
*/
|
||||||
|
public ViewPort getMirrorViewPort();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the texture attached to the left eye.
|
* Get the texture attached to the left eye.
|
||||||
|
|||||||
@ -117,18 +117,18 @@ public class VRViewManagerOSVR extends AbstractVRViewManager{
|
|||||||
/**
|
/**
|
||||||
* Get the {@link ViewPort viewport} attached to the left eye.
|
* Get the {@link ViewPort viewport} attached to the left eye.
|
||||||
* @return the {@link ViewPort viewport} attached to the left eye.
|
* @return the {@link ViewPort viewport} attached to the left eye.
|
||||||
* @see #getRightViewport()
|
* @see #getRightViewPort()
|
||||||
*/
|
*/
|
||||||
public ViewPort getLeftViewport() {
|
public ViewPort getLeftViewPort() {
|
||||||
return leftViewport;
|
return leftViewport;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the {@link ViewPort viewport} attached to the right eye.
|
* Get the {@link ViewPort viewport} attached to the right eye.
|
||||||
* @return the {@link ViewPort viewport} attached to the right eye.
|
* @return the {@link ViewPort viewport} attached to the right eye.
|
||||||
* @see #getLeftViewport()
|
* @see #getLeftViewPort()
|
||||||
*/
|
*/
|
||||||
public ViewPort getRightViewport() {
|
public ViewPort getRightViewPort() {
|
||||||
return rightViewport;
|
return rightViewport;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,7 @@ package com.jme3.util;
|
|||||||
import com.jme3.app.VREnvironment;
|
import com.jme3.app.VREnvironment;
|
||||||
import com.jme3.input.vr.OpenVR;
|
import com.jme3.input.vr.OpenVR;
|
||||||
import com.jme3.input.vr.VRAPI;
|
import com.jme3.input.vr.VRAPI;
|
||||||
|
import com.jme3.input.vr.VRTrackedController;
|
||||||
import com.jme3.material.Material;
|
import com.jme3.material.Material;
|
||||||
import com.jme3.math.ColorRGBA;
|
import com.jme3.math.ColorRGBA;
|
||||||
import com.jme3.math.Quaternion;
|
import com.jme3.math.Quaternion;
|
||||||
@ -346,10 +347,10 @@ public class VRViewManagerOpenVR extends AbstractVRViewManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
leftEyeTexture = (Texture2D) getLeftViewport().getOutputFrameBuffer().getColorBuffer().getTexture();
|
leftEyeTexture = (Texture2D) getLeftViewPort().getOutputFrameBuffer().getColorBuffer().getTexture();
|
||||||
rightEyeTexture = (Texture2D)getRightViewport().getOutputFrameBuffer().getColorBuffer().getTexture();
|
rightEyeTexture = (Texture2D)getRightViewPort().getOutputFrameBuffer().getColorBuffer().getTexture();
|
||||||
leftEyeDepth = (Texture2D) getLeftViewport().getOutputFrameBuffer().getDepthBuffer().getTexture();
|
leftEyeDepth = (Texture2D) getLeftViewPort().getOutputFrameBuffer().getDepthBuffer().getTexture();
|
||||||
rightEyeDepth = (Texture2D)getRightViewport().getOutputFrameBuffer().getDepthBuffer().getTexture();
|
rightEyeDepth = (Texture2D)getRightViewPort().getOutputFrameBuffer().getDepthBuffer().getTexture();
|
||||||
|
|
||||||
// main viewport is either going to be a distortion scene or nothing
|
// main viewport is either going to be a distortion scene or nothing
|
||||||
// mirroring is handled by copying framebuffers
|
// mirroring is handled by copying framebuffers
|
||||||
@ -387,6 +388,7 @@ public class VRViewManagerOpenVR extends AbstractVRViewManager {
|
|||||||
|
|
||||||
if( environment.getApplication().getContext().getSettings().isSwapBuffers() ) {
|
if( environment.getApplication().getContext().getSettings().isSwapBuffers() ) {
|
||||||
setupMirrorBuffers(environment.getCamera(), leftEyeTexture, false);
|
setupMirrorBuffers(environment.getCamera(), leftEyeTexture, false);
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalStateException("This VR environment is not attached to any application.");
|
throw new IllegalStateException("This VR environment is not attached to any application.");
|
||||||
@ -414,9 +416,35 @@ public class VRViewManagerOpenVR extends AbstractVRViewManager {
|
|||||||
// grab the hardware handle
|
// grab the hardware handle
|
||||||
VRAPI dev = environment.getVRHardware();
|
VRAPI dev = environment.getVRHardware();
|
||||||
if( dev != null ) {
|
if( dev != null ) {
|
||||||
|
|
||||||
|
|
||||||
// update the HMD's position & orientation
|
// update the HMD's position & orientation
|
||||||
dev.updatePose();
|
dev.updatePose();
|
||||||
dev.getPositionAndOrientation(hmdPos, hmdRot);
|
dev.getPositionAndOrientation(hmdPos, hmdRot);
|
||||||
|
/*
|
||||||
|
// TOREMOVE
|
||||||
|
Vector3f v = dev.getVRinput().getTrackedController(0).getPosition();
|
||||||
|
Quaternion q = dev.getVRinput().getTrackedController(0).getOrientation();
|
||||||
|
if ((v != null)&&(q != null)){
|
||||||
|
hmdPos.set(v);
|
||||||
|
hmdRot.set(q);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.severe("HMD controller ");
|
||||||
|
logger.severe(" Position "+hmdPos);
|
||||||
|
logger.severe(" Orientation "+hmdRot);
|
||||||
|
|
||||||
|
VRTrackedController tc = null;
|
||||||
|
for(int i = 0; i < dev.getVRinput().getTrackedControllerCount(); i++){
|
||||||
|
tc = dev.getVRinput().getTrackedController(i);
|
||||||
|
logger.severe("Tracked controller "+i+": "+tc.getControllerName());
|
||||||
|
logger.severe(" Position "+tc.getPosition());
|
||||||
|
logger.severe(" Orientation "+tc.getOrientation());
|
||||||
|
logger.severe("");
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
// TOREMOVE
|
||||||
|
|
||||||
if( obs != null ) {
|
if( obs != null ) {
|
||||||
// update hmdPos based on obs rotation
|
// update hmdPos based on obs rotation
|
||||||
finalRotation.set(objRot);
|
finalRotation.set(objRot);
|
||||||
@ -490,18 +518,18 @@ public class VRViewManagerOpenVR extends AbstractVRViewManager {
|
|||||||
//org.lwjgl.opengl.GL11.glEnable(org.lwjgl.opengl.GL30.GL_FRAMEBUFFER_SRGB);
|
//org.lwjgl.opengl.GL11.glEnable(org.lwjgl.opengl.GL30.GL_FRAMEBUFFER_SRGB);
|
||||||
|
|
||||||
if( !environment.isInstanceRendering()) {
|
if( !environment.isInstanceRendering()) {
|
||||||
leftViewport = setupViewBuffers(getLeftCamera(), LEFT_VIEW_NAME);
|
leftViewPort = setupViewBuffers(getLeftCamera(), LEFT_VIEW_NAME);
|
||||||
rightCamera = getLeftCamera().clone();
|
rightCamera = getLeftCamera().clone();
|
||||||
if( environment.getVRHardware() != null ){
|
if( environment.getVRHardware() != null ){
|
||||||
getRightCamera().setProjectionMatrix(environment.getVRHardware().getHMDMatrixProjectionRightEye(getRightCamera()));
|
getRightCamera().setProjectionMatrix(environment.getVRHardware().getHMDMatrixProjectionRightEye(getRightCamera()));
|
||||||
}
|
}
|
||||||
rightViewport = setupViewBuffers(getRightCamera(), RIGHT_VIEW_NAME);
|
rightViewPort = setupViewBuffers(getRightCamera(), RIGHT_VIEW_NAME);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (environment.getApplication() != null){
|
if (environment.getApplication() != null){
|
||||||
|
|
||||||
logger.severe("THIS CODE NEED CHANGES !!!");
|
logger.severe("THIS CODE NEED CHANGES !!!");
|
||||||
leftViewport = environment.getApplication().getViewPort();
|
leftViewPort = environment.getApplication().getViewPort();
|
||||||
//leftViewport.attachScene(app.getRootNode());
|
//leftViewport.attachScene(app.getRootNode());
|
||||||
rightCamera = getLeftCamera().clone();
|
rightCamera = getLeftCamera().clone();
|
||||||
if( environment.getVRHardware() != null ){
|
if( environment.getVRHardware() != null ){
|
||||||
@ -520,7 +548,7 @@ public class VRViewManagerOpenVR extends AbstractVRViewManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// setup gui
|
// setup gui
|
||||||
environment.getVRGUIManager().setupGui(getLeftCamera(), getRightCamera(), getLeftViewport(), getRightViewport());
|
environment.getVRGUIManager().setupGui(getLeftCamera(), getRightCamera(), getLeftViewPort(), getRightViewPort());
|
||||||
|
|
||||||
if( environment.getVRHardware() != null ) {
|
if( environment.getVRHardware() != null ) {
|
||||||
// call these to cache the results internally
|
// call these to cache the results internally
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user