mirror of
https://github.com/processing/processing4.git
synced 2026-06-16 04:26:26 +02:00
Better handling of geometric transformations in PShape3D.
This commit is contained in:
@@ -189,10 +189,10 @@ public class PFramebuffer implements PConstants {
|
||||
public void finish() {
|
||||
if (noDepth) {
|
||||
// No need to clear depth buffer because depth testing was disabled.
|
||||
if (pg.hintEnabled(DISABLE_DEPTH_TEST)) {
|
||||
pgl.glDisable(PGL.GL_DEPTH_TEST);
|
||||
if (pg.hintEnabled(ENABLE_DEPTH_TEST)) {
|
||||
pgl.glEnable(PGL.GL_DEPTH_TEST);
|
||||
} else {
|
||||
pgl.glEnable(PGL.GL_DEPTH_TEST);
|
||||
pgl.glDisable(PGL.GL_DEPTH_TEST);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,6 +342,8 @@ public class PGraphicsOpenGL extends PGraphics {
|
||||
|
||||
// Bezier and Catmull-Rom curves
|
||||
|
||||
// TODO: move bezier/curve vertex generation to InGeometry.
|
||||
|
||||
protected boolean bezierInited = false;
|
||||
public int bezierDetail = 20;
|
||||
protected PMatrix3D bezierDrawMatrix;
|
||||
@@ -4509,8 +4511,7 @@ public class PGraphicsOpenGL extends PGraphics {
|
||||
|
||||
|
||||
protected void backgroundImpl() {
|
||||
tessGeo.clear();
|
||||
texCache.clear();
|
||||
flush();
|
||||
|
||||
pgl.glDepthMask(true);
|
||||
pgl.glClearColor(0, 0, 0, 0);
|
||||
@@ -4521,7 +4522,7 @@ public class PGraphicsOpenGL extends PGraphics {
|
||||
pgl.glDepthMask(true);
|
||||
}
|
||||
|
||||
pgl.glClearColor(backgroundR, backgroundG, backgroundB, 1);
|
||||
pgl.glClearColor(backgroundR, backgroundG, backgroundB, backgroundA);
|
||||
pgl.glClear(PGL.GL_COLOR_BUFFER_BIT);
|
||||
if (0 < parent.frameCount) {
|
||||
clearColorBuffer = true;
|
||||
@@ -6160,13 +6161,18 @@ public class PGraphicsOpenGL extends PGraphics {
|
||||
public int[] emissive;
|
||||
public float[] shininess;
|
||||
|
||||
// TODO: this should probably go in the TessGeometry class
|
||||
// TODO: this should probably go in the TessGeometry class, or maybe not...
|
||||
public int[][] edges;
|
||||
|
||||
// For later, to be used by libraries...
|
||||
//public float[][] mtexcoords;
|
||||
//public float[][] attributes;
|
||||
|
||||
// Internally used by the addVertex() methods.
|
||||
protected int fillColor;
|
||||
protected int strokeColor;
|
||||
protected float strokeWeight;
|
||||
protected int ambientColor;
|
||||
protected int specularColor;
|
||||
protected int emissiveColor;
|
||||
protected float shininessFactor;
|
||||
|
||||
public InGeometry(int mode) {
|
||||
renderMode = mode;
|
||||
allocate();
|
||||
@@ -6260,8 +6266,7 @@ public class PGraphicsOpenGL extends PGraphics {
|
||||
public boolean isFull() {
|
||||
return PGL.MAX_TESS_VERTICES <= vertexCount;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public int addVertex(float x, float y,
|
||||
int fcolor,
|
||||
float u, float v,
|
||||
@@ -6277,6 +6282,17 @@ public class PGraphicsOpenGL extends PGraphics {
|
||||
code);
|
||||
}
|
||||
|
||||
public int addVertex(float x, float y,
|
||||
float u, float v,
|
||||
int code) {
|
||||
return addVertex(x, y,
|
||||
fillColor,
|
||||
u, v,
|
||||
strokeColor, strokeWeight,
|
||||
ambientColor, specularColor, emissiveColor, shininessFactor,
|
||||
code);
|
||||
}
|
||||
|
||||
public int addVertex(float x, float y,
|
||||
int fcolor,
|
||||
int scolor, float sweight,
|
||||
@@ -6290,7 +6306,16 @@ public class PGraphicsOpenGL extends PGraphics {
|
||||
am, sp, em, shine,
|
||||
code);
|
||||
}
|
||||
|
||||
|
||||
public int addVertex(float x, float y,
|
||||
int code) {
|
||||
return addVertex(x, y,
|
||||
fillColor,
|
||||
strokeColor, strokeWeight,
|
||||
ambientColor, specularColor, emissiveColor, shininessFactor,
|
||||
code);
|
||||
}
|
||||
|
||||
public int addVertex(float x, float y, float z,
|
||||
int fcolor,
|
||||
float nx, float ny, float nz,
|
||||
@@ -6332,6 +6357,19 @@ public class PGraphicsOpenGL extends PGraphics {
|
||||
|
||||
return lastVertex;
|
||||
}
|
||||
|
||||
public int addVertex(float x, float y, float z,
|
||||
float nx, float ny, float nz,
|
||||
float u, float v,
|
||||
int code) {
|
||||
return addVertex(x, y, z,
|
||||
fillColor,
|
||||
nx, ny, nz,
|
||||
u, v,
|
||||
strokeColor, strokeWeight,
|
||||
ambientColor, specularColor, emissiveColor, shininessFactor,
|
||||
code);
|
||||
}
|
||||
|
||||
public int javaToNativeARGB(int color) {
|
||||
if (PGL.BIG_ENDIAN) {
|
||||
@@ -6760,12 +6798,11 @@ public class PGraphicsOpenGL extends PGraphics {
|
||||
}
|
||||
}
|
||||
|
||||
// Primitive generation
|
||||
|
||||
public void generateEllipse(int ellipseMode, float a, float b, float c, float d,
|
||||
boolean fill, int fillColor,
|
||||
boolean stroke, int strokeColor, float strokeWeight,
|
||||
int ambient, int specular, int emissive, float shininess) {
|
||||
int ambientColor, int specularColor, int emissiveColor,
|
||||
float shininessFactor) {
|
||||
float x = a;
|
||||
float y = b;
|
||||
float w = c;
|
||||
@@ -6795,7 +6832,15 @@ public class PGraphicsOpenGL extends PGraphics {
|
||||
y += h;
|
||||
h = -h;
|
||||
}
|
||||
|
||||
|
||||
this.fillColor = fillColor;
|
||||
this.strokeColor = strokeColor;
|
||||
this.strokeWeight = strokeWeight;
|
||||
this.ambientColor = ambientColor;
|
||||
this.specularColor = specularColor;
|
||||
this.emissiveColor = emissiveColor;
|
||||
this.shininessFactor = shininessFactor;
|
||||
|
||||
float radiusH = w / 2;
|
||||
float radiusV = h / 2;
|
||||
|
||||
@@ -6814,10 +6859,7 @@ public class PGraphicsOpenGL extends PGraphics {
|
||||
float inc = (float) PGraphicsOpenGL.SINCOS_LENGTH / accuracy;
|
||||
|
||||
if (fill) {
|
||||
addVertex(centerX, centerY,
|
||||
fillColor, strokeColor, strokeWeight,
|
||||
ambient, specular, emissive, shininess,
|
||||
VERTEX);
|
||||
addVertex(centerX, centerY, VERTEX);
|
||||
}
|
||||
int idx0, pidx, idx;
|
||||
idx0 = pidx = idx = 0;
|
||||
@@ -6825,8 +6867,6 @@ public class PGraphicsOpenGL extends PGraphics {
|
||||
for (int i = 0; i < accuracy; i++) {
|
||||
idx = addVertex(centerX + PGraphicsOpenGL.cosLUT[(int) val] * radiusH,
|
||||
centerY + PGraphicsOpenGL.sinLUT[(int) val] * radiusV,
|
||||
fillColor, strokeColor, strokeWeight,
|
||||
ambient, specular, emissive, shininess,
|
||||
VERTEX);
|
||||
val = (val + inc) % PGraphicsOpenGL.SINCOS_LENGTH;
|
||||
|
||||
@@ -6841,12 +6881,82 @@ public class PGraphicsOpenGL extends PGraphics {
|
||||
// Back to the beginning
|
||||
addVertex(centerX + PGraphicsOpenGL.cosLUT[0] * radiusH,
|
||||
centerY + PGraphicsOpenGL.sinLUT[0] * radiusV,
|
||||
fillColor, strokeColor, strokeWeight,
|
||||
ambient, specular, emissive, shininess,
|
||||
VERTEX);
|
||||
if (stroke) addEdge(idx, idx0, false, true);
|
||||
}
|
||||
|
||||
public void generateBox(float w, float h, float d,
|
||||
boolean fill, int fillColor,
|
||||
boolean stroke, int strokeColor, float strokeWeight,
|
||||
int ambientColor, int specularColor, int emissiveColor,
|
||||
float shininessFactor) {
|
||||
float x1 = -w/2f; float x2 = w/2f;
|
||||
float y1 = -h/2f; float y2 = h/2f;
|
||||
float z1 = -d/2f; float z2 = d/2f;
|
||||
|
||||
this.fillColor = fillColor;
|
||||
this.strokeColor = strokeColor;
|
||||
this.strokeWeight = strokeWeight;
|
||||
this.ambientColor = ambientColor;
|
||||
this.specularColor = specularColor;
|
||||
this.emissiveColor = emissiveColor;
|
||||
this.shininessFactor = shininessFactor;
|
||||
|
||||
if (fill || stroke) {
|
||||
// front face
|
||||
addVertex(x1, y1, z1, 0, 0, 1, 0, 0, VERTEX);
|
||||
addVertex(x2, y1, z1, 0, 0, 1, 1, 0, VERTEX);
|
||||
addVertex(x2, y2, z1, 0, 0, 1, 1, 1, VERTEX);
|
||||
addVertex(x1, y2, z1, 0, 0, 1, 0, 1, VERTEX);
|
||||
|
||||
// right face
|
||||
addVertex(x2, y1, z1, 1, 0, 0, 0, 0, VERTEX);
|
||||
addVertex(x2, y1, z2, 1, 0, 0, 1, 0, VERTEX);
|
||||
addVertex(x2, y2, z2, 1, 0, 0, 1, 1, VERTEX);
|
||||
addVertex(x2, y2, z1, 1, 0, 0, 0, 1, VERTEX);
|
||||
|
||||
// back face
|
||||
addVertex(x2, y1, z2, 0, 0, -1, 0, 0, VERTEX);
|
||||
addVertex(x1, y1, z2, 0, 0, -1, 1, 0, VERTEX);
|
||||
addVertex(x1, y2, z2, 0, 0, -1, 1, 1, VERTEX);
|
||||
addVertex(x2, y2, z2, 0, 0, -1, 0, 1, VERTEX);
|
||||
|
||||
// left face
|
||||
addVertex(x1, y1, z2, -1, 0, 0, 0, 0, VERTEX);
|
||||
addVertex(x1, y1, z1, -1, 0, 0, 1, 0, VERTEX);
|
||||
addVertex(x1, y2, z1, -1, 0, 0, 1, 1, VERTEX);
|
||||
addVertex(x1, y2, z2, -1, 0, 0, 0, 1, VERTEX);;
|
||||
|
||||
// top face
|
||||
addVertex(x1, y1, z2, 0, 1, 0, 0, 0, VERTEX);
|
||||
addVertex(x2, y1, z2, 0, 1, 0, 1, 0, VERTEX);
|
||||
addVertex(x2, y1, z1, 0, 1, 0, 1, 1, VERTEX);
|
||||
addVertex(x1, y1, z1, 0, 1, 0, 0, 1, VERTEX);
|
||||
|
||||
// bottom face
|
||||
addVertex(x1, y2, z1, 0, -1, 0, 0, 0, VERTEX);
|
||||
addVertex(x2, y2, z1, 0, -1, 0, 1, 0, VERTEX);
|
||||
addVertex(x2, y2, z2, 0, -1, 0, 1, 1, VERTEX);
|
||||
addVertex(x1, y2, z2, 0, -1, 0, 0, 1, VERTEX);
|
||||
}
|
||||
|
||||
if (stroke) {
|
||||
addEdge(0, 1, true, false);
|
||||
addEdge(1, 2, false, false);
|
||||
addEdge(2, 3, false, false);
|
||||
addEdge(3, 0, false, false);
|
||||
|
||||
addEdge(0, 9, false, false);
|
||||
addEdge(1, 8, false, false);
|
||||
addEdge(2, 11, false, false);
|
||||
addEdge(3, 10, false, false);
|
||||
|
||||
addEdge( 8, 9, false, false);
|
||||
addEdge( 9, 10, false, false);
|
||||
addEdge(10, 11, false, false);
|
||||
addEdge(11, 8, false, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Holds tessellated data for fill, line and point geometry.
|
||||
@@ -7903,6 +8013,14 @@ public class PGraphicsOpenGL extends PGraphics {
|
||||
return fillVertexCount + lineVertexCount + pointVertexCount;
|
||||
}
|
||||
|
||||
public void applyMatrix(PMatrix tr) {
|
||||
if (tr instanceof PMatrix2D) {
|
||||
applyMatrix((PMatrix2D) tr);
|
||||
} else if (tr instanceof PMatrix3D) {
|
||||
applyMatrix((PMatrix3D) tr);
|
||||
}
|
||||
}
|
||||
|
||||
public void applyMatrix(PMatrix2D tr) {
|
||||
if (0 < fillVertexCount) {
|
||||
int index;
|
||||
|
||||
@@ -69,11 +69,15 @@ import java.util.Hashtable;
|
||||
* Other formats to consider:
|
||||
* AMF: http://en.wikipedia.org/wiki/Additive_Manufacturing_File_Format
|
||||
* STL: http://en.wikipedia.org/wiki/STL_(file_format)
|
||||
* OFF: http://en.wikipedia.org/wiki/STL_(file_format)
|
||||
* OFF: http://people.sc.fsu.edu/~jburkardt/data/off/off.html(file_format)
|
||||
* DXF: http://en.wikipedia.org/wiki/AutoCAD_DXF
|
||||
*/
|
||||
|
||||
public class PShape3D extends PShape {
|
||||
static protected final int TRANSLATE = 0;
|
||||
static protected final int ROTATE = 1;
|
||||
static protected final int SCALE = 2;
|
||||
static protected final int MATRIX = 3;
|
||||
|
||||
protected PGraphicsOpenGL pg;
|
||||
protected PGL pgl;
|
||||
protected PGL.Context context; // The context that created this shape.
|
||||
@@ -244,6 +248,15 @@ public class PShape3D extends PShape {
|
||||
protected int ellipseMode;
|
||||
protected int shapeMode;
|
||||
protected int imageMode;
|
||||
|
||||
// ........................................................
|
||||
|
||||
// Geometric transformations
|
||||
|
||||
protected PMatrix transform;
|
||||
protected boolean cacheTransformations;
|
||||
|
||||
|
||||
|
||||
public PShape3D(PApplet parent, int family) {
|
||||
pg = (PGraphicsOpenGL)parent.g;
|
||||
@@ -318,6 +331,13 @@ public class PShape3D extends PShape {
|
||||
normalZ = 1;
|
||||
|
||||
normalMode = NORMAL_MODE_AUTO;
|
||||
|
||||
cacheTransformations = pg.hintEnabled(ENABLE_TRANSFORM_CACHE);
|
||||
|
||||
if (family == GROUP) {
|
||||
// GROUP shapes are always marked as ended.
|
||||
shapeEnded = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -343,7 +363,9 @@ public class PShape3D extends PShape {
|
||||
child.updateRoot(root);
|
||||
root.tessellated = false;
|
||||
tessellated = false;
|
||||
((PShape3D)child).tessellated = false;
|
||||
if (!cacheTransformations && ((PShape3D)child).hasMatrix()) {
|
||||
setChildHasMatrix(true);
|
||||
}
|
||||
} else {
|
||||
PGraphics.showWarning("Cannot add child shape to non-group shape.");
|
||||
}
|
||||
@@ -1333,6 +1355,9 @@ public class PShape3D extends PShape {
|
||||
// Geometric transformations
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// TODO: Remove center, add function to get center from point...
|
||||
public void center(float cx, float cy) {
|
||||
if (shapeEnded) {
|
||||
updateTesselation();
|
||||
@@ -1347,7 +1372,7 @@ public class PShape3D extends PShape {
|
||||
float tx = cx - center.x;
|
||||
float ty = cy - center.y;
|
||||
|
||||
childHasMatrix();
|
||||
setChildHasMatrix(true);
|
||||
applyMatrix = true;
|
||||
super.translate(tx, ty);
|
||||
} else {
|
||||
@@ -1381,7 +1406,7 @@ public class PShape3D extends PShape {
|
||||
float ty = cy - center0.y;
|
||||
float tz = cz - center0.z;
|
||||
|
||||
childHasMatrix();
|
||||
setChildHasMatrix(true);
|
||||
applyMatrix = true;
|
||||
super.translate(tx, ty, tz);
|
||||
} else {
|
||||
@@ -1409,306 +1434,49 @@ public class PShape3D extends PShape {
|
||||
}
|
||||
return count;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
public void translate(float tx, float ty) {
|
||||
if (shapeEnded) {
|
||||
updateTesselation();
|
||||
|
||||
if (family == GROUP) {
|
||||
childHasMatrix();
|
||||
applyMatrix = true;
|
||||
super.translate(tx, ty);
|
||||
} else {
|
||||
checkMatrix(2);
|
||||
matrix.reset();
|
||||
matrix.translate(tx, ty);
|
||||
tess.applyMatrix((PMatrix2D) matrix);
|
||||
|
||||
modified();
|
||||
if (0 < tess.fillVertexCount) {
|
||||
modifiedFillVertices = true;
|
||||
modifiedFillNormals = true;
|
||||
}
|
||||
if (0 < tess.lineVertexCount) {
|
||||
modifiedLineVertices = true;
|
||||
modifiedLineAttributes = true;
|
||||
}
|
||||
if (0 < tess.pointVertexCount) {
|
||||
modifiedPointVertices = true;
|
||||
modifiedPointNormals = true;
|
||||
}
|
||||
|
||||
// So the transformation is not applied again when drawing
|
||||
applyMatrix = false;
|
||||
}
|
||||
}
|
||||
transform(TRANSLATE, tx, ty);
|
||||
}
|
||||
|
||||
|
||||
public void translate(float tx, float ty, float tz) {
|
||||
if (shapeEnded) {
|
||||
updateTesselation();
|
||||
|
||||
if (family == GROUP) {
|
||||
childHasMatrix();
|
||||
applyMatrix = true;
|
||||
super.translate(tx, ty, tz);
|
||||
} else {
|
||||
checkMatrix(3);
|
||||
matrix.reset();
|
||||
matrix.translate(tx, ty, tz);
|
||||
tess.applyMatrix((PMatrix3D) matrix);
|
||||
|
||||
modified();
|
||||
if (0 < tess.fillVertexCount) {
|
||||
modifiedFillVertices = true;
|
||||
modifiedFillNormals = true;
|
||||
}
|
||||
if (0 < tess.lineVertexCount) {
|
||||
modifiedLineVertices = true;
|
||||
modifiedLineAttributes = true;
|
||||
}
|
||||
if (0 < tess.pointVertexCount) {
|
||||
modifiedPointVertices = true;
|
||||
modifiedPointNormals = true;
|
||||
}
|
||||
|
||||
// So the transformation is not applied again when drawing
|
||||
applyMatrix = false;
|
||||
}
|
||||
}
|
||||
transform(TRANSLATE, tx, ty, tz);
|
||||
}
|
||||
|
||||
|
||||
public void rotate(float angle) {
|
||||
if (shapeEnded) {
|
||||
updateTesselation();
|
||||
|
||||
if (family == GROUP) {
|
||||
childHasMatrix();
|
||||
applyMatrix = true;
|
||||
super.rotate(angle);
|
||||
} else {
|
||||
checkMatrix(2);
|
||||
matrix.reset();
|
||||
matrix.rotate(angle);
|
||||
tess.applyMatrix((PMatrix2D) matrix);
|
||||
|
||||
modified();
|
||||
if (0 < tess.fillVertexCount) {
|
||||
modifiedFillVertices = true;
|
||||
modifiedFillNormals = true;
|
||||
}
|
||||
if (0 < tess.lineVertexCount) {
|
||||
modifiedLineVertices = true;
|
||||
modifiedLineAttributes = true;
|
||||
}
|
||||
if (0 < tess.pointVertexCount) {
|
||||
modifiedPointVertices = true;
|
||||
modifiedPointNormals = true;
|
||||
}
|
||||
|
||||
// So the transformation is not applied again when drawing
|
||||
applyMatrix = false;
|
||||
}
|
||||
}
|
||||
transform(ROTATE, angle);
|
||||
}
|
||||
|
||||
|
||||
public void rotate(float angle, float v0, float v1, float v2) {
|
||||
if (shapeEnded) {
|
||||
updateTesselation();
|
||||
|
||||
if (family == GROUP) {
|
||||
childHasMatrix();
|
||||
applyMatrix = true;
|
||||
super.rotate(angle, v0, v1, v2);
|
||||
} else {
|
||||
checkMatrix(3);
|
||||
matrix.reset();
|
||||
matrix.rotate(angle, v0, v1, v2);
|
||||
tess.applyMatrix((PMatrix3D) matrix);
|
||||
|
||||
modified();
|
||||
if (0 < tess.fillVertexCount) {
|
||||
modifiedFillVertices = true;
|
||||
modifiedFillNormals = true;
|
||||
}
|
||||
if (0 < tess.lineVertexCount) {
|
||||
modifiedLineVertices = true;
|
||||
modifiedLineAttributes = true;
|
||||
}
|
||||
if (0 < tess.pointVertexCount) {
|
||||
modifiedPointVertices = true;
|
||||
modifiedPointNormals = true;
|
||||
}
|
||||
|
||||
// So the transformation is not applied again when drawing
|
||||
applyMatrix = false;
|
||||
}
|
||||
}
|
||||
transform(ROTATE, v0, v1, v2);
|
||||
}
|
||||
|
||||
|
||||
public void scale(float s) {
|
||||
if (shapeEnded) {
|
||||
updateTesselation();
|
||||
|
||||
if (family == GROUP) {
|
||||
childHasMatrix();
|
||||
applyMatrix = true;
|
||||
super.scale(s);
|
||||
} else {
|
||||
checkMatrix(2);
|
||||
matrix.reset();
|
||||
matrix.scale(s);
|
||||
tess.applyMatrix((PMatrix2D) matrix);
|
||||
|
||||
modified();
|
||||
if (0 < tess.fillVertexCount) {
|
||||
modifiedFillVertices = true;
|
||||
modifiedFillNormals = true;
|
||||
}
|
||||
if (0 < tess.lineVertexCount) {
|
||||
modifiedLineVertices = true;
|
||||
modifiedLineAttributes = true;
|
||||
}
|
||||
if (0 < tess.pointVertexCount) {
|
||||
modifiedPointVertices = true;
|
||||
modifiedPointNormals = true;
|
||||
}
|
||||
|
||||
// So the transformation is not applied again when drawing
|
||||
applyMatrix = false;
|
||||
}
|
||||
}
|
||||
transform(SCALE, s, s);
|
||||
}
|
||||
|
||||
|
||||
public void scale(float x, float y) {
|
||||
if (shapeEnded) {
|
||||
updateTesselation();
|
||||
|
||||
if (family == GROUP) {
|
||||
childHasMatrix();
|
||||
applyMatrix = true;
|
||||
super.scale(x, y);
|
||||
} else {
|
||||
checkMatrix(2);
|
||||
matrix.reset();
|
||||
matrix.scale(x, y);
|
||||
tess.applyMatrix((PMatrix2D) matrix);
|
||||
|
||||
modified();
|
||||
if (0 < tess.fillVertexCount) {
|
||||
modifiedFillVertices = true;
|
||||
modifiedFillNormals = true;
|
||||
}
|
||||
if (0 < tess.lineVertexCount) {
|
||||
modifiedLineVertices = true;
|
||||
modifiedLineAttributes = true;
|
||||
}
|
||||
if (0 < tess.pointVertexCount) {
|
||||
modifiedPointVertices = true;
|
||||
modifiedPointNormals = true;
|
||||
}
|
||||
|
||||
// So the transformation is not applied again when drawing
|
||||
applyMatrix = false;
|
||||
}
|
||||
}
|
||||
transform(SCALE, x, y);
|
||||
}
|
||||
|
||||
|
||||
public void scale(float x, float y, float z) {
|
||||
if (shapeEnded) {
|
||||
updateTesselation();
|
||||
|
||||
if (family == GROUP) {
|
||||
childHasMatrix();
|
||||
applyMatrix = true;
|
||||
super.scale(x, y, z);
|
||||
} else {
|
||||
checkMatrix(3);
|
||||
matrix.reset();
|
||||
matrix.scale(x, y, z);
|
||||
tess.applyMatrix((PMatrix3D) matrix);
|
||||
|
||||
modified();
|
||||
if (0 < tess.fillVertexCount) {
|
||||
modifiedFillVertices = true;
|
||||
modifiedFillNormals = true;
|
||||
}
|
||||
if (0 < tess.lineVertexCount) {
|
||||
modifiedLineVertices = true;
|
||||
modifiedLineAttributes = true;
|
||||
}
|
||||
if (0 < tess.pointVertexCount) {
|
||||
modifiedPointVertices = true;
|
||||
modifiedPointNormals = true;
|
||||
}
|
||||
|
||||
// So the transformation is not applied again when drawing
|
||||
applyMatrix = false;
|
||||
}
|
||||
}
|
||||
transform(SCALE, x, y, z);
|
||||
}
|
||||
|
||||
|
||||
public void applyMatrix(PMatrix source) {
|
||||
super.applyMatrix(source);
|
||||
}
|
||||
|
||||
|
||||
public void applyMatrix(PMatrix2D source) {
|
||||
super.applyMatrix(source);
|
||||
}
|
||||
|
||||
|
||||
public void applyMatrix(float n00, float n01, float n02,
|
||||
float n10, float n11, float n12) {
|
||||
if (shapeEnded) {
|
||||
updateTesselation();
|
||||
|
||||
if (family == GROUP) {
|
||||
childHasMatrix();
|
||||
applyMatrix = true;
|
||||
super.applyMatrix(n00, n01, n02,
|
||||
n10, n11, n12);
|
||||
} else {
|
||||
checkMatrix(2);
|
||||
matrix.reset();
|
||||
matrix.apply(n00, n01, n02,
|
||||
n10, n11, n12);
|
||||
tess.applyMatrix((PMatrix2D) matrix);
|
||||
|
||||
modified();
|
||||
if (0 < tess.fillVertexCount) {
|
||||
modifiedFillVertices = true;
|
||||
modifiedFillNormals = true;
|
||||
}
|
||||
if (0 < tess.lineVertexCount) {
|
||||
modifiedLineVertices = true;
|
||||
modifiedLineAttributes = true;
|
||||
}
|
||||
if (0 < tess.pointVertexCount) {
|
||||
modifiedPointVertices = true;
|
||||
modifiedPointNormals = true;
|
||||
}
|
||||
|
||||
// So the transformation is not applied again when drawing
|
||||
applyMatrix = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void apply(PMatrix3D source) {
|
||||
applyMatrix(source.m00, source.m01, source.m02, source.m03,
|
||||
source.m10, source.m11, source.m12, source.m13,
|
||||
source.m20, source.m21, source.m22, source.m23,
|
||||
source.m30, source.m31, source.m32, source.m33);
|
||||
transform(MATRIX, n00, n01, n02,
|
||||
n10, n11, n12);
|
||||
}
|
||||
|
||||
|
||||
@@ -1716,65 +1484,194 @@ public class PShape3D extends PShape {
|
||||
float n10, float n11, float n12, float n13,
|
||||
float n20, float n21, float n22, float n23,
|
||||
float n30, float n31, float n32, float n33) {
|
||||
if (shapeEnded) {
|
||||
updateTesselation();
|
||||
|
||||
if (family == GROUP) {
|
||||
childHasMatrix();
|
||||
applyMatrix = true;
|
||||
super.applyMatrix(n00, n01, n02, n03,
|
||||
n10, n11, n12, n13,
|
||||
n20, n21, n22, n23,
|
||||
n30, n31, n32, n33);
|
||||
} else {
|
||||
checkMatrix(3);
|
||||
matrix.reset();
|
||||
matrix.apply(n00, n01, n02, n03,
|
||||
n10, n11, n12, n13,
|
||||
n20, n21, n22, n23,
|
||||
n30, n31, n32, n33);
|
||||
tess.applyMatrix((PMatrix3D) matrix);
|
||||
|
||||
modified();
|
||||
if (0 < tess.fillVertexCount) {
|
||||
modifiedFillVertices = true;
|
||||
modifiedFillNormals = true;
|
||||
}
|
||||
if (0 < tess.lineVertexCount) {
|
||||
modifiedLineVertices = true;
|
||||
modifiedLineAttributes = true;
|
||||
}
|
||||
if (0 < tess.pointVertexCount) {
|
||||
modifiedPointVertices = true;
|
||||
modifiedPointNormals = true;
|
||||
}
|
||||
|
||||
// So the transformation is not applied again when drawing
|
||||
applyMatrix = false;
|
||||
}
|
||||
}
|
||||
transform(MATRIX, n00, n01, n02, n03,
|
||||
n10, n11, n12, n13,
|
||||
n20, n21, n22, n23,
|
||||
n30, n31, n32, n33);
|
||||
}
|
||||
|
||||
|
||||
public void resetMatrix() {
|
||||
// TODO
|
||||
// What to do in the case of geometry shapes?
|
||||
// In order to properly reset the transformation,
|
||||
// we need to have the last matrix applied, calculate
|
||||
// the inverse and apply on the tess object...
|
||||
//checkMatrix(2);
|
||||
//matrix.reset();
|
||||
}
|
||||
|
||||
|
||||
protected void childHasMatrix() {
|
||||
childHasMatrix = true;
|
||||
if (parent != null) {
|
||||
((PShape3D)parent).childHasMatrix();
|
||||
if (!cacheTransformations && parent != null && hasMatrix()) {
|
||||
((PShape3D)parent).setChildHasMatrix(false);
|
||||
}
|
||||
|
||||
if (shapeEnded) {
|
||||
updateTesselation();
|
||||
|
||||
if (family == GROUP) {
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
PShape3D child = (PShape3D) children[i];
|
||||
child.resetMatrix();
|
||||
}
|
||||
if (matrix != null) {
|
||||
matrix.reset();
|
||||
applyMatrix = false;
|
||||
}
|
||||
} else {
|
||||
if (cacheTransformations) {
|
||||
boolean res = matrix.invert();
|
||||
if (res) {
|
||||
applyMatrix(matrix);
|
||||
matrix.reset();
|
||||
} else {
|
||||
PGraphics.showWarning("The transformation matrix cannot be inverted");
|
||||
}
|
||||
} else {
|
||||
if (hasMatrix()) {
|
||||
matrix.reset();
|
||||
applyMatrix = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void transform(int type, float... args) {
|
||||
int dimensions;
|
||||
if (type == ROTATE) {
|
||||
dimensions = args.length == 1 ? 2 : 3;
|
||||
} else if (type == MATRIX) {
|
||||
dimensions = args.length == 6 ? 2 : 3;
|
||||
} else {
|
||||
dimensions = args.length;
|
||||
}
|
||||
transformImpl(type, dimensions, args);
|
||||
}
|
||||
|
||||
|
||||
protected void transformImpl(int type, int ncoords, float... args) {
|
||||
if (shapeEnded) {
|
||||
updateTesselation();
|
||||
|
||||
if (family == GROUP) {
|
||||
if (cacheTransformations) {
|
||||
// The transformation will be passed down to the child shapes
|
||||
// which will in turn apply it to the tessellated vertices,
|
||||
// so effectively becoming "cached" into the geometry itself.
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
PShape3D child = (PShape3D) children[i];
|
||||
child.transformImpl(type, ncoords, args);
|
||||
}
|
||||
} else {
|
||||
checkMatrix(ncoords);
|
||||
calcTransform(type, ncoords, args);
|
||||
applyMatrix = true;
|
||||
}
|
||||
} else {
|
||||
checkMatrix(ncoords);
|
||||
if (cacheTransformations) {
|
||||
calcTransform(type, ncoords, args);
|
||||
applyTransform(ncoords);
|
||||
|
||||
// Setting the applyMatrix variable to false so
|
||||
// that the transformation is not applied again
|
||||
// in the draw() method.
|
||||
applyMatrix = false;
|
||||
|
||||
// TODO: check the vertex cache stuff...
|
||||
modified();
|
||||
if (0 < tess.fillVertexCount) {
|
||||
modifiedFillVertices = true;
|
||||
modifiedFillNormals = true;
|
||||
}
|
||||
if (0 < tess.lineVertexCount) {
|
||||
modifiedLineVertices = true;
|
||||
modifiedLineAttributes = true;
|
||||
}
|
||||
if (0 < tess.pointVertexCount) {
|
||||
modifiedPointVertices = true;
|
||||
modifiedPointNormals = true;
|
||||
}
|
||||
} else {
|
||||
// The transformation will be applied in draw().
|
||||
calcTransform(type, ncoords, args);
|
||||
applyMatrix = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!cacheTransformations && parent != null && hasMatrix()) {
|
||||
// Making sure that the parent shapes (if any) know that
|
||||
// this shape has a transformation matrix to be applied
|
||||
// in draw().
|
||||
((PShape3D)parent).setChildHasMatrix(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void calcTransform(int type, int dimensions, float... args) {
|
||||
if (transform == null) {
|
||||
if (dimensions == 2) {
|
||||
transform = new PMatrix2D();
|
||||
} else {
|
||||
transform = new PMatrix3D();
|
||||
}
|
||||
} else {
|
||||
transform.reset();
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case TRANSLATE:
|
||||
if (dimensions == 3) {
|
||||
transform.translate(args[0], args[1], args[2]);
|
||||
} else {
|
||||
transform.translate(args[0], args[1]);
|
||||
}
|
||||
break;
|
||||
case ROTATE:
|
||||
if (dimensions == 3) {
|
||||
transform.rotate(args[0], args[1], args[2], args[3]);
|
||||
} else {
|
||||
transform.rotate(args[0]);
|
||||
}
|
||||
break;
|
||||
case SCALE:
|
||||
if (dimensions == 3) {
|
||||
transform.scale(args[0], args[1], args[2]);
|
||||
} else {
|
||||
transform.scale(args[0], args[1]);
|
||||
}
|
||||
break;
|
||||
case MATRIX:
|
||||
if (dimensions == 3) {
|
||||
transform.set(args[ 0], args[ 1], args[ 2], args[ 3],
|
||||
args[ 4], args[ 5], args[ 6], args[ 7],
|
||||
args[ 8], args[ 9], args[10], args[11],
|
||||
args[12], args[13], args[14], args[15]);
|
||||
} else {
|
||||
transform.set(args[0], args[1], args[2],
|
||||
args[3], args[4], args[5]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
matrix.apply(transform);
|
||||
}
|
||||
|
||||
|
||||
protected void applyTransform(int dimensions) {
|
||||
if (dimensions == 3) {
|
||||
tess.applyMatrix((PMatrix3D) transform);
|
||||
} else {
|
||||
tess.applyMatrix((PMatrix2D) transform);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void setChildHasMatrix(boolean value) {
|
||||
childHasMatrix = value;
|
||||
if (parent != null) {
|
||||
((PShape3D)parent).setChildHasMatrix(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected boolean hasMatrix() {
|
||||
return matrix != null || childHasMatrix;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
//
|
||||
@@ -2466,12 +2363,7 @@ public class PShape3D extends PShape {
|
||||
child.tessellate();
|
||||
}
|
||||
} else {
|
||||
if (shapeEnded) {
|
||||
if (tessellated) {
|
||||
in.clearEdges();
|
||||
tess.clear();
|
||||
}
|
||||
|
||||
if (shapeEnded && !tessellated) {
|
||||
tessellator.setInGeometry(in);
|
||||
tessellator.setTessGeometry(tess);
|
||||
tessellator.setFill(fill || texture != null);
|
||||
@@ -2534,8 +2426,9 @@ public class PShape3D extends PShape {
|
||||
// equivalent to use POLYGON with fill disabled.
|
||||
}
|
||||
|
||||
// Tessellated arrays are trimmed since they are expanded by doubling their old size,
|
||||
// which might lead to arrays larger than the vertex counts.
|
||||
// Tessellated arrays are trimmed since they are expanded
|
||||
// by doubling their old size, which might lead to arrays
|
||||
// larger than the vertex counts.
|
||||
tess.trim();
|
||||
|
||||
if (texture != null && parent != null) {
|
||||
@@ -2583,7 +2476,8 @@ public class PShape3D extends PShape {
|
||||
in.generateEllipse(ellipseMode, a, b, c, d,
|
||||
fill, fillColor,
|
||||
stroke, strokeColor, strokeWeight,
|
||||
ambientColor, specularColor, emissiveColor, shininess);
|
||||
ambientColor, specularColor, emissiveColor,
|
||||
shininess);
|
||||
|
||||
tessellator.tessellateTriangleFan();
|
||||
}
|
||||
@@ -2595,7 +2489,6 @@ public class PShape3D extends PShape {
|
||||
|
||||
|
||||
protected void tessellateBox() {
|
||||
// TODO: move to InGeometry
|
||||
float w, h, d;
|
||||
if (params.length == 1) {
|
||||
w = h = d = params[0];
|
||||
@@ -2605,57 +2498,13 @@ public class PShape3D extends PShape {
|
||||
d = params[2];
|
||||
}
|
||||
|
||||
//in.generateBox(w, h, d);
|
||||
|
||||
in.generateBox(w, h, d,
|
||||
fill, fillColor,
|
||||
stroke, strokeColor, strokeWeight,
|
||||
ambientColor, specularColor, emissiveColor,
|
||||
shininess);
|
||||
|
||||
float x1 = -w/2f; float x2 = w/2f;
|
||||
float y1 = -h/2f; float y2 = h/2f;
|
||||
float z1 = -d/2f; float z2 = d/2f;
|
||||
|
||||
// front
|
||||
normal(0, 0, 1);
|
||||
vertex(x1, y1, z1, 0, 0);
|
||||
vertex(x2, y1, z1, 1, 0);
|
||||
vertex(x2, y2, z1, 1, 1);
|
||||
vertex(x1, y2, z1, 0, 1);
|
||||
|
||||
// right
|
||||
normal(1, 0, 0);
|
||||
vertex(x2, y1, z1, 0, 0);
|
||||
vertex(x2, y1, z2, 1, 0);
|
||||
vertex(x2, y2, z2, 1, 1);
|
||||
vertex(x2, y2, z1, 0, 1);
|
||||
|
||||
// back
|
||||
normal(0, 0, -1);
|
||||
vertex(x2, y1, z2, 0, 0);
|
||||
vertex(x1, y1, z2, 1, 0);
|
||||
vertex(x1, y2, z2, 1, 1);
|
||||
vertex(x2, y2, z2, 0, 1);
|
||||
|
||||
// left
|
||||
normal(-1, 0, 0);
|
||||
vertex(x1, y1, z2, 0, 0);
|
||||
vertex(x1, y1, z1, 1, 0);
|
||||
vertex(x1, y2, z1, 1, 1);
|
||||
vertex(x1, y2, z2, 0, 1);
|
||||
|
||||
// top
|
||||
normal(0, 1, 0);
|
||||
vertex(x1, y1, z2, 0, 0);
|
||||
vertex(x2, y1, z2, 1, 0);
|
||||
vertex(x2, y1, z1, 1, 1);
|
||||
vertex(x1, y1, z1, 0, 1);
|
||||
|
||||
// bottom
|
||||
normal(0, -1, 0);
|
||||
vertex(x1, y2, z1, 0, 0);
|
||||
vertex(x2, y2, z1, 1, 0);
|
||||
vertex(x2, y2, z2, 1, 1);
|
||||
vertex(x1, y2, z2, 0, 1);
|
||||
|
||||
if (stroke) in.addQuadsEdges();
|
||||
tessellator.tessellateQuads();
|
||||
tessellator.tessellateQuads();
|
||||
}
|
||||
|
||||
|
||||
@@ -3738,18 +3587,16 @@ public class PShape3D extends PShape {
|
||||
|
||||
|
||||
public void draw(PGraphics g) {
|
||||
if (visible) {
|
||||
|
||||
if (visible) {
|
||||
updateTesselation();
|
||||
updateGeometry();
|
||||
|
||||
if (matrix != null && applyMatrix) {
|
||||
if (applyMatrix && matrix != null) {
|
||||
g.pushMatrix();
|
||||
g.applyMatrix(matrix);
|
||||
}
|
||||
|
||||
if (family == GROUP) {
|
||||
|
||||
if (family == GROUP) {
|
||||
boolean matrixBelow = childHasMatrix;
|
||||
boolean diffTexBelow = textures != null && 1 < textures.size();
|
||||
|
||||
@@ -3780,7 +3627,7 @@ public class PShape3D extends PShape {
|
||||
render(texture);
|
||||
}
|
||||
|
||||
if (matrix != null && applyMatrix) {
|
||||
if (applyMatrix && matrix != null) {
|
||||
g.popMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user