OBJ-loading code moved into PShapeOBJ, removed PShape2D and PShap3D

This commit is contained in:
codeanticode
2012-09-03 22:21:49 +00:00
parent 85a44aa9be
commit ebf861adef
7 changed files with 660 additions and 721 deletions

View File

@@ -205,6 +205,8 @@ public class PShape implements PConstants {
/** True if colorMode(RGB, 255) */
boolean colorModeDefault; // = true;
/** True if contains 3D data */
protected boolean is3D = false;
// should this be called vertices (consistent with PGraphics internals)
// or does that hurt flexibility?
@@ -430,7 +432,7 @@ public class PShape implements PConstants {
* Return true if this shape is 2D. Defaults to true.
*/
public boolean is2D() {
return true;
return !is3D;
}
@@ -438,7 +440,12 @@ public class PShape implements PConstants {
* Return true if this shape is 3D. Defaults to false.
*/
public boolean is3D() {
return false;
return is3D;
}
public void is3D(boolean val) {
is3D = val;
}
@@ -840,9 +847,13 @@ public class PShape implements PConstants {
// s.emissive(vert[ER] * 255, vert[EG] * 255, vert[EB] * 255);
// s.shininess(vert[SHINE]);
dest.normal(vert[PGraphics.NX],
vert[PGraphics.NY],
vert[PGraphics.NZ]);
if (0 < PApplet.dist(vert[PGraphics.NX],
vert[PGraphics.NY],
vert[PGraphics.NZ], 0, 0, 0)) {
dest.normal(vert[PGraphics.NX],
vert[PGraphics.NY],
vert[PGraphics.NZ]);
}
dest.vertex(vert[X], vert[Y], vert[Z],
vert[PGraphics.U],
vert[PGraphics.V]);

View File

@@ -0,0 +1,409 @@
package processing.core;
import java.io.BufferedReader;
import java.util.ArrayList;
import java.util.Hashtable;
/**
* OBJ loading implemented using code from Saito's OBJLoader library:
* http://code.google.com/p/saitoobjloader/
* and OBJReader from Ahmet Kizilay
* http://www.openprocessing.org/visuals/?visualID=191
*
*/
public class PShapeOBJ extends PShape {
/**
* Initializes a new OBJ Object with the given filename.
*/
public PShapeOBJ(PApplet parent, String filename) {
this(parent, parent.createReader(filename));
}
public PShapeOBJ(PApplet parent, BufferedReader reader) {
ArrayList<OBJFace> faces = new ArrayList<OBJFace>();
ArrayList<OBJMaterial> materials = new ArrayList<OBJMaterial>();
ArrayList<PVector> coords = new ArrayList<PVector>();
ArrayList<PVector> normals = new ArrayList<PVector>();
ArrayList<PVector> texcoords = new ArrayList<PVector>();
parseOBJ(parent, reader, faces, materials, coords, normals, texcoords);
// The OBJ geometry is stored with each face in a separate child shape.
parent = null;
family = GROUP;
addChildren(faces, materials, coords, normals, texcoords);
}
protected PShapeOBJ(OBJFace face, OBJMaterial mtl,
ArrayList<PVector> coords,
ArrayList<PVector> normals,
ArrayList<PVector> texcoords) {
family = GEOMETRY;
if (face.vertIdx.size() == 3) {
kind = TRIANGLES;
} else if (face.vertIdx.size() == 4) {
kind = QUADS;
} else {
kind = POLYGON;
}
// Setting material properties for the new face
fillColor = rgbaValue(mtl.kd);
ambientColor = rgbaValue(mtl.ka);
specularColor = rgbaValue(mtl.ks);
shininess = mtl.ns;
if (mtl.kdMap != null) {
// If current material is textured, then tinting the texture using the
// diffuse color.
tintColor = rgbaValue(mtl.kd, mtl.d);
}
vertexCount = face.vertIdx.size();
vertices = new float[vertexCount][12];
for (int j = 0; j < face.vertIdx.size(); j++){
int vertIdx, normIdx;
PVector vert, norms;
vert = norms = null;
vertIdx = face.vertIdx.get(j).intValue() - 1;
vert = coords.get(vertIdx);
if (j < face.normIdx.size()) {
normIdx = face.normIdx.get(j).intValue() - 1;
if (-1 < normIdx) {
norms = normals.get(normIdx);
}
}
vertices[j][X] = vert.x;
vertices[j][Y] = vert.y;
vertices[j][Z] = vert.z;
vertices[j][PGraphics.R] = mtl.kd.x;
vertices[j][PGraphics.B] = mtl.kd.y;
vertices[j][PGraphics.G] = mtl.kd.z;
vertices[j][PGraphics.A] = 1;
if (norms != null) {
vertices[j][PGraphics.NX] = norms.x;
vertices[j][PGraphics.NY] = norms.y;
vertices[j][PGraphics.NZ] = norms.z;
}
if (mtl != null && mtl.kdMap != null) {
// This face is textured.
int texIdx;
PVector tex = null;
if (j < face.texIdx.size()) {
texIdx = face.texIdx.get(j).intValue() - 1;
if (-1 < texIdx) {
tex = texcoords.get(texIdx);
}
}
image = mtl.kdMap;
if (tex != null) {
vertices[j][PGraphics.U] = tex.x;
vertices[j][PGraphics.V] = tex.y;
}
}
}
}
protected void addChildren(ArrayList<OBJFace> faces,
ArrayList<OBJMaterial> materials,
ArrayList<PVector> coords,
ArrayList<PVector> normals,
ArrayList<PVector> texcoords) {
int mtlIdxCur = -1;
OBJMaterial mtl = null;
for (int i = 0; i < faces.size(); i++) {
OBJFace face = faces.get(i);
// Getting current material.
if (mtlIdxCur != face.matIdx) {
// To make sure that at least we get the default material
mtlIdxCur = PApplet.max(0, face.matIdx);
mtl = materials.get(mtlIdxCur);
}
// Creating child shape for current face.
PShape child = new PShapeOBJ(face, mtl, coords, normals, texcoords);
addChild(child);
}
}
static protected void parseOBJ(PApplet parent,
BufferedReader reader,
ArrayList<OBJFace> faces,
ArrayList<OBJMaterial> materials,
ArrayList<PVector> coords,
ArrayList<PVector> normals,
ArrayList<PVector> texcoords) {
Hashtable<String, Integer> mtlTable = new Hashtable<String, Integer>();
int mtlIdxCur = -1;
boolean readv, readvn, readvt;
try {
readv = readvn = readvt = false;
String line;
String gname = "object";
while ((line = reader.readLine()) != null) {
// Parse the line.
// The below patch/hack comes from Carlos Tomas Marti and is a
// fix for single backslashes in Rhino obj files
// BEGINNING OF RHINO OBJ FILES HACK
// Statements can be broken in multiple lines using '\' at the
// end of a line.
// In regular expressions, the backslash is also an escape
// character.
// The regular expression \\ matches a single backslash. This
// regular expression as a Java string, becomes "\\\\".
// That's right: 4 backslashes to match a single one.
while (line.contains("\\")) {
line = line.split("\\\\")[0];
final String s = reader.readLine();
if (s != null)
line += s;
}
// END OF RHINO OBJ FILES HACK
String[] parts = line.split("\\s+");
// if not a blank line, process the line.
if (parts.length > 0) {
if (parts[0].equals("v")) {
// vertex
PVector tempv = new PVector(Float.valueOf(parts[1]).floatValue(),
Float.valueOf(parts[2]).floatValue(),
Float.valueOf(parts[3]).floatValue());
coords.add(tempv);
readv = true;
} else if (parts[0].equals("vn")) {
// normal
PVector tempn = new PVector(Float.valueOf(parts[1]).floatValue(),
Float.valueOf(parts[2]).floatValue(),
Float.valueOf(parts[3]).floatValue());
normals.add(tempn);
readvn = true;
} else if (parts[0].equals("vt")) {
// uv, inverting v to take into account Processing's inverted Y axis
// with respect to OpenGL.
PVector tempv = new PVector(Float.valueOf(parts[1]).floatValue(),
1 - Float.valueOf(parts[2]).
floatValue());
texcoords.add(tempv);
readvt = true;
} else if (parts[0].equals("o")) {
// Object name is ignored, for now.
} else if (parts[0].equals("mtllib")) {
if (parts[1] != null) {
BufferedReader mreader = parent.createReader(parts[1]);
if (mreader != null) {
parseMTL(parent, mreader, materials, mtlTable);
}
}
} else if (parts[0].equals("g")) {
gname = 1 < parts.length ? parts[1] : "";
} else if (parts[0].equals("usemtl")) {
// Getting index of current active material (will be applied on
// all subsequent faces).
if (parts[1] != null) {
String mtlname = parts[1];
if (mtlTable.containsKey(mtlname)) {
Integer tempInt = mtlTable.get(mtlname);
mtlIdxCur = tempInt.intValue();
} else {
mtlIdxCur = -1;
}
}
} else if (parts[0].equals("f")) {
// Face setting
OBJFace face = new OBJFace();
face.matIdx = mtlIdxCur;
face.name = gname;
for (int i = 1; i < parts.length; i++) {
String seg = parts[i];
if (seg.indexOf("/") > 0) {
String[] forder = seg.split("/");
if (forder.length > 2) {
// Getting vertex and texture and normal indexes.
if (forder[0].length() > 0 && readv) {
face.vertIdx.add(Integer.valueOf(forder[0]));
}
if (forder[1].length() > 0 && readvt) {
face.texIdx.add(Integer.valueOf(forder[1]));
}
if (forder[2].length() > 0 && readvn) {
face.normIdx.add(Integer.valueOf(forder[2]));
}
} else if (forder.length > 1) {
// Getting vertex and texture/normal indexes.
if (forder[0].length() > 0 && readv) {
face.vertIdx.add(Integer.valueOf(forder[0]));
}
if (forder[1].length() > 0) {
if (readvt) {
face.texIdx.add(Integer.valueOf(forder[1]));
} else if (readvn) {
face.normIdx.add(Integer.valueOf(forder[1]));
}
}
} else if (forder.length > 0) {
// Getting vertex index only.
if (forder[0].length() > 0 && readv) {
face.vertIdx.add(Integer.valueOf(forder[0]));
}
}
} else {
// Getting vertex index only.
if (seg.length() > 0 && readv) {
face.vertIdx.add(Integer.valueOf(seg));
}
}
}
faces.add(face);
}
}
}
if (materials.size() == 0) {
// No materials definition so far. Adding one default material.
OBJMaterial defMtl = new OBJMaterial();
materials.add(defMtl);
}
} catch (Exception e) {
e.printStackTrace();
}
}
static protected void parseMTL(PApplet parent,
BufferedReader reader,
ArrayList<OBJMaterial> materials,
Hashtable<String, Integer> materialsHash) {
try {
String line;
OBJMaterial currentMtl = null;
while ((line = reader.readLine()) != null) {
// Parse the line
line = line.trim();
String parts[] = line.split("\\s+");
if (parts.length > 0) {
// Extract the material data.
if (parts[0].equals("newmtl")) {
// Starting new material.
String mtlname = parts[1];
currentMtl = new OBJMaterial(mtlname);
materialsHash.put(mtlname, new Integer(materials.size()));
materials.add(currentMtl);
} else if (parts[0].equals("map_Kd") && parts.length > 1) {
// Loading texture map.
String texname = parts[1];
currentMtl.kdMap = parent.loadImage(texname);
} else if (parts[0].equals("Ka") && parts.length > 3) {
// The ambient color of the material
currentMtl.ka.x = Float.valueOf(parts[1]).floatValue();
currentMtl.ka.y = Float.valueOf(parts[2]).floatValue();
currentMtl.ka.z = Float.valueOf(parts[3]).floatValue();
} else if (parts[0].equals("Kd") && parts.length > 3) {
// The diffuse color of the material
currentMtl.kd.x = Float.valueOf(parts[1]).floatValue();
currentMtl.kd.y = Float.valueOf(parts[2]).floatValue();
currentMtl.kd.z = Float.valueOf(parts[3]).floatValue();
} else if (parts[0].equals("Ks") && parts.length > 3) {
// The specular color weighted by the specular coefficient
currentMtl.ks.x = Float.valueOf(parts[1]).floatValue();
currentMtl.ks.y = Float.valueOf(parts[2]).floatValue();
currentMtl.ks.z = Float.valueOf(parts[3]).floatValue();
} else if ((parts[0].equals("d") ||
parts[0].equals("Tr")) && parts.length > 1) {
// Reading the alpha transparency.
currentMtl.d = Float.valueOf(parts[1]).floatValue();
} else if (parts[0].equals("Ns") && parts.length > 1) {
// The specular component of the Phong shading model
currentMtl.ns = Float.valueOf(parts[1]).floatValue();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
protected static int rgbaValue(PVector color) {
return 0xFF000000 | ((int)(color.x * 255) << 16) |
((int)(color.y * 255) << 8) |
(int)(color.z * 255);
}
protected static int rgbaValue(PVector color, float alpha) {
return ((int)(alpha * 255) << 24) |
((int)(color.x * 255) << 16) |
((int)(color.y * 255) << 8) |
(int)(color.z * 255);
}
// Stores a face from an OBJ file
static protected class OBJFace {
ArrayList<Integer> vertIdx;
ArrayList<Integer> texIdx;
ArrayList<Integer> normIdx;
int matIdx;
String name;
OBJFace() {
vertIdx = new ArrayList<Integer>();
texIdx = new ArrayList<Integer>();
normIdx = new ArrayList<Integer>();
matIdx = -1;
name = "";
}
}
// Stores a material defined in an MTL file.
static protected class OBJMaterial {
String name;
PVector ka;
PVector kd;
PVector ks;
float d;
float ns;
PImage kdMap;
OBJMaterial() {
this("default");
}
OBJMaterial(String name) {
this.name = name;
ka = new PVector(0.5f, 0.5f, 0.5f);
kd = new PVector(0.5f, 0.5f, 0.5f);
ks = new PVector(0.5f, 0.5f, 0.5f);
d = 1.0f;
ns = 0.0f;
kdMap = null;
}
}
}

View File

@@ -243,8 +243,8 @@ public class PGraphics2D extends PGraphicsOpenGL {
}
static protected PShape2D loadShapeImpl(PGraphics pg, String filename,
String extension) {
static protected PShape loadShapeImpl(PGraphics pg, String filename,
String extension) {
PShapeSVG svg = null;
if (extension.equals("svg")) {
@@ -262,7 +262,7 @@ public class PGraphics2D extends PGraphicsOpenGL {
}
if (svg != null) {
PShape2D p2d = PShape2D.createShape(pg.parent, svg);
PShapeOpenGL p2d = PShapeOpenGL.createShape2D(pg.parent, svg);
return p2d;
} else {
return null;
@@ -277,7 +277,7 @@ public class PGraphics2D extends PGraphicsOpenGL {
@Override
public PShape createShape(PShape source) {
return PShape2D.createShape(parent, source);
return PShapeOpenGL.createShape2D(parent, source);
}
@@ -299,44 +299,45 @@ public class PGraphics2D extends PGraphicsOpenGL {
}
static protected PShape2D createShapeImpl(PApplet parent, int type) {
PShape2D shape = null;
static protected PShapeOpenGL createShapeImpl(PApplet parent, int type) {
PShapeOpenGL shape = null;
if (type == PConstants.GROUP) {
shape = new PShape2D(parent, PConstants.GROUP);
shape = new PShapeOpenGL(parent, PConstants.GROUP);
} else if (type == PShape.PATH) {
shape = new PShape2D(parent, PShape.PATH);
shape = new PShapeOpenGL(parent, PShape.PATH);
} else if (type == POINTS) {
shape = new PShape2D(parent, PShape.GEOMETRY);
shape = new PShapeOpenGL(parent, PShape.GEOMETRY);
shape.setKind(POINTS);
} else if (type == LINES) {
shape = new PShape2D(parent, PShape.GEOMETRY);
shape = new PShapeOpenGL(parent, PShape.GEOMETRY);
shape.setKind(LINES);
} else if (type == TRIANGLE || type == TRIANGLES) {
shape = new PShape2D(parent, PShape.GEOMETRY);
shape = new PShapeOpenGL(parent, PShape.GEOMETRY);
shape.setKind(TRIANGLES);
} else if (type == TRIANGLE_FAN) {
shape = new PShape2D(parent, PShape.GEOMETRY);
shape = new PShapeOpenGL(parent, PShape.GEOMETRY);
shape.setKind(TRIANGLE_FAN);
} else if (type == TRIANGLE_STRIP) {
shape = new PShape2D(parent, PShape.GEOMETRY);
shape = new PShapeOpenGL(parent, PShape.GEOMETRY);
shape.setKind(TRIANGLE_STRIP);
} else if (type == QUAD || type == QUADS) {
shape = new PShape2D(parent, PShape.GEOMETRY);
shape = new PShapeOpenGL(parent, PShape.GEOMETRY);
shape.setKind(QUADS);
} else if (type == QUAD_STRIP) {
shape = new PShape2D(parent, PShape.GEOMETRY);
shape = new PShapeOpenGL(parent, PShape.GEOMETRY);
shape.setKind(QUAD_STRIP);
} else if (type == POLYGON) {
shape = new PShape2D(parent, PShape.GEOMETRY);
shape = new PShapeOpenGL(parent, PShape.GEOMETRY);
shape.setKind(POLYGON);
}
shape.is3D(false);
return shape;
}
static protected PShape2D createShapeImpl(PApplet parent, int kind,
float... p) {
PShape2D shape = null;
static protected PShapeOpenGL createShapeImpl(PApplet parent,
int kind, float... p) {
PShapeOpenGL shape = null;
int len = p.length;
if (kind == POINT) {
@@ -344,49 +345,49 @@ public class PGraphics2D extends PGraphicsOpenGL {
showWarning("Wrong number of parameters");
return null;
}
shape = new PShape2D(parent, PShape.PRIMITIVE);
shape = new PShapeOpenGL(parent, PShape.PRIMITIVE);
shape.setKind(POINT);
} else if (kind == LINE) {
if (len != 4) {
showWarning("Wrong number of parameters");
return null;
}
shape = new PShape2D(parent, PShape.PRIMITIVE);
shape = new PShapeOpenGL(parent, PShape.PRIMITIVE);
shape.setKind(LINE);
} else if (kind == TRIANGLE) {
if (len != 6) {
showWarning("Wrong number of parameters");
return null;
}
shape = new PShape2D(parent, PShape.PRIMITIVE);
shape = new PShapeOpenGL(parent, PShape.PRIMITIVE);
shape.setKind(TRIANGLE);
} else if (kind == QUAD) {
if (len != 8) {
showWarning("Wrong number of parameters");
return null;
}
shape = new PShape2D(parent, PShape.PRIMITIVE);
shape = new PShapeOpenGL(parent, PShape.PRIMITIVE);
shape.setKind(QUAD);
} else if (kind == RECT) {
if (len != 4 && len != 5 && len != 8) {
showWarning("Wrong number of parameters");
return null;
}
shape = new PShape2D(parent, PShape.PRIMITIVE);
shape = new PShapeOpenGL(parent, PShape.PRIMITIVE);
shape.setKind(RECT);
} else if (kind == ELLIPSE) {
if (len != 4) {
showWarning("Wrong number of parameters");
return null;
}
shape = new PShape2D(parent, PShape.PRIMITIVE);
shape = new PShapeOpenGL(parent, PShape.PRIMITIVE);
shape.setKind(ELLIPSE);
} else if (kind == ARC) {
if (len != 6) {
showWarning("Wrong number of parameters");
return null;
}
shape = new PShape2D(parent, PShape.PRIMITIVE);
shape = new PShapeOpenGL(parent, PShape.PRIMITIVE);
shape.setKind(ARC);
} else if (kind == BOX) {
showWarning("Primitive not supported in 2D");
@@ -400,6 +401,7 @@ public class PGraphics2D extends PGraphicsOpenGL {
shape.setParams(p);
}
shape.is3D(false);
return shape;
}

View File

@@ -22,16 +22,14 @@
package processing.opengl;
import java.io.BufferedReader;
import java.util.ArrayList;
import java.util.Hashtable;
import java.io.InputStream;
import java.util.zip.GZIPInputStream;
import processing.core.PApplet;
import processing.core.PConstants;
import processing.core.PGraphics;
import processing.core.PImage;
import processing.core.PShape;
import processing.core.PVector;
import processing.core.PShapeOBJ;
public class PGraphics3D extends PGraphicsOpenGL {
@@ -111,119 +109,34 @@ public class PGraphics3D extends PGraphicsOpenGL {
static protected PShape loadShapeImpl(PGraphics pg, String filename,
String ext) {
ArrayList<PVector> vertices = new ArrayList<PVector>();
ArrayList<PVector> normals = new ArrayList<PVector>();
ArrayList<PVector> textures = new ArrayList<PVector>();
ArrayList<OBJFace> faces = new ArrayList<OBJFace>();
ArrayList<OBJMaterial> materials = new ArrayList<OBJMaterial>();
String extension) {
PShapeOBJ obj = null;
BufferedReader reader = pg.parent.createReader(filename);
parseOBJ(pg.parent, reader, vertices, normals, textures, faces, materials);
if (extension.equals("obj")) {
obj = new PShapeOBJ(pg.parent, filename);
int prevColorMode = pg.colorMode;
float prevColorModeX = pg.colorModeX;
float prevColorModeY = pg.colorModeY;
float prevColorModeZ = pg.colorModeZ;
float prevColorModeA = pg.colorModeA;
boolean prevStroke = pg.stroke;
int prevTextureMode = pg.textureMode;
pg.colorMode(RGB, 1);
pg.stroke = false;
pg.textureMode = NORMAL;
// The OBJ geometry is stored in a group shape,
// with each face in a separate child geometry
// shape.
PShape root = createShapeImpl(pg.parent, GROUP);
int mtlIdxCur = -1;
OBJMaterial mtl = null;
for (int i = 0; i < faces.size(); i++) {
OBJFace face = faces.get(i);
// Getting current material.
if (mtlIdxCur != face.matIdx) {
mtlIdxCur = PApplet.max(0, face.matIdx); // To make sure that at least we get the default material.
mtl = materials.get(mtlIdxCur);
} else if (extension.equals("objz")) {
try {
InputStream input =
new GZIPInputStream(pg.parent.createInput(filename));
obj = new PShapeOBJ(pg.parent, PApplet.createReader(input));
} catch (Exception e) {
e.printStackTrace();
}
// Creating child shape for current face.
PShape child;
if (face.vertIdx.size() == 3) {
child = createShapeImpl(pg.parent, TRIANGLES); // Face is a triangle, so using appropriate shape kind.
} else if (face.vertIdx.size() == 4) {
child = createShapeImpl(pg.parent, QUADS); // Face is a quad, so using appropriate shape kind.
} else {
child = createShapeImpl(pg.parent, POLYGON); // Face is a general polygon
}
// Setting material properties for the new face
child.fill(mtl.kd.x, mtl.kd.y, mtl.kd.z);
child.ambient(mtl.ka.x, mtl.ka.y, mtl.ka.z);
child.specular(mtl.ks.x, mtl.ks.y, mtl.ks.z);
child.shininess(mtl.ns);
if (mtl.kdMap != null) {
// If current material is textured, then tinting the texture using the diffuse color.
child.tint(mtl.kd.x, mtl.kd.y, mtl.kd.z, mtl.d);
}
for (int j = 0; j < face.vertIdx.size(); j++){
int vertIdx, normIdx;
PVector vert, norms;
vert = norms = null;
vertIdx = face.vertIdx.get(j).intValue() - 1;
vert = vertices.get(vertIdx);
if (j < face.normIdx.size()) {
normIdx = face.normIdx.get(j).intValue() - 1;
if (-1 < normIdx) {
norms = normals.get(normIdx);
}
}
if (mtl != null && mtl.kdMap != null) {
// This face is textured.
int texIdx;
PVector tex = null;
if (j < face.texIdx.size()) {
texIdx = face.texIdx.get(j).intValue() - 1;
if (-1 < texIdx) {
tex = textures.get(texIdx);
}
}
child.texture(mtl.kdMap);
if (norms != null) {
child.normal(norms.x, norms.y, norms.z);
}
if (tex != null) {
child.vertex(vert.x, vert.y, vert.z, tex.x, tex.y);
} else {
child.vertex(vert.x, vert.y, vert.z);
}
} else {
// This face is not textured.
if (norms != null) {
child.normal(norms.x, norms.y, norms.z);
}
child.vertex(vert.x, vert.y, vert.z);
}
}
child.end(CLOSE);
root.addChild(child);
}
pg.colorMode(prevColorMode, prevColorModeX, prevColorModeY, prevColorModeZ,
prevColorModeA);
pg.stroke = prevStroke;
pg.textureMode = prevTextureMode;
return root;
if (obj != null) {
boolean prevStroke = pg.stroke;
int prevTextureMode = pg.textureMode;
pg.stroke = false;
pg.textureMode = NORMAL;
PShapeOpenGL p3d = PShapeOpenGL.createShape3D(pg.parent, obj);
pg.stroke = prevStroke;
pg.textureMode = prevTextureMode;
return p3d;
} else {
return null;
}
}
@@ -234,7 +147,7 @@ public class PGraphics3D extends PGraphicsOpenGL {
@Override
public PShape createShape(PShape source) {
return PShape3D.createShape(parent, source);
return PShapeOpenGL.createShape3D(parent, source);
}
@@ -256,43 +169,45 @@ public class PGraphics3D extends PGraphicsOpenGL {
}
static protected PShape3D createShapeImpl(PApplet parent, int type) {
PShape3D shape = null;
static protected PShapeOpenGL createShapeImpl(PApplet parent, int type) {
PShapeOpenGL shape = null;
if (type == PConstants.GROUP) {
shape = new PShape3D(parent, PConstants.GROUP);
shape = new PShapeOpenGL(parent, PConstants.GROUP);
} else if (type == PShape.PATH) {
shape = new PShape3D(parent, PShape.PATH);
shape = new PShapeOpenGL(parent, PShape.PATH);
} else if (type == POINTS) {
shape = new PShape3D(parent, PShape.GEOMETRY);
shape = new PShapeOpenGL(parent, PShape.GEOMETRY);
shape.setKind(POINTS);
} else if (type == LINES) {
shape = new PShape3D(parent, PShape.GEOMETRY);
shape = new PShapeOpenGL(parent, PShape.GEOMETRY);
shape.setKind(LINES);
} else if (type == TRIANGLE || type == TRIANGLES) {
shape = new PShape3D(parent, PShape.GEOMETRY);
shape = new PShapeOpenGL(parent, PShape.GEOMETRY);
shape.setKind(TRIANGLES);
} else if (type == TRIANGLE_FAN) {
shape = new PShape3D(parent, PShape.GEOMETRY);
shape = new PShapeOpenGL(parent, PShape.GEOMETRY);
shape.setKind(TRIANGLE_FAN);
} else if (type == TRIANGLE_STRIP) {
shape = new PShape3D(parent, PShape.GEOMETRY);
shape = new PShapeOpenGL(parent, PShape.GEOMETRY);
shape.setKind(TRIANGLE_STRIP);
} else if (type == QUAD || type == QUADS) {
shape = new PShape3D(parent, PShape.GEOMETRY);
shape = new PShapeOpenGL(parent, PShape.GEOMETRY);
shape.setKind(QUADS);
} else if (type == QUAD_STRIP) {
shape = new PShape3D(parent, PShape.GEOMETRY);
shape = new PShapeOpenGL(parent, PShape.GEOMETRY);
shape.setKind(QUAD_STRIP);
} else if (type == POLYGON) {
shape = new PShape3D(parent, PShape.GEOMETRY);
shape = new PShapeOpenGL(parent, PShape.GEOMETRY);
shape.setKind(POLYGON);
}
shape.is3D(true);
return shape;
}
static protected PShape3D createShapeImpl(PApplet parent, int kind, float... p) {
PShape3D shape = null;
static protected PShapeOpenGL createShapeImpl(PApplet parent,
int kind, float... p) {
PShapeOpenGL shape = null;
int len = p.length;
if (kind == POINT) {
@@ -300,63 +215,63 @@ public class PGraphics3D extends PGraphicsOpenGL {
showWarning("Wrong number of parameters");
return null;
}
shape = new PShape3D(parent, PShape.PRIMITIVE);
shape = new PShapeOpenGL(parent, PShape.PRIMITIVE);
shape.setKind(POINT);
} else if (kind == LINE) {
if (len != 4 && len != 6) {
showWarning("Wrong number of parameters");
return null;
}
shape = new PShape3D(parent, PShape.PRIMITIVE);
shape = new PShapeOpenGL(parent, PShape.PRIMITIVE);
shape.setKind(LINE);
} else if (kind == TRIANGLE) {
if (len != 6) {
showWarning("Wrong number of parameters");
return null;
}
shape = new PShape3D(parent, PShape.PRIMITIVE);
shape = new PShapeOpenGL(parent, PShape.PRIMITIVE);
shape.setKind(TRIANGLE);
} else if (kind == QUAD) {
if (len != 8) {
showWarning("Wrong number of parameters");
return null;
}
shape = new PShape3D(parent, PShape.PRIMITIVE);
shape = new PShapeOpenGL(parent, PShape.PRIMITIVE);
shape.setKind(QUAD);
} else if (kind == RECT) {
if (len != 4 && len != 5 && len != 8) {
showWarning("Wrong number of parameters");
return null;
}
shape = new PShape3D(parent, PShape.PRIMITIVE);
shape = new PShapeOpenGL(parent, PShape.PRIMITIVE);
shape.setKind(RECT);
} else if (kind == ELLIPSE) {
if (len != 4) {
showWarning("Wrong number of parameters");
return null;
}
shape = new PShape3D(parent, PShape.PRIMITIVE);
shape = new PShapeOpenGL(parent, PShape.PRIMITIVE);
shape.setKind(ELLIPSE);
} else if (kind == ARC) {
if (len != 6) {
showWarning("Wrong number of parameters");
return null;
}
shape = new PShape3D(parent, PShape.PRIMITIVE);
shape = new PShapeOpenGL(parent, PShape.PRIMITIVE);
shape.setKind(ARC);
} else if (kind == BOX) {
if (len != 1 && len != 3) {
showWarning("Wrong number of parameters");
return null;
}
shape = new PShape3D(parent, PShape.PRIMITIVE);
shape = new PShapeOpenGL(parent, PShape.PRIMITIVE);
shape.setKind(BOX);
} else if (kind == SPHERE) {
if (len != 1) {
showWarning("Wrong number of parameters");
return null;
}
shape = new PShape3D(parent, PShape.PRIMITIVE);
shape = new PShapeOpenGL(parent, PShape.PRIMITIVE);
shape.setKind(SPHERE);
} else {
showWarning("Unrecognized primitive type");
@@ -366,267 +281,7 @@ public class PGraphics3D extends PGraphicsOpenGL {
shape.setParams(p);
}
shape.is3D(true);
return shape;
}
//////////////////////////////////////////////////////////////
// OBJ LOADING
static protected void parseOBJ(PApplet parent,
BufferedReader reader,
ArrayList<PVector> vertices,
ArrayList<PVector> normals,
ArrayList<PVector> textures,
ArrayList<OBJFace> faces,
ArrayList<OBJMaterial> materials) {
Hashtable<String, Integer> mtlTable = new Hashtable<String, Integer>();
int mtlIdxCur = -1;
boolean readv, readvn, readvt;
try {
readv = readvn = readvt = false;
String line;
String gname = "object";
while ((line = reader.readLine()) != null) {
// Parse the line.
// The below patch/hack comes from Carlos Tomas Marti and is a
// fix for single backslashes in Rhino obj files
// BEGINNING OF RHINO OBJ FILES HACK
// Statements can be broken in multiple lines using '\' at the
// end of a line.
// In regular expressions, the backslash is also an escape
// character.
// The regular expression \\ matches a single backslash. This
// regular expression as a Java string, becomes "\\\\".
// That's right: 4 backslashes to match a single one.
while (line.contains("\\")) {
line = line.split("\\\\")[0];
final String s = reader.readLine();
if (s != null)
line += s;
}
// END OF RHINO OBJ FILES HACK
String[] elements = line.split("\\s+");
// if not a blank line, process the line.
if (elements.length > 0) {
if (elements[0].equals("v")) {
// vertex
PVector tempv = new PVector(Float.valueOf(elements[1]).floatValue(),
Float.valueOf(elements[2]).floatValue(),
Float.valueOf(elements[3]).floatValue());
vertices.add(tempv);
readv = true;
} else if (elements[0].equals("vn")) {
// normal
PVector tempn = new PVector(Float.valueOf(elements[1]).floatValue(),
Float.valueOf(elements[2]).floatValue(),
Float.valueOf(elements[3]).floatValue());
normals.add(tempn);
readvn = true;
} else if (elements[0].equals("vt")) {
// uv, inverting v to take into account Processing's invertex Y axis
// with respect to OpenGL.
PVector tempv = new PVector(Float.valueOf(elements[1]).floatValue(),
1 - Float.valueOf(elements[2]).
floatValue());
textures.add(tempv);
readvt = true;
} else if (elements[0].equals("o")) {
// Object name is ignored, for now.
} else if (elements[0].equals("mtllib")) {
if (elements[1] != null) {
BufferedReader mreader = parent.createReader(elements[1]);
if (mreader != null) {
parseMTL(parent, mreader, materials, mtlTable);
}
}
} else if (elements[0].equals("g")) {
gname = 1 < elements.length ? elements[1] : "";
} else if (elements[0].equals("usemtl")) {
// Getting index of current active material (will be applied on all subsequent faces).
if (elements[1] != null) {
String mtlname = elements[1];
if (mtlTable.containsKey(mtlname)) {
Integer tempInt = mtlTable.get(mtlname);
mtlIdxCur = tempInt.intValue();
} else {
mtlIdxCur = -1;
}
}
} else if (elements[0].equals("f")) {
// Face setting
OBJFace face = new OBJFace();
face.matIdx = mtlIdxCur;
face.name = gname;
for (int i = 1; i < elements.length; i++) {
String seg = elements[i];
if (seg.indexOf("/") > 0) {
String[] forder = seg.split("/");
if (forder.length > 2) {
// Getting vertex and texture and normal indexes.
if (forder[0].length() > 0 && readv) {
face.vertIdx.add(Integer.valueOf(forder[0]));
}
if (forder[1].length() > 0 && readvt) {
face.texIdx.add(Integer.valueOf(forder[1]));
}
if (forder[2].length() > 0 && readvn) {
face.normIdx.add(Integer.valueOf(forder[2]));
}
} else if (forder.length > 1) {
// Getting vertex and texture/normal indexes.
if (forder[0].length() > 0 && readv) {
face.vertIdx.add(Integer.valueOf(forder[0]));
}
if (forder[1].length() > 0) {
if (readvt) {
face.texIdx.add(Integer.valueOf(forder[1]));
} else if (readvn) {
face.normIdx.add(Integer.valueOf(forder[1]));
}
}
} else if (forder.length > 0) {
// Getting vertex index only.
if (forder[0].length() > 0 && readv) {
face.vertIdx.add(Integer.valueOf(forder[0]));
}
}
} else {
// Getting vertex index only.
if (seg.length() > 0 && readv) {
face.vertIdx.add(Integer.valueOf(seg));
}
}
}
faces.add(face);
}
}
}
if (materials.size() == 0) {
// No materials definition so far. Adding one default material.
OBJMaterial defMtl = new OBJMaterial();
materials.add(defMtl);
}
} catch (Exception e) {
e.printStackTrace();
}
}
static protected void parseMTL(PApplet parent,
BufferedReader reader,
ArrayList<OBJMaterial> materials,
Hashtable<String, Integer> materialsHash) {
try {
String line;
OBJMaterial currentMtl = null;
while ((line = reader.readLine()) != null) {
// Parse the line
line = line.trim();
String elements[] = line.split("\\s+");
if (elements.length > 0) {
// Extract the material data.
if (elements[0].equals("newmtl")) {
// Starting new material.
String mtlname = elements[1];
currentMtl = new OBJMaterial(mtlname);
materialsHash.put(mtlname, new Integer(materials.size()));
materials.add(currentMtl);
} else if (elements[0].equals("map_Kd") && elements.length > 1) {
// Loading texture map.
String texname = elements[1];
currentMtl.kdMap = parent.loadImage(texname);
} else if (elements[0].equals("Ka") && elements.length > 3) {
// The ambient color of the material
currentMtl.ka.x = Float.valueOf(elements[1]).floatValue();
currentMtl.ka.y = Float.valueOf(elements[2]).floatValue();
currentMtl.ka.z = Float.valueOf(elements[3]).floatValue();
} else if (elements[0].equals("Kd") && elements.length > 3) {
// The diffuse color of the material
currentMtl.kd.x = Float.valueOf(elements[1]).floatValue();
currentMtl.kd.y = Float.valueOf(elements[2]).floatValue();
currentMtl.kd.z = Float.valueOf(elements[3]).floatValue();
} else if (elements[0].equals("Ks") && elements.length > 3) {
// The specular color weighted by the specular coefficient
currentMtl.ks.x = Float.valueOf(elements[1]).floatValue();
currentMtl.ks.y = Float.valueOf(elements[2]).floatValue();
currentMtl.ks.z = Float.valueOf(elements[3]).floatValue();
} else if ((elements[0].equals("d") ||
elements[0].equals("Tr")) && elements.length > 1) {
// Reading the alpha transparency.
currentMtl.d = Float.valueOf(elements[1]).floatValue();
} else if (elements[0].equals("Ns") && elements.length > 1) {
// The specular component of the Phong shading model
currentMtl.ns = Float.valueOf(elements[1]).floatValue();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
// Stores a face from an OBJ file
static protected class OBJFace {
ArrayList<Integer> vertIdx;
ArrayList<Integer> texIdx;
ArrayList<Integer> normIdx;
int matIdx;
String name;
OBJFace() {
vertIdx = new ArrayList<Integer>();
texIdx = new ArrayList<Integer>();
normIdx = new ArrayList<Integer>();
matIdx = -1;
name = "";
}
}
// Stores a material defined in an MTL file.
static protected class OBJMaterial {
String name;
PVector ka;
PVector kd;
PVector ks;
float d;
float ns;
PImage kdMap;
OBJMaterial() {
this("default");
}
OBJMaterial(String name) {
this.name = name;
ka = new PVector(0.5f, 0.5f, 0.5f);
kd = new PVector(0.5f, 0.5f, 0.5f);
ks = new PVector(0.5f, 0.5f, 0.5f);
d = 1.0f;
ns = 0.0f;
kdMap = null;
}
}
}

View File

@@ -1,189 +0,0 @@
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Part of the Processing project - http://processing.org
Copyright (c) 2012 Ben Fry and Casey Reas
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation, version 2.1.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
*/
package processing.opengl;
import processing.core.PApplet;
import processing.core.PGraphics;
import processing.core.PShape;
public class PShape2D extends PShapeOpenGL {
public PShape2D(PApplet parent, int family) {
super(parent, family);
}
@Override
public boolean is2D() {
return true;
}
@Override
public boolean is3D() {
return false;
}
////////////////////////////////////////////////////////////////////////
//
// Shape copy
static public PShape2D createShape(PApplet parent, PShape src) {
PShape2D dest = null;
if (src.getFamily() == GROUP) {
dest = PGraphics2D.createShapeImpl(parent, GROUP);
PShape2D.copyGroup(parent, src, dest);
} else if (src.getFamily() == PRIMITIVE) {
dest = PGraphics2D.createShapeImpl(parent, src.getKind(),
src.getParams());
PShape.copyPrimitive(src, dest);
} else if (src.getFamily() == GEOMETRY) {
dest = PGraphics2D.createShapeImpl(parent, src.getKind());
PShape.copyGeometry(src, dest);
} else if (src.getFamily() == PATH) {
dest = PGraphics2D.createShapeImpl(parent, PATH);
PShape.copyPath(src, dest);
}
dest.setName(src.getName());
return dest;
}
static public void copyGroup(PApplet parent, PShape src, PShape dest) {
copyMatrix(src, dest);
copyStyles(src, dest);
copyImage(src, dest);
for (int i = 0; i < src.getChildCount(); i++) {
PShape c = PShape2D.createShape(parent, src.getChild(i));
dest.addChild(c);
}
}
///////////////////////////////////////////////////////////
//
// Drawing methods
@Override
public void vertex(float x, float y, float z) {
PGraphics.showDepthWarningXYZ("vertex");
}
@Override
public void vertex(float x, float y, float z, float u, float v) {
PGraphics.showDepthWarningXYZ("vertex");
}
///////////////////////////////////////////////////////////
//
// Bezier curves
@Override
public void bezierVertex(float x2, float y2, float z2,
float x3, float y3, float z3,
float x4, float y4, float z4) {
PGraphics.showDepthWarningXYZ("bezierVertex");
}
@Override
public void quadraticVertex(float x2, float y2, float z2,
float x4, float y4, float z4) {
PGraphics.showDepthWarningXYZ("quadVertex");
}
@Override
public void curveVertex(float x, float y, float z) {
PGraphics.showDepthWarningXYZ("curveVertex");
}
///////////////////////////////////////////////////////////
//
// Geometric transformations
@Override
public void translate(float tx, float ty, float tz) {
PGraphics.showVariationWarning("translate");
}
@Override
public void rotateX(float angle) {
PGraphics.showDepthWarning("rotateX");
}
@Override
public void rotateY(float angle) {
PGraphics.showDepthWarning("rotateY");
}
@Override
public void rotateZ(float angle) {
PGraphics.showDepthWarning("rotateZ");
}
@Override
public void rotate(float angle, float vx, float vy, float vz) {
PGraphics.showVariationWarning("rotate");
}
@Override
public void applyMatrix(float n00, float n01, float n02, float n03,
float n10, float n11, float n12, float n13,
float n20, float n21, float n22, float n23,
float n30, float n31, float n32, float n33) {
PGraphics.showVariationWarning("applyMatrix");
}
@Override
public void scale(float sx, float sy, float sz) {
PGraphics.showDepthWarningXYZ("scale");
}
///////////////////////////////////////////////////////////
//
// Setters/getters of individual vertices
@Override
public float getVertexZ(int index) {
PGraphics.showDepthWarningXYZ("getVertexZ");
return 0;
}
@Override
public void setVertex(int index, float x, float y) {
super.setVertex(index, x, y, 0);
}
@Override
public void setVertex(int index, float x, float y, float z) {
PGraphics.showDepthWarningXYZ("setVertex");
}
}

View File

@@ -1,81 +0,0 @@
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Part of the Processing project - http://processing.org
Copyright (c) 2012 Ben Fry and Casey Reas
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation, version 2.1.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
*/
package processing.opengl;
import processing.core.PApplet;
import processing.core.PShape;
public class PShape3D extends PShapeOpenGL {
public PShape3D(PApplet parent, int family) {
super(parent, family);
}
@Override
public boolean is2D() {
return false;
}
@Override
public boolean is3D() {
return true;
}
////////////////////////////////////////////////////////////////////////
//
// Shape copy
static public PShape3D createShape(PApplet parent, PShape src) {
PShape3D dest = null;
if (src.getFamily() == GROUP) {
dest = PGraphics3D.createShapeImpl(parent, GROUP);
PShape3D.copyGroup(parent, src, dest);
} else if (src.getFamily() == PRIMITIVE) {
dest = PGraphics3D.createShapeImpl(parent, src.getKind(),
src.getParams());
PShape.copyPrimitive(src, dest);
} else if (src.getFamily() == GEOMETRY) {
dest = PGraphics3D.createShapeImpl(parent, src.getKind());
PShape.copyGeometry(src, dest);
} else if (src.getFamily() == PATH) {
dest = PGraphics3D.createShapeImpl(parent, PATH);
PShape.copyPath(src, dest);
}
dest.setName(src.getName());
return dest;
}
static public void copyGroup(PApplet parent, PShape src, PShape dest) {
copyMatrix(src, dest);
copyStyles(src, dest);
copyImage(src, dest);
for (int i = 0; i < src.getChildCount(); i++) {
PShape c = PShape3D.createShape(parent, src.getChild(i));
dest.addChild(c);
}
}
}

View File

@@ -87,7 +87,6 @@ public class PShapeOpenGL extends PShape {
// Texturing
protected HashSet<PImage> textures;
protected PImage texture;
protected boolean strokedTexture;
// ........................................................
@@ -377,8 +376,8 @@ public class PShapeOpenGL extends PShape {
strokedTexture(true);
}
} else {
if (c3d.texture != null) {
addTexture(c3d.texture);
if (c3d.image != null) {
addTexture(c3d.image);
if (c3d.stroke) {
strokedTexture(true);
}
@@ -493,6 +492,77 @@ public class PShapeOpenGL extends PShape {
}
}
///////////////////////////////////////////////////////////
//
// Shape creation (temporary hack)
static protected PShapeOpenGL createShape3D(PApplet parent, PShape src) {
PShapeOpenGL dest = null;
if (src.getFamily() == GROUP) {
dest = PGraphics3D.createShapeImpl(parent, GROUP);
copyGroup3D(parent, src, dest);
} else if (src.getFamily() == PRIMITIVE) {
dest = PGraphics3D.createShapeImpl(parent, src.getKind(),
src.getParams());
PShape.copyPrimitive(src, dest);
} else if (src.getFamily() == GEOMETRY) {
dest = PGraphics3D.createShapeImpl(parent, src.getKind());
PShape.copyGeometry(src, dest);
} else if (src.getFamily() == PATH) {
dest = PGraphics3D.createShapeImpl(parent, PATH);
PShape.copyPath(src, dest);
}
dest.setName(src.getName());
return dest;
}
static public PShapeOpenGL createShape2D(PApplet parent, PShape src) {
PShapeOpenGL dest = null;
if (src.getFamily() == GROUP) {
dest = PGraphics2D.createShapeImpl(parent, GROUP);
copyGroup2D(parent, src, dest);
} else if (src.getFamily() == PRIMITIVE) {
dest = PGraphics2D.createShapeImpl(parent, src.getKind(),
src.getParams());
PShape.copyPrimitive(src, dest);
} else if (src.getFamily() == GEOMETRY) {
dest = PGraphics2D.createShapeImpl(parent, src.getKind());
PShape.copyGeometry(src, dest);
} else if (src.getFamily() == PATH) {
dest = PGraphics2D.createShapeImpl(parent, PATH);
PShape.copyPath(src, dest);
}
dest.setName(src.getName());
return dest;
}
static public void copyGroup3D(PApplet parent, PShape src, PShape dest) {
copyMatrix(src, dest);
copyStyles(src, dest);
copyImage(src, dest);
for (int i = 0; i < src.getChildCount(); i++) {
PShape c = createShape3D(parent, src.getChild(i));
dest.addChild(c);
}
}
static public void copyGroup2D(PApplet parent, PShape src, PShape dest) {
copyMatrix(src, dest);
copyStyles(src, dest);
copyImage(src, dest);
for (int i = 0; i < src.getChildCount(); i++) {
PShape c = createShape2D(parent, src.getChild(i));
dest.addChild(c);
}
}
///////////////////////////////////////////////////////////
@@ -674,13 +744,13 @@ public class PShapeOpenGL extends PShape {
child.texture(tex);
}
} else {
PImage tex0 = texture;
texture = tex;
PImage tex0 = image;
image = tex;
if (tex0 != tex && parent != null) {
((PShapeOpenGL)parent).removeTexture(tex);
}
if (parent != null) {
((PShapeOpenGL)parent).addTexture(texture);
((PShapeOpenGL)parent).addTexture(image);
if (is2D() && stroke) {
((PShapeOpenGL)parent).strokedTexture(true);
}
@@ -697,8 +767,8 @@ public class PShapeOpenGL extends PShape {
child.noTexture();
}
} else {
PImage tex0 = texture;
texture = null;
PImage tex0 = image;
image = null;
if (tex0 != null && parent != null) {
((PShapeOpenGL)parent).removeTexture(tex0);
if (is2D()) {
@@ -785,7 +855,7 @@ public class PShapeOpenGL extends PShape {
if (family == GROUP) {
return textures != null && textures.contains(tex);
} else {
return texture == tex;
return image == tex;
}
}
@@ -794,7 +864,7 @@ public class PShapeOpenGL extends PShape {
if (family == GROUP) {
return strokedTexture;
} else {
return texture != null && stroke;
return image != null && stroke;
}
}
@@ -857,6 +927,10 @@ public class PShapeOpenGL extends PShape {
@Override
public void vertex(float x, float y, float z) {
// if (!is3D) {
// PGraphics.showDepthWarningXYZ("vertex");
// return;
// }
vertexImpl(x, y, z, 0, 0);
}
@@ -872,8 +946,12 @@ public class PShapeOpenGL extends PShape {
PGraphics.showWarning("Cannot add vertices to GROUP shape");
return;
}
// if (!is3D) {
// PGraphics.showDepthWarningXYZ("vertex");
// return;
// }
boolean textured = texture != null;
boolean textured = image != null;
int fcolor = 0x00;
if (fill || textured) {
if (!textured) {
@@ -887,9 +965,9 @@ public class PShapeOpenGL extends PShape {
}
}
if (texture != null && textureMode == IMAGE) {
u = PApplet.min(1, u / texture.width);
v = PApplet.min(1, v / texture.height);
if (image != null && textureMode == IMAGE) {
u = PApplet.min(1, u / image.width);
v = PApplet.min(1, v / image.height);
}
int scolor = 0x00;
@@ -1202,7 +1280,7 @@ public class PShapeOpenGL extends PShape {
if (fillColor == newFillColor) return;
fillColor = newFillColor;
if (texture == null) {
if (image == null) {
Arrays.fill(inGeo.colors, 0, inGeo.vertexCount,
PGL.javaToNativeARGB(fillColor));
if (shapeEnded && tessellated && hasPolys) {
@@ -1344,7 +1422,7 @@ public class PShapeOpenGL extends PShape {
stroke = true;
}
updateStrokeColor(calcColor);
if (is2D() && texture != null && parent != null) {
if (is2D() && image != null && parent != null) {
((PShapeOpenGL)parent).strokedTexture(true);
}
}
@@ -1496,7 +1574,7 @@ public class PShapeOpenGL extends PShape {
if (tintColor == newTintColor) return;
tintColor = newTintColor;
if (texture != null) {
if (image != null) {
Arrays.fill(inGeo.colors, 0, inGeo.vertexCount,
PGL.javaToNativeARGB(tintColor));
if (shapeEnded && tessellated && hasPolys) {
@@ -1796,6 +1874,10 @@ public class PShapeOpenGL extends PShape {
@Override
public void translate(float tx, float ty, float tz) {
// if (!is3D) {
// PGraphics.showVariationWarning("translate");
// return;
// }
transform(TRANSLATE, tx, ty, tz);
}
@@ -1806,8 +1888,38 @@ public class PShapeOpenGL extends PShape {
}
@Override
public void rotateX(float angle) {
// if (!is3D) {
// PGraphics.showDepthWarning("rotateX");
// return;
// }
rotate(angle, 1, 0, 0);
}
@Override
public void rotateY(float angle) {
// if (!is3D) {
// PGraphics.showDepthWarning("rotateY");
// return;
// }
rotate(angle, 0, 1, 0);
}
@Override
public void rotateZ(float angle) {
transform(ROTATE, angle);
}
@Override
public void rotate(float angle, float v0, float v1, float v2) {
// if (!is3D) {
// PGraphics.showVariationWarning("rotate");
// return;
// }
transform(ROTATE, angle, v0, v1, v2);
}
@@ -1826,6 +1938,10 @@ public class PShapeOpenGL extends PShape {
@Override
public void scale(float x, float y, float z) {
// if (!is3D) {
// PGraphics.showDepthWarningXYZ("scale");
// return;
// }
transform(SCALE, x, y, z);
}
@@ -1850,6 +1966,10 @@ public class PShapeOpenGL 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 (!is3D) {
// PGraphics.showVariationWarning("applyMatrix");
// return;
// }
transform(MATRIX, n00, n01, n02, n03,
n10, n11, n12, n13,
n20, n21, n22, n23,
@@ -2000,6 +2120,10 @@ public class PShapeOpenGL extends PShape {
public void bezierVertex(float x2, float y2, float z2,
float x3, float y3, float z3,
float x4, float y4, float z4) {
// if (!is3D) {
// PGraphics.showDepthWarningXYZ("bezierVertex");
// return;
// }
bezierVertexImpl(x2, y2, z2,
x3, y3, z3,
x4, y4, z4);
@@ -2030,6 +2154,10 @@ public class PShapeOpenGL extends PShape {
@Override
public void quadraticVertex(float cx, float cy, float cz,
float x3, float y3, float z3) {
// if (!is3D) {
// PGraphics.showDepthWarningXYZ("quadraticVertex");
// return;
// }
quadraticVertexImpl(cx, cy, cz,
x3, y3, z3);
}
@@ -2075,6 +2203,10 @@ public class PShapeOpenGL extends PShape {
@Override
public void curveVertex(float x, float y, float z) {
// if (!is3D) {
// PGraphics.showDepthWarningXYZ("curveVertex");
// return;
// }
curveVertexImpl(x, y, z);
}
@@ -2517,7 +2649,7 @@ public class PShapeOpenGL extends PShape {
tessellator.setInGeometry(inGeo);
tessellator.setTessGeometry(tessGeo);
tessellator.setFill(fill || texture != null);
tessellator.setFill(fill || image != null);
tessellator.setStroke(stroke);
tessellator.setStrokeColor(strokeColor);
tessellator.setStrokeWeight(strokeWeight);
@@ -2591,8 +2723,8 @@ public class PShapeOpenGL extends PShape {
tessellatePath();
}
if (texture != null && parent != null) {
((PShapeOpenGL)parent).addTexture(texture);
if (image != null && parent != null) {
((PShapeOpenGL)parent).addTexture(image);
}
firstPolyIndexCache = tessellator.firstPolyIndexCache;
@@ -3159,7 +3291,7 @@ public class PShapeOpenGL extends PShape {
protected boolean startStrokedTex(int n) {
return texture != null && (n == firstLineIndexCache ||
return image != null && (n == firstLineIndexCache ||
n == firstPointIndexCache);
}
@@ -4101,7 +4233,7 @@ public class PShapeOpenGL extends PShape {
}
} else {
render(gl, texture);
render(gl, image);
}
post(gl);