* AwtMouseInput event queue is now synchronized like it should be
* TangentBinormalGenerator no longer writes binormal buffers. Instead it writes the W coordinate of the tangent based on the binormal's sign. Should fix "normal map seams" type problems git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@8385 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
This commit is contained in:
parent
86e5ffd7a4
commit
5feebef7c5
@ -32,6 +32,8 @@
|
|||||||
|
|
||||||
package com.jme3.util;
|
package com.jme3.util;
|
||||||
|
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import com.jme3.scene.mesh.IndexBuffer;
|
||||||
import com.jme3.scene.Geometry;
|
import com.jme3.scene.Geometry;
|
||||||
import com.jme3.scene.Node;
|
import com.jme3.scene.Node;
|
||||||
import com.jme3.scene.Spatial;
|
import com.jme3.scene.Spatial;
|
||||||
@ -41,14 +43,11 @@ import com.jme3.math.Vector2f;
|
|||||||
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 java.nio.Buffer;
|
|
||||||
import java.nio.FloatBuffer;
|
import java.nio.FloatBuffer;
|
||||||
import java.nio.IntBuffer;
|
import java.nio.IntBuffer;
|
||||||
import java.nio.ShortBuffer;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import static com.jme3.util.BufferUtils.*;
|
import static com.jme3.util.BufferUtils.*;
|
||||||
|
|
||||||
@ -68,38 +67,6 @@ public class TangentBinormalGenerator {
|
|||||||
setToleranceAngle(45);
|
setToleranceAngle(45);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static interface IndexWrapper {
|
|
||||||
public int get(int i);
|
|
||||||
public int size();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IndexWrapper getIndexWrapper(final Buffer buff) {
|
|
||||||
if (buff instanceof ShortBuffer) {
|
|
||||||
return new IndexWrapper() {
|
|
||||||
private ShortBuffer buf = (ShortBuffer) buff;
|
|
||||||
public int get(int i) {
|
|
||||||
return ((int) buf.get(i))&(0x0000FFFF);
|
|
||||||
}
|
|
||||||
public int size() {
|
|
||||||
return buf.capacity();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else if (buff instanceof IntBuffer) {
|
|
||||||
return new IndexWrapper() {
|
|
||||||
private IntBuffer buf = (IntBuffer) buff;
|
|
||||||
public int get(int i) {
|
|
||||||
return buf.get(i);
|
|
||||||
}
|
|
||||||
public int size() {
|
|
||||||
return buf.capacity();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class VertexData {
|
private static class VertexData {
|
||||||
public final Vector3f tangent = new Vector3f();
|
public final Vector3f tangent = new Vector3f();
|
||||||
public final Vector3f binormal = new Vector3f();
|
public final Vector3f binormal = new Vector3f();
|
||||||
@ -188,7 +155,7 @@ public class TangentBinormalGenerator {
|
|||||||
private static VertexData[] processTriangles(Mesh mesh,
|
private static VertexData[] processTriangles(Mesh mesh,
|
||||||
int[] index, Vector3f[] v, Vector2f[] t)
|
int[] index, Vector3f[] v, Vector2f[] t)
|
||||||
{
|
{
|
||||||
IndexWrapper indexBuffer = getIndexWrapper(mesh.getBuffer(Type.Index).getData());
|
IndexBuffer indexBuffer = mesh.getIndexBuffer();
|
||||||
FloatBuffer vertexBuffer = (FloatBuffer) mesh.getBuffer(Type.Position).getData();
|
FloatBuffer vertexBuffer = (FloatBuffer) mesh.getBuffer(Type.Position).getData();
|
||||||
if (mesh.getBuffer(Type.TexCoord) == null)
|
if (mesh.getBuffer(Type.TexCoord) == null)
|
||||||
throw new IllegalArgumentException("Can only generate tangents for "
|
throw new IllegalArgumentException("Can only generate tangents for "
|
||||||
@ -218,7 +185,7 @@ public class TangentBinormalGenerator {
|
|||||||
private static VertexData[] processTriangleStrip(Mesh mesh,
|
private static VertexData[] processTriangleStrip(Mesh mesh,
|
||||||
int[] index, Vector3f[] v, Vector2f[] t)
|
int[] index, Vector3f[] v, Vector2f[] t)
|
||||||
{
|
{
|
||||||
IndexWrapper indexBuffer = getIndexWrapper(mesh.getBuffer(Type.Index).getData());
|
IndexBuffer indexBuffer = mesh.getIndexBuffer();
|
||||||
FloatBuffer vertexBuffer = (FloatBuffer) mesh.getBuffer(Type.Position).getData();
|
FloatBuffer vertexBuffer = (FloatBuffer) mesh.getBuffer(Type.Position).getData();
|
||||||
FloatBuffer textureBuffer = (FloatBuffer) mesh.getBuffer(Type.TexCoord).getData();
|
FloatBuffer textureBuffer = (FloatBuffer) mesh.getBuffer(Type.TexCoord).getData();
|
||||||
|
|
||||||
@ -266,7 +233,7 @@ public class TangentBinormalGenerator {
|
|||||||
private static VertexData[] processTriangleFan(Mesh mesh,
|
private static VertexData[] processTriangleFan(Mesh mesh,
|
||||||
int[] index, Vector3f[] v, Vector2f[] t)
|
int[] index, Vector3f[] v, Vector2f[] t)
|
||||||
{
|
{
|
||||||
IndexWrapper indexBuffer = getIndexWrapper(mesh.getBuffer(Type.Index).getData());
|
IndexBuffer indexBuffer = mesh.getIndexBuffer();
|
||||||
FloatBuffer vertexBuffer = (FloatBuffer) mesh.getBuffer(Type.Position).getData();
|
FloatBuffer vertexBuffer = (FloatBuffer) mesh.getBuffer(Type.Position).getData();
|
||||||
FloatBuffer textureBuffer = (FloatBuffer) mesh.getBuffer(Type.TexCoord).getData();
|
FloatBuffer textureBuffer = (FloatBuffer) mesh.getBuffer(Type.TexCoord).getData();
|
||||||
|
|
||||||
@ -331,11 +298,11 @@ public class TangentBinormalGenerator {
|
|||||||
|
|
||||||
boolean normalize = false;
|
boolean normalize = false;
|
||||||
if (Math.abs(det) < ZERO_TOLERANCE) {
|
if (Math.abs(det) < ZERO_TOLERANCE) {
|
||||||
// log.log(Level.WARNING, "Colinear uv coordinates for triangle " +
|
log.log(Level.WARNING, "Colinear uv coordinates for triangle " +
|
||||||
// "[{0}, {1}, {2}]; tex0 = [{3}, {4}], " +
|
"[{0}, {1}, {2}]; tex0 = [{3}, {4}], " +
|
||||||
// "tex1 = [{5}, {6}], tex2 = [{7}, {8}]",
|
"tex1 = [{5}, {6}], tex2 = [{7}, {8}]",
|
||||||
// new Object[]{ index[0], index[1], index[2],
|
new Object[]{ index[0], index[1], index[2],
|
||||||
// t[0].x, t[0].y, t[1].x, t[1].y, t[2].x, t[2].y });
|
t[0].x, t[0].y, t[1].x, t[1].y, t[2].x, t[2].y });
|
||||||
det = 1;
|
det = 1;
|
||||||
normalize = true;
|
normalize = true;
|
||||||
}
|
}
|
||||||
@ -348,13 +315,13 @@ public class TangentBinormalGenerator {
|
|||||||
binormal.set(edge2);
|
binormal.set(edge2);
|
||||||
binormal.normalizeLocal();
|
binormal.normalizeLocal();
|
||||||
|
|
||||||
// if (Math.abs(Math.abs(tangent.dot(binormal)) - 1)
|
if (Math.abs(Math.abs(tangent.dot(binormal)) - 1)
|
||||||
// < ZERO_TOLERANCE)
|
< ZERO_TOLERANCE)
|
||||||
// {
|
{
|
||||||
// log.log(Level.WARNING, "Vertices are on the same line " +
|
log.log(Level.WARNING, "Vertices are on the same line " +
|
||||||
// "for triangle [{0}, {1}, {2}].",
|
"for triangle [{0}, {1}, {2}].",
|
||||||
// new Object[]{ index[0], index[1], index[2] });
|
new Object[]{ index[0], index[1], index[2] });
|
||||||
// }
|
}
|
||||||
|
|
||||||
float factor = 1/det;
|
float factor = 1/det;
|
||||||
tangent.x = (edge2uv.y*edge1.x - edge1uv.y*edge2.x)*factor;
|
tangent.x = (edge2uv.y*edge1.x - edge1uv.y*edge2.x)*factor;
|
||||||
@ -392,8 +359,8 @@ public class TangentBinormalGenerator {
|
|||||||
{
|
{
|
||||||
FloatBuffer normalBuffer = (FloatBuffer) mesh.getBuffer(Type.Normal).getData();
|
FloatBuffer normalBuffer = (FloatBuffer) mesh.getBuffer(Type.Normal).getData();
|
||||||
|
|
||||||
FloatBuffer tangents = BufferUtils.createFloatBuffer(vertices.length * 3);
|
FloatBuffer tangents = BufferUtils.createFloatBuffer(vertices.length * 4);
|
||||||
FloatBuffer binormals = BufferUtils.createFloatBuffer(vertices.length * 3);
|
// FloatBuffer binormals = BufferUtils.createFloatBuffer(vertices.length * 3);
|
||||||
|
|
||||||
Vector3f tangent = new Vector3f();
|
Vector3f tangent = new Vector3f();
|
||||||
Vector3f binormal = new Vector3f();
|
Vector3f binormal = new Vector3f();
|
||||||
@ -403,7 +370,10 @@ public class TangentBinormalGenerator {
|
|||||||
Vector3f tangentUnit = new Vector3f();
|
Vector3f tangentUnit = new Vector3f();
|
||||||
Vector3f binormalUnit = new Vector3f();
|
Vector3f binormalUnit = new Vector3f();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < vertices.length; i++) {
|
for (int i = 0; i < vertices.length; i++) {
|
||||||
|
float wCoord = -1;
|
||||||
|
|
||||||
populateFromBuffer(givenNormal, normalBuffer, i);
|
populateFromBuffer(givenNormal, normalBuffer, i);
|
||||||
givenNormal.normalizeLocal();
|
givenNormal.normalizeLocal();
|
||||||
@ -423,9 +393,9 @@ public class TangentBinormalGenerator {
|
|||||||
tangentUnit.set(triangleData.tangent);
|
tangentUnit.set(triangleData.tangent);
|
||||||
tangentUnit.normalizeLocal();
|
tangentUnit.normalizeLocal();
|
||||||
if (tangent.dot(tangentUnit) < toleranceDot) {
|
if (tangent.dot(tangentUnit) < toleranceDot) {
|
||||||
// log.log(Level.WARNING,
|
log.log(Level.WARNING,
|
||||||
// "Angle between tangents exceeds tolerance " +
|
"Angle between tangents exceeds tolerance " +
|
||||||
// "for vertex {0}.", i);
|
"for vertex {0}.", i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -433,9 +403,9 @@ public class TangentBinormalGenerator {
|
|||||||
binormalUnit.set(triangleData.binormal);
|
binormalUnit.set(triangleData.binormal);
|
||||||
binormalUnit.normalizeLocal();
|
binormalUnit.normalizeLocal();
|
||||||
if (binormal.dot(binormalUnit) < toleranceDot) {
|
if (binormal.dot(binormalUnit) < toleranceDot) {
|
||||||
// log.log(Level.WARNING,
|
log.log(Level.WARNING,
|
||||||
// "Angle between binormals exceeds tolerance " +
|
"Angle between binormals exceeds tolerance " +
|
||||||
// "for vertex {0}.", i);
|
"for vertex {0}.", i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -455,16 +425,18 @@ public class TangentBinormalGenerator {
|
|||||||
flippedNormal = true;
|
flippedNormal = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (flippedNormal && approxTangent) {
|
if (flippedNormal /*&& approxTangent*/) {
|
||||||
// Generated normal is flipped for this vertex,
|
// Generated normal is flipped for this vertex,
|
||||||
// so binormal = normal.cross(tangent) will be flipped in the shader
|
// so binormal = normal.cross(tangent) will be flipped in the shader
|
||||||
// log.log(Level.WARNING,
|
// log.log(Level.WARNING,
|
||||||
// "Binormal is flipped for vertex {0}.", i);
|
// "Binormal is flipped for vertex {0}.", i);
|
||||||
|
|
||||||
|
wCoord = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tangent.length() < ZERO_TOLERANCE) {
|
if (tangent.length() < ZERO_TOLERANCE) {
|
||||||
// log.log(Level.WARNING,
|
log.log(Level.WARNING,
|
||||||
// "Shared tangent is zero for vertex {0}.", i);
|
"Shared tangent is zero for vertex {0}.", i);
|
||||||
// attempt to fix from binormal
|
// attempt to fix from binormal
|
||||||
if (binormal.length() >= ZERO_TOLERANCE) {
|
if (binormal.length() >= ZERO_TOLERANCE) {
|
||||||
binormal.cross(givenNormal, tangent);
|
binormal.cross(givenNormal, tangent);
|
||||||
@ -484,16 +456,15 @@ public class TangentBinormalGenerator {
|
|||||||
if (Math.abs(Math.abs(tangentUnit.dot(givenNormal)) - 1)
|
if (Math.abs(Math.abs(tangentUnit.dot(givenNormal)) - 1)
|
||||||
< ZERO_TOLERANCE)
|
< ZERO_TOLERANCE)
|
||||||
{
|
{
|
||||||
// log.log(Level.WARNING,
|
log.log(Level.WARNING,
|
||||||
// "Normal and tangent are parallel for vertex {0}.", i);
|
"Normal and tangent are parallel for vertex {0}.", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!approxTangent) {
|
if (!approxTangent) {
|
||||||
|
|
||||||
if (binormal.length() < ZERO_TOLERANCE) {
|
if (binormal.length() < ZERO_TOLERANCE) {
|
||||||
// log.log(Level.WARNING,
|
log.log(Level.WARNING,
|
||||||
// "Shared binormal is zero for vertex {0}.", i);
|
"Shared binormal is zero for vertex {0}.", i);
|
||||||
// attempt to fix from tangent
|
// attempt to fix from tangent
|
||||||
if (tangent.length() >= ZERO_TOLERANCE) {
|
if (tangent.length() >= ZERO_TOLERANCE) {
|
||||||
givenNormal.cross(tangent, binormal);
|
givenNormal.cross(tangent, binormal);
|
||||||
@ -513,33 +484,40 @@ public class TangentBinormalGenerator {
|
|||||||
if (Math.abs(Math.abs(binormalUnit.dot(givenNormal)) - 1)
|
if (Math.abs(Math.abs(binormalUnit.dot(givenNormal)) - 1)
|
||||||
< ZERO_TOLERANCE)
|
< ZERO_TOLERANCE)
|
||||||
{
|
{
|
||||||
// log.log(Level.WARNING,
|
log.log(Level.WARNING,
|
||||||
// "Normal and binormal are parallel for vertex {0}.", i);
|
"Normal and binormal are parallel for vertex {0}.", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Math.abs(Math.abs(binormalUnit.dot(tangentUnit)) - 1)
|
if (Math.abs(Math.abs(binormalUnit.dot(tangentUnit)) - 1)
|
||||||
< ZERO_TOLERANCE)
|
< ZERO_TOLERANCE)
|
||||||
{
|
{
|
||||||
// log.log(Level.WARNING,
|
log.log(Level.WARNING,
|
||||||
// "Tangent and binormal are parallel for vertex {0}.", i);
|
"Tangent and binormal are parallel for vertex {0}.", i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (approxTangent) {
|
if (approxTangent) {
|
||||||
givenNormal.cross(tangent, binormal);
|
// givenNormal.cross(tangent, binormal);
|
||||||
binormal.cross(givenNormal, tangent);
|
// binormal.cross(givenNormal, tangent);
|
||||||
tangent.normalizeLocal();
|
tangent.normalizeLocal();
|
||||||
|
|
||||||
setInBuffer(tangent, tangents, i);
|
tangents.put((i * 4), tangent.x);
|
||||||
|
tangents.put((i * 4) + 1, tangent.y);
|
||||||
|
tangents.put((i * 4) + 2, tangent.z);
|
||||||
|
tangents.put((i * 4) + 3, wCoord);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
setInBuffer(tangent, tangents, i);
|
tangents.put((i * 4), tangent.x);
|
||||||
setInBuffer(binormal, binormals, i);
|
tangents.put((i * 4) + 1, tangent.y);
|
||||||
|
tangents.put((i * 4) + 2, tangent.z);
|
||||||
|
tangents.put((i * 4) + 3, wCoord);
|
||||||
|
|
||||||
|
// setInBuffer(binormal, binormals, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mesh.setBuffer(Type.Tangent, 3, tangents);
|
mesh.setBuffer(Type.Tangent, 4, tangents);
|
||||||
if (!approxTangent) mesh.setBuffer(Type.Binormal, 3, binormals);
|
// if (!approxTangent) mesh.setBuffer(Type.Binormal, 3, binormals);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Mesh genTbnLines(Mesh mesh, float scale) {
|
public static Mesh genTbnLines(Mesh mesh, float scale) {
|
||||||
|
@ -74,7 +74,9 @@ public class AwtMouseInput implements MouseInput, MouseListener, MouseWheelListe
|
|||||||
|
|
||||||
private Component component;
|
private Component component;
|
||||||
|
|
||||||
private ArrayList<MouseButtonEvent> eventQueue = new ArrayList<MouseButtonEvent>();
|
private final ArrayList<MouseButtonEvent> eventQueue = new ArrayList<MouseButtonEvent>();
|
||||||
|
private final ArrayList<MouseButtonEvent> eventQueueCopy = new ArrayList<MouseButtonEvent>();
|
||||||
|
|
||||||
private int lastEventX;
|
private int lastEventX;
|
||||||
private int lastEventY;
|
private int lastEventY;
|
||||||
private int lastEventWheel;
|
private int lastEventWheel;
|
||||||
@ -110,6 +112,8 @@ public class AwtMouseInput implements MouseInput, MouseListener, MouseWheelListe
|
|||||||
component.removeMouseMotionListener(this);
|
component.removeMouseMotionListener(this);
|
||||||
component.removeMouseWheelListener(this);
|
component.removeMouseWheelListener(this);
|
||||||
|
|
||||||
|
eventQueue.clear();
|
||||||
|
|
||||||
wheelPos = 0;
|
wheelPos = 0;
|
||||||
isRecentering = false;
|
isRecentering = false;
|
||||||
eventsSinceRecenter = 0;
|
eventsSinceRecenter = 0;
|
||||||
@ -160,7 +164,6 @@ public class AwtMouseInput implements MouseInput, MouseListener, MouseWheelListe
|
|||||||
recenterMouse(component);
|
recenterMouse(component);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,13 +189,18 @@ public class AwtMouseInput implements MouseInput, MouseListener, MouseWheelListe
|
|||||||
cursorMoved = false;
|
cursorMoved = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int size = eventQueue.size();
|
synchronized (eventQueue){
|
||||||
for (int i = 0; i < size; i++){
|
eventQueueCopy.clear();
|
||||||
listener.onMouseButtonEvent(eventQueue.get(i));
|
eventQueueCopy.addAll(eventQueue);
|
||||||
}
|
|
||||||
eventQueue.clear();
|
eventQueue.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int size = eventQueueCopy.size();
|
||||||
|
for (int i = 0; i < size; i++){
|
||||||
|
listener.onMouseButtonEvent(eventQueueCopy.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Cursor getTransparentCursor() {
|
private Cursor getTransparentCursor() {
|
||||||
if (transparentCursor == null){
|
if (transparentCursor == null){
|
||||||
BufferedImage cursorImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
|
BufferedImage cursorImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
|
||||||
@ -224,14 +232,18 @@ public class AwtMouseInput implements MouseInput, MouseListener, MouseWheelListe
|
|||||||
public void mousePressed(MouseEvent arg0) {
|
public void mousePressed(MouseEvent arg0) {
|
||||||
MouseButtonEvent evt = new MouseButtonEvent(getJMEButtonIndex(arg0), true, arg0.getX(), arg0.getY());
|
MouseButtonEvent evt = new MouseButtonEvent(getJMEButtonIndex(arg0), true, arg0.getX(), arg0.getY());
|
||||||
evt.setTime(arg0.getWhen());
|
evt.setTime(arg0.getWhen());
|
||||||
|
synchronized (eventQueue){
|
||||||
eventQueue.add(evt);
|
eventQueue.add(evt);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void mouseReleased(MouseEvent arg0) {
|
public void mouseReleased(MouseEvent arg0) {
|
||||||
MouseButtonEvent evt = new MouseButtonEvent(getJMEButtonIndex(arg0), false, arg0.getX(), arg0.getY());
|
MouseButtonEvent evt = new MouseButtonEvent(getJMEButtonIndex(arg0), false, arg0.getX(), arg0.getY());
|
||||||
evt.setTime(arg0.getWhen());
|
evt.setTime(arg0.getWhen());
|
||||||
|
synchronized (eventQueue){
|
||||||
eventQueue.add(evt);
|
eventQueue.add(evt);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void mouseEntered(MouseEvent arg0) {
|
public void mouseEntered(MouseEvent arg0) {
|
||||||
if (!visible)
|
if (!visible)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user