mirror of
https://github.com/processing/processing4.git
synced 2026-06-16 04:26:26 +02:00
Implemented automatic normal calculation in A3D (this closes issue 345)
This commit is contained in:
@@ -81,6 +81,9 @@ public interface PConstants {
|
||||
|
||||
|
||||
// material properties
|
||||
// TODO: check whether we still need them in PGraphicsAndroid3D and if yes
|
||||
// how the work in combination with the global material properties (ambient, diffuse,
|
||||
// emissive, specular colors).
|
||||
|
||||
// Ambient color (usually to be kept the same as diffuse)
|
||||
// fill(_) sets both ambient and diffuse.
|
||||
@@ -105,10 +108,10 @@ public interface PConstants {
|
||||
static public final int ER = 32;
|
||||
static public final int EG = 33;
|
||||
static public final int EB = 34;
|
||||
|
||||
// has this vertex been lit yet
|
||||
static public final int BEEN_LIT = 35;
|
||||
|
||||
|
||||
// has this vertex been assigned a normal yet
|
||||
static public final int HAS_NORMAL = 35;
|
||||
|
||||
static public final int VERTEX_FIELD_COUNT = 36;
|
||||
|
||||
|
||||
@@ -371,6 +374,27 @@ public interface PConstants {
|
||||
static final int SHAPE = 5;
|
||||
|
||||
|
||||
// normal modes.
|
||||
|
||||
/**
|
||||
* In the vertex mode, the user should specify a normal for
|
||||
* each vertex.
|
||||
*/
|
||||
static final int VERTEX = 6;
|
||||
|
||||
/**
|
||||
* Normal vectors are automatically calculated if not set.
|
||||
*/
|
||||
static final int AUTO = 7;
|
||||
|
||||
/**
|
||||
* ... and, the constant SHAPE from text placement modes
|
||||
* is used to set the SHAPE normal mode, where the same shape
|
||||
* is used for all the vertices in a shape. This conflict in the
|
||||
* name of constants should be solved (TODO).
|
||||
*/
|
||||
|
||||
|
||||
// text alignment modes
|
||||
// are inherited from LEFT, CENTER, RIGHT
|
||||
|
||||
|
||||
@@ -403,6 +403,8 @@ public class PGraphics extends PImage implements PConstants {
|
||||
protected float vertices[][] =
|
||||
new float[DEFAULT_VERTICES][VERTEX_FIELD_COUNT];
|
||||
protected int vertexCount; // total number of vertices
|
||||
|
||||
// This array allows to assign a different texture for each vertex.
|
||||
protected PImage verticesTexture[] = new PImage[DEFAULT_VERTICES];
|
||||
|
||||
// ........................................................
|
||||
@@ -490,19 +492,9 @@ public class PGraphics extends PImage implements PConstants {
|
||||
|
||||
// ........................................................
|
||||
|
||||
/// normal calculated per triangle
|
||||
static protected final int NORMAL_MODE_AUTO = 0;
|
||||
/// one normal manually specified per shape
|
||||
static protected final int NORMAL_MODE_SHAPE = 1;
|
||||
/// normals specified for each shape vertex
|
||||
static protected final int NORMAL_MODE_VERTEX = 2;
|
||||
|
||||
/// Current mode for normals, one of AUTO, SHAPE, or VERTEX
|
||||
protected int normalMode;
|
||||
|
||||
/// Keep track of how many calls to normal, to determine the mode.
|
||||
//protected int normalCount;
|
||||
|
||||
|
||||
/** Current normal vector. */
|
||||
public float normalX, normalY, normalZ;
|
||||
|
||||
@@ -703,6 +695,8 @@ public class PGraphics extends PImage implements PConstants {
|
||||
|
||||
rectMode(CORNER);
|
||||
ellipseMode(DIAMETER);
|
||||
|
||||
normalMode = AUTO;
|
||||
|
||||
// no current font
|
||||
textFont = null;
|
||||
@@ -875,6 +869,14 @@ public class PGraphics extends PImage implements PConstants {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the normal mode, either AUTO, SHAPE or VERTEX.
|
||||
*/
|
||||
public void normalMode(int mode) {
|
||||
this.normalMode = mode;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the current normal vector. Only applies with 3D rendering
|
||||
* and inside a beginShape/endShape block.
|
||||
@@ -883,10 +885,6 @@ public class PGraphics extends PImage implements PConstants {
|
||||
* allowing you to specify a vector perpendicular to the surface
|
||||
* of the shape, which determines how lighting affects it.
|
||||
* <P/>
|
||||
* For the most part, PGraphics3D will attempt to automatically
|
||||
* assign normals to shapes, but since that's imperfect,
|
||||
* this is a better option when you want more control.
|
||||
* <P/>
|
||||
* For people familiar with OpenGL, this function is basically
|
||||
* identical to glNormal3f().
|
||||
*/
|
||||
@@ -894,25 +892,6 @@ public class PGraphics extends PImage implements PConstants {
|
||||
normalX = nx;
|
||||
normalY = ny;
|
||||
normalZ = nz;
|
||||
|
||||
// if drawing a shape and the normal hasn't been set yet,
|
||||
// then we need to set the normals for each vertex so far
|
||||
if (shape != 0) {
|
||||
if (normalMode == NORMAL_MODE_AUTO) {
|
||||
// either they set the normals, or they don't [0149]
|
||||
// for (int i = vertex_start; i < vertexCount; i++) {
|
||||
// vertices[i][NX] = normalX;
|
||||
// vertices[i][NY] = normalY;
|
||||
// vertices[i][NZ] = normalZ;
|
||||
// }
|
||||
// One normal per begin/end shape
|
||||
normalMode = NORMAL_MODE_SHAPE;
|
||||
|
||||
} else if (normalMode == NORMAL_MODE_SHAPE) {
|
||||
// a separate normal for each vertex
|
||||
normalMode = NORMAL_MODE_VERTEX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1078,11 +1057,31 @@ public class PGraphics extends PImage implements PConstants {
|
||||
vertex[V] = textureV;
|
||||
}
|
||||
|
||||
float norm2 = normalX * normalX + normalY * normalY + normalZ * normalZ;
|
||||
if (norm2 < EPSILON) {
|
||||
vertex[HAS_NORMAL] = 0;
|
||||
} else {
|
||||
if (Math.abs(norm2 - 1) < EPSILON) {
|
||||
float norm = PApplet.sqrt(norm2);
|
||||
normalX /= norm;
|
||||
normalY /= norm;
|
||||
normalZ /= norm;
|
||||
}
|
||||
vertex[HAS_NORMAL] = 1;
|
||||
}
|
||||
|
||||
vertex[NX] = normalX;
|
||||
vertex[NY] = normalY;
|
||||
vertex[NZ] = normalZ;
|
||||
|
||||
vertex[BEEN_LIT] = 0;
|
||||
|
||||
if (normalMode == VERTEX || normalMode == AUTO) {
|
||||
// The AUTO mode works as the VERTEX mode (it allows the user to specify
|
||||
// per-vertex normals) but if there are triangles where some of the vertices
|
||||
// have no normal, then it will calculate the normal for that triangle (in
|
||||
// the renderTriangles() method of PGraphicsAndroid3D).
|
||||
normalX = normalY = normalZ = 0;
|
||||
}
|
||||
|
||||
|
||||
verticesTexture[vertexCount] = textureImage;
|
||||
|
||||
|
||||
@@ -163,7 +163,8 @@ public class PGraphicsAndroid3D extends PGraphics {
|
||||
/** Used to store empty values to be passed when a light has no
|
||||
ambient, diffuse or specular component **/
|
||||
public float[] zeroLight = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
public float[] baseLight = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
/** Default ambient light for the entire scene **/
|
||||
public float[] baseLight = { 0.05f, 0.05f, 0.05f, 1.0f };
|
||||
|
||||
boolean lightsAllocated = false;
|
||||
|
||||
@@ -866,6 +867,9 @@ public class PGraphicsAndroid3D extends PGraphics {
|
||||
|
||||
shapeFirst = 0;
|
||||
|
||||
// The current normal vector is set to zero.
|
||||
normalX = normalY = normalZ = 0;
|
||||
|
||||
if (primarySurface) {
|
||||
// This instance of PGraphicsAndroid3D is the primary (onscreen) drawing surface.
|
||||
|
||||
@@ -1164,7 +1168,7 @@ public class PGraphicsAndroid3D extends PGraphics {
|
||||
textureImage = null;
|
||||
textureImagePrev = null;
|
||||
|
||||
normalMode = NORMAL_MODE_AUTO;
|
||||
normalMode = AUTO;
|
||||
}
|
||||
|
||||
// public void edge(boolean e)
|
||||
@@ -1232,6 +1236,10 @@ public class PGraphicsAndroid3D extends PGraphics {
|
||||
}
|
||||
|
||||
shape = 0;
|
||||
|
||||
if (normalMode == SHAPE) {
|
||||
normalX = normalY = normalZ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected void endShapeStroke(int mode) {
|
||||
@@ -1892,6 +1900,41 @@ public class PGraphicsAndroid3D extends PGraphics {
|
||||
float b[] = vertices[triangles[i][VERTEX2]];
|
||||
float c[] = vertices[triangles[i][VERTEX3]];
|
||||
|
||||
if (normalMode == AUTO && (a[HAS_NORMAL] == 0 ||
|
||||
b[HAS_NORMAL] == 0 ||
|
||||
c[HAS_NORMAL] == 0)) {
|
||||
// Ok, some of the vertices defining the current triangle have not been
|
||||
// assigned a normal, and the normal mode is AUTO, so we generate the normal
|
||||
// for all the vertices of this triangle.
|
||||
|
||||
// Assuming CW vertex ordering, so the outside direction for this triangle
|
||||
// should be given by the cross product (b - a) x (b - c):
|
||||
float x1 = b[X] - a[X];
|
||||
float y1 = b[Y] - a[Y];
|
||||
float z1 = b[Z] - a[Z];
|
||||
|
||||
float x2 = b[X] - c[X];
|
||||
float y2 = b[Y] - c[Y];
|
||||
float z2 = b[Z] - c[Z];
|
||||
|
||||
float cx = y1 * z2 - y2 * z1;
|
||||
float cy = z1 * x2 - z2 * x1;
|
||||
float cz = x1 * y2 - x2 * y1;
|
||||
|
||||
float norm = PApplet.sqrt(cx * cx + cy * cy + cz * cz);
|
||||
|
||||
cx /= norm;
|
||||
cy /= norm;
|
||||
cz /= norm;
|
||||
|
||||
// Same normal vector assigned to the three vertices:
|
||||
a[NX] = b[NX] = c[NX] = cx;
|
||||
a[NY] = b[NY] = c[NY] = cy;
|
||||
a[NZ] = b[NZ] = c[NZ] = cz;
|
||||
|
||||
a[HAS_NORMAL] = b[HAS_NORMAL] = c[HAS_NORMAL] = 1;
|
||||
}
|
||||
|
||||
float uscale = 1.0f;
|
||||
float vscale = 1.0f;
|
||||
float cx = 0.0f;
|
||||
@@ -5574,9 +5617,9 @@ public class PGraphicsAndroid3D extends PGraphics {
|
||||
float t = 1.0f - c;
|
||||
|
||||
mult((t*rx*rx) + c, (t*rx*ry) - (s*rz), (t*rx*rz) + (s*ry), 0,
|
||||
(t*rx*ry) + (s*rz), (t*ry*ry) + c, (t*ry*rz) - (s*rx), 0,
|
||||
(t*rx*rz) - (s*ry), (t*ry*rz) + (s*rx), (t*rz*rz) + c, 0,
|
||||
0, 0, 0, 1);
|
||||
(t*rx*ry) + (s*rz), (t*ry*ry) + c, (t*ry*rz) - (s*rx), 0,
|
||||
(t*rx*rz) - (s*ry), (t*ry*rz) + (s*rx), (t*rz*rz) + c, 0,
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
|
||||
public void scale(float sx, float sy, float sz) {
|
||||
|
||||
@@ -2317,7 +2317,7 @@ public class PShape3D extends PShape implements PConstants {
|
||||
// Loading texture map.
|
||||
String texname = elements[1];
|
||||
currentMtl.kdMap = parent.loadImage(texname);
|
||||
// Texture orientation in Processing is inverted with respecto to OpenGL.
|
||||
// Texture orientation in Processing is inverted with respect to OpenGL.
|
||||
currentMtl.kdMap.getTexture().setFlippedY(true);
|
||||
} else if (elements[0].equals("Ka") && elements.length > 3) {
|
||||
// The ambient color of the material
|
||||
@@ -2358,6 +2358,9 @@ public class PShape3D extends PShape implements PConstants {
|
||||
int tMode0 = a3d.textureMode;
|
||||
a3d.textureMode = NORMAL;
|
||||
|
||||
int nMode0 = a3d.normalMode;
|
||||
a3d.normalMode = AUTO;
|
||||
|
||||
// Using RGB mode for coloring.
|
||||
int cMode0 = a3d.colorMode;
|
||||
a3d.colorMode = RGB;
|
||||
@@ -2502,9 +2505,10 @@ public class PShape3D extends PShape implements PConstants {
|
||||
|
||||
a3d.endShapeRecorderImpl(this);
|
||||
|
||||
// Restore texture and color modes.
|
||||
// Restore texture, color, and normal modes.
|
||||
a3d.textureMode = tMode0;
|
||||
a3d.colorMode = cMode0;
|
||||
a3d.normalMode = nMode0;
|
||||
|
||||
// Restore colors
|
||||
a3d.calcR = specularR0;
|
||||
|
||||
Reference in New Issue
Block a user