use of org.rajawali3d.Object3D in project Rajawali by Rajawali.
the class LoaderGCode method readGCode.
/**
* @param buffer
* @return
* @throws IOException
*/
protected Object3D readGCode(BufferedInputStream buffer) throws IOException {
RajLog.i("GCodePaser: reading file");
Object3D ret = new Object3D();
String codeLine;
// Read the facet
SupportedCommands cmd = null;
GCodeLine motion = null, prevMotion = null;
GCodeLayer currentLayer = new GCodeLayer();
float lastZPos = 0, lastExtrudeZ = 0, x, y;
@SuppressWarnings("unused") float // default for millis
units = 1F;
boolean relative = false;
prevMotion = new GCodeLine();
prevMotion.setX(0.0f);
prevMotion.setY(0.0f);
prevMotion.setZ(0.0f);
prevMotion.setE(0.0f);
prevMotion.setF(0.0f);
StringBuilder lnBuilder = new StringBuilder(1024);
int lineNum = 0;
while (buffer.available() > 0) {
byte b = (byte) buffer.read();
if (b != '\n') {
lnBuilder.append((char) b);
continue;
} else {
codeLine = lnBuilder.toString();
lnBuilder.delete(0, lnBuilder.length());
}
// while ((codeline = buffer.readLine()) != null) {
if (codeLine.startsWith(";")) {
continue;
}
String[] tokens = codeLine.split(" ");
if (null == tokens || tokens.length == 0) {
continue;
}
try {
cmd = SupportedCommands.fromString(tokens[0]);
} catch (IllegalArgumentException e) {
RajLog.w("encountered unsupported gcode:" + tokens[0]);
continue;
}
switch(cmd) {
case G1:
motion = new GCodeLine(codeLine);
motion.setOrigin(prevMotion);
// TODO color lines based on travel and speed
if (motion.getX() == 0xFFFFFFFF && motion.getY() == 0xFFFFFFFF && motion.getZ() == 0xFFFFFFFF) {
// extrusion or speed setting
continue;
}
x = motion.getX() == 0xFFFFFFFF ? 0 : motion.getX();
y = motion.getY() == 0xFFFFFFFF ? 0 : motion.getY();
if (motion.getZ() != 0xFFFFFFFF) {
lastZPos = motion.getZ();
if (x == 0 && y == 0) {
continue;
}
}
currentLayer.getPoints().add(new Vector3(x, y, lastZPos));
if (motion.getE() != 0xFFFFFFFF) {
float delta;
if (relative) {
delta = motion.getE() - prevMotion.getE();
} else {
delta = motion.getE();
if (delta == 0xFFFFFFFF) {
delta = 0;
}
}
if (delta > 0) {
// check if extruding at new Z
if (lastZPos > lastExtrudeZ) {
// || layers.empty()
lastExtrudeZ = lastZPos;
ret.addChild(new Line3D(currentLayer.getPoints(), 1f, Color.argb(255, 0x55, 0x11, 0xEF)));
currentLayer = new GCodeLayer();
}
}
}
prevMotion = motion;
break;
case G21:
// G21: Set Units to Millimeters
// Example: G21
units = 1F;
break;
case G90:
// G90: Set to Absolute Positioning
// Example: G90
relative = false;
break;
case G91:
// G91: Set to Relative Positioning
// Example: G91
relative = true;
break;
case G92:
// G92: Set Position
// Example: G92 E0
motion = new GCodeLine(codeLine);
if (motion.getX() != -0xFFFFFFFF) {
prevMotion.setX(motion.getX());
}
if (motion.getY() != -0xFFFFFFFF) {
prevMotion.setY(motion.getY());
}
if (motion.getZ() != -0xFFFFFFFF) {
prevMotion.setZ(motion.getZ());
}
if (motion.getE() != -0xFFFFFFFF) {
prevMotion.setE(motion.getE());
}
break;
case M82:
// no-op, so long as M83 is not supported.
break;
case M84:
// no-op
break;
}
// RajLog.d("gcode parser parsed line #" + lineNum++);
}
return ret;
}
use of org.rajawali3d.Object3D in project Rajawali by Rajawali.
the class LoaderOBJ method parse.
@Override
public LoaderOBJ parse() throws ParsingException {
super.parse();
BufferedReader buffer = null;
if (mFile == null) {
InputStream fileIn = mResources.openRawResource(mResourceId);
buffer = new BufferedReader(new InputStreamReader(fileIn));
} else {
try {
buffer = new BufferedReader(new FileReader(mFile));
} catch (FileNotFoundException e) {
RajLog.e("[" + getClass().getCanonicalName() + "] Could not find file.");
e.printStackTrace();
}
}
String line;
ObjIndexData currObjIndexData = new ObjIndexData(new Object3D(generateObjectName()));
ArrayList<ObjIndexData> objIndices = new ArrayList<ObjIndexData>();
ArrayList<Float> vertices = new ArrayList<Float>();
ArrayList<Float> texCoords = new ArrayList<Float>();
ArrayList<Float> normals = new ArrayList<Float>();
MaterialLib matLib = new MaterialLib();
String currentMaterialName = null;
boolean currentObjHasFaces = false;
Object3D currentGroup = mRootObject;
mRootObject.setName("default");
Map<String, Object3D> groups = new HashMap<String, Object3D>();
try {
while ((line = buffer.readLine()) != null) {
// Skip comments and empty lines.
if (line.length() == 0 || line.charAt(0) == '#')
continue;
StringTokenizer parts = new StringTokenizer(line, " ");
int numTokens = parts.countTokens();
if (numTokens == 0)
continue;
String type = parts.nextToken();
if (type.equals(VERTEX)) {
vertices.add(Float.parseFloat(parts.nextToken()));
vertices.add(Float.parseFloat(parts.nextToken()));
vertices.add(Float.parseFloat(parts.nextToken()));
} else if (type.equals(FACE)) {
currentObjHasFaces = true;
boolean isQuad = numTokens == 5;
int[] quadvids = new int[4];
int[] quadtids = new int[4];
int[] quadnids = new int[4];
boolean emptyVt = line.indexOf("//") > -1;
if (emptyVt)
line = line.replace("//", "/");
parts = new StringTokenizer(line);
parts.nextToken();
StringTokenizer subParts = new StringTokenizer(parts.nextToken(), "/");
int partLength = subParts.countTokens();
boolean hasuv = partLength >= 2 && !emptyVt;
boolean hasn = partLength == 3 || (partLength == 2 && emptyVt);
int idx;
for (int i = 1; i < numTokens; i++) {
if (i > 1)
subParts = new StringTokenizer(parts.nextToken(), "/");
idx = Integer.parseInt(subParts.nextToken());
if (idx < 0)
idx = (vertices.size() / 3) + idx;
else
idx -= 1;
if (!isQuad)
currObjIndexData.vertexIndices.add(idx);
else
quadvids[i - 1] = idx;
if (hasuv) {
idx = Integer.parseInt(subParts.nextToken());
if (idx < 0)
idx = (texCoords.size() / 2) + idx;
else
idx -= 1;
if (!isQuad)
currObjIndexData.texCoordIndices.add(idx);
else
quadtids[i - 1] = idx;
}
if (hasn) {
idx = Integer.parseInt(subParts.nextToken());
if (idx < 0)
idx = (normals.size() / 3) + idx;
else
idx -= 1;
if (!isQuad)
currObjIndexData.normalIndices.add(idx);
else
quadnids[i - 1] = idx;
}
}
if (isQuad) {
int[] indices = new int[] { 0, 1, 2, 0, 2, 3 };
for (int i = 0; i < 6; ++i) {
int index = indices[i];
currObjIndexData.vertexIndices.add(quadvids[index]);
currObjIndexData.texCoordIndices.add(quadtids[index]);
currObjIndexData.normalIndices.add(quadnids[index]);
}
}
} else if (type.equals(TEXCOORD)) {
texCoords.add(Float.parseFloat(parts.nextToken()));
texCoords.add(1f - Float.parseFloat(parts.nextToken()));
} else if (type.equals(NORMAL)) {
normals.add(Float.parseFloat(parts.nextToken()));
normals.add(Float.parseFloat(parts.nextToken()));
normals.add(Float.parseFloat(parts.nextToken()));
} else if (type.equals(GROUP)) {
int numGroups = parts.countTokens();
Object3D previousGroup = null;
for (int i = 0; i < numGroups; i++) {
String groupName = parts.nextToken();
if (!groups.containsKey(groupName)) {
groups.put(groupName, new Object3D(groupName));
}
Object3D group = groups.get(groupName);
if (previousGroup != null) {
addChildSetParent(group, previousGroup);
} else {
currentGroup = group;
}
previousGroup = group;
}
RajLog.i("Parsing group: " + currentGroup.getName());
if (currentObjHasFaces) {
objIndices.add(currObjIndexData);
currObjIndexData = new ObjIndexData(new Object3D(generateObjectName()));
RajLog.i("Parsing object: " + currObjIndexData.targetObj.getName());
currObjIndexData.materialName = currentMaterialName;
currentObjHasFaces = false;
}
addChildSetParent(currentGroup, currObjIndexData.targetObj);
} else if (type.equals(OBJECT)) {
String objName = parts.hasMoreTokens() ? parts.nextToken() : generateObjectName();
if (currentObjHasFaces) {
objIndices.add(currObjIndexData);
currObjIndexData = new ObjIndexData(new Object3D(currObjIndexData.targetObj.getName()));
currObjIndexData.materialName = currentMaterialName;
addChildSetParent(currentGroup, currObjIndexData.targetObj);
RajLog.i("Parsing object: " + currObjIndexData.targetObj.getName());
currentObjHasFaces = false;
}
currObjIndexData.targetObj.setName(objName);
} else if (type.equals(MATERIAL_LIB)) {
if (!parts.hasMoreTokens())
continue;
String materialLibPath = mNeedToRenameMtl ? parts.nextToken().replace(".", "_") : parts.nextToken();
RajLog.d("Found Material Lib: " + materialLibPath);
if (mFile != null)
matLib.parse(materialLibPath, null, null);
else
matLib.parse(materialLibPath, mResources.getResourceTypeName(mResourceId), mResources.getResourcePackageName(mResourceId));
} else if (type.equals(USE_MATERIAL)) {
currentMaterialName = parts.nextToken();
if (currentObjHasFaces) {
objIndices.add(currObjIndexData);
currObjIndexData = new ObjIndexData(new Object3D(generateObjectName()));
RajLog.i("Parsing object: " + currObjIndexData.targetObj.getName());
addChildSetParent(currentGroup, currObjIndexData.targetObj);
currentObjHasFaces = false;
}
currObjIndexData.materialName = currentMaterialName;
}
}
buffer.close();
if (currentObjHasFaces) {
RajLog.i("Parsing object: " + currObjIndexData.targetObj.getName());
objIndices.add(currObjIndexData);
}
} catch (IOException e) {
throw new ParsingException(e);
}
int numObjects = objIndices.size();
for (int j = 0; j < numObjects; ++j) {
ObjIndexData oid = objIndices.get(j);
int i;
float[] aVertices = new float[oid.vertexIndices.size() * 3];
float[] aTexCoords = new float[oid.texCoordIndices.size() * 2];
float[] aNormals = new float[oid.normalIndices.size() * 3];
float[] aColors = new float[oid.colorIndices.size() * 4];
int[] aIndices = new int[oid.vertexIndices.size()];
for (i = 0; i < oid.vertexIndices.size(); ++i) {
int faceIndex = oid.vertexIndices.get(i) * 3;
int vertexIndex = i * 3;
try {
aVertices[vertexIndex] = vertices.get(faceIndex);
aVertices[vertexIndex + 1] = vertices.get(faceIndex + 1);
aVertices[vertexIndex + 2] = vertices.get(faceIndex + 2);
aIndices[i] = i;
} catch (ArrayIndexOutOfBoundsException e) {
RajLog.d("Obj array index out of bounds: " + vertexIndex + ", " + faceIndex);
}
}
if (texCoords != null && texCoords.size() > 0) {
for (i = 0; i < oid.texCoordIndices.size(); ++i) {
int texCoordIndex = oid.texCoordIndices.get(i) * 2;
int ti = i * 2;
aTexCoords[ti] = texCoords.get(texCoordIndex);
aTexCoords[ti + 1] = texCoords.get(texCoordIndex + 1);
}
}
for (i = 0; i < oid.colorIndices.size(); ++i) {
int colorIndex = oid.colorIndices.get(i) * 4;
int ti = i * 4;
aTexCoords[ti] = texCoords.get(colorIndex);
aTexCoords[ti + 1] = texCoords.get(colorIndex + 1);
aTexCoords[ti + 2] = texCoords.get(colorIndex + 2);
aTexCoords[ti + 3] = texCoords.get(colorIndex + 3);
}
for (i = 0; i < oid.normalIndices.size(); ++i) {
int normalIndex = oid.normalIndices.get(i) * 3;
int ni = i * 3;
if (normals.size() == 0) {
RajLog.e("[" + getClass().getName() + "] There are no normals specified for this model. Please re-export with normals.");
throw new ParsingException("[" + getClass().getName() + "] There are no normals specified for this model. Please re-export with normals.");
}
aNormals[ni] = normals.get(normalIndex);
aNormals[ni + 1] = normals.get(normalIndex + 1);
aNormals[ni + 2] = normals.get(normalIndex + 2);
}
oid.targetObj.setData(aVertices, aNormals, aTexCoords, aColors, aIndices, false);
try {
matLib.setMaterial(oid.targetObj, oid.materialName);
} catch (TextureException tme) {
throw new ParsingException(tme);
}
if (oid.targetObj.getParent() == null)
addChildSetParent(mRootObject, oid.targetObj);
}
for (Object3D group : groups.values()) {
if (group.getParent() == null)
addChildSetParent(mRootObject, group);
}
if (mRootObject.getNumChildren() == 1 && !mRootObject.getChildAt(0).isContainer())
mRootObject = mRootObject.getChildAt(0);
for (int i = 0; i < mRootObject.getNumChildren(); i++) mergeGroupsAsObjects(mRootObject.getChildAt(i));
return this;
}
use of org.rajawali3d.Object3D in project Rajawali by Rajawali.
the class BlockContainer method parseBlock.
public void parseBlock(AWDLittleEndianDataInputStream dis, BlockHeader blockHeader) throws Exception {
mBaseObject = new Object3D();
mSceneGraphBlock = new SceneGraphBlock();
mSceneGraphBlock.readGraphData(blockHeader, dis);
// Container properties did not exist until 2.1, as such the container will be default 0, 0, 0
if (blockHeader.awdVersion == 2 && blockHeader.awdRevision == 1) {
// FIXME will have to implement this
dis.readProperties();
} else {
dis.readProperties();
}
mBaseObject.setVisible(dis.readByte() != 0);
mBaseObject.isContainer(true);
}
use of org.rajawali3d.Object3D in project Rajawali by Rajawali.
the class BlockTriangleGeometry method parseBlock.
public void parseBlock(AWDLittleEndianDataInputStream dis, BlockHeader blockHeader) throws Exception {
// Lookup name
mLookupName = dis.readVarString();
// Count of sub geometries
mSubGeometryCount = dis.readUnsignedShort();
// TODO Meshes need to be joined in some fashion. This might work. Need to test it I suppose.
// One object for each sub geometry
mBaseObjects = new Object3D[mSubGeometryCount];
// Debug
if (RajLog.isDebugEnabled()) {
RajLog.d(" Lookup Name: " + mLookupName);
RajLog.d(" Sub Geometry Count: " + mSubGeometryCount);
}
// Determine the precision for the block
final boolean geoAccuracy = (blockHeader.flags & BlockHeader.FLAG_ACCURACY_GEO) == BlockHeader.FLAG_ACCURACY_GEO;
final short geoNr = geoAccuracy ? AWDLittleEndianDataInputStream.TYPE_FLOAT64 : AWDLittleEndianDataInputStream.TYPE_FLOAT32;
// Read the properties
SparseArray<Short> properties = new SparseArray<Short>();
// Scale Texture U
properties.put(1, geoNr);
// Scale Texture V
properties.put(2, geoNr);
// TODO Apply texture scales, need example of this working.
dis.readProperties(properties);
// Calculate the sizes
final int geoPrecisionSize = blockHeader.globalPrecisionGeo ? 8 : 4;
// Read each sub mesh data
for (int parsedSub = 0; parsedSub < mSubGeometryCount; ++parsedSub) {
long subMeshEnd = dis.getPosition() + dis.readUnsignedInt();
// Geometry
float[] vertices = null;
int[] indices = null;
float[] uvs = null;
float[] normals = null;
int[] joints = null;
float[] weights = null;
// Skip reading of mesh properties for now (per AWD implementation)
dis.readProperties();
// Read each data type from the mesh
while (dis.getPosition() < subMeshEnd) {
int idx = 0;
int type = dis.readUnsignedByte();
int typeF = dis.readUnsignedByte();
long subLength = dis.readUnsignedInt();
long subEnd = dis.getPosition() + subLength;
if (RajLog.isDebugEnabled())
RajLog.d(" Mesh Data: t:" + type + " tf:" + typeF + " l:" + subLength + " ls:" + dis.getPosition() + " le:" + subEnd);
// Process the mesh data by type
switch((int) type) {
case // Vertex positions
1:
vertices = new float[(int) (subLength / geoPrecisionSize)];
while (idx < vertices.length) {
// X, Y, Z
vertices[idx++] = (float) dis.readPrecisionNumber(blockHeader.globalPrecisionGeo);
vertices[idx++] = (float) dis.readPrecisionNumber(blockHeader.globalPrecisionGeo);
vertices[idx++] = (float) -dis.readPrecisionNumber(blockHeader.globalPrecisionGeo);
}
break;
case // Face indices
2:
indices = new int[(int) (subLength / 2)];
while (idx < indices.length) {
indices[idx + 2] = dis.readUnsignedShort();
indices[idx + 1] = dis.readUnsignedShort();
indices[idx] = dis.readUnsignedShort();
idx += 3;
}
break;
case // UV coordinates
3:
uvs = new float[(int) (subLength / geoPrecisionSize)];
while (idx < uvs.length) uvs[idx++] = (float) dis.readPrecisionNumber(blockHeader.globalPrecisionGeo);
break;
case // Vertex normals
4:
normals = new float[(int) (subLength / geoPrecisionSize)];
while (idx < normals.length) {
normals[idx++] = (float) dis.readPrecisionNumber(blockHeader.globalPrecisionGeo);
normals[idx++] = (float) dis.readPrecisionNumber(blockHeader.globalPrecisionGeo);
normals[idx++] = (float) dis.readPrecisionNumber(blockHeader.globalPrecisionGeo);
}
break;
case // Joint index
6:
joints = new int[(int) (subLength / 2)];
while (idx < joints.length) joints[idx++] = dis.readUnsignedShort();
break;
case // Joint weight
7:
weights = new float[(int) (subLength / geoPrecisionSize)];
while (idx < weights.length) weights[idx++] = (float) dis.readPrecisionNumber(blockHeader.globalPrecisionGeo);
break;
// Vertex tangents
case 5:
default:
// Unknown mesh data, skipping
dis.skip(subLength);
}
// Validate each mesh data ending. This is a sanity check against precision flags.
if (dis.getPosition() != subEnd)
throw new ParsingException("Unexpected ending. Expected " + subEnd + ". Got " + dis.getPosition());
}
dis.readUserAttributes(null);
// Verify the arrays
if (vertices == null)
vertices = new float[0];
if (normals == null)
normals = new float[0];
if (uvs == null)
uvs = new float[0];
if (indices == null)
indices = new int[0];
// FIXME This should be combining sub geometry not creating objects
if (joints != null && joints.length > 0) {
/*
* Prepares skeletal animation object as far as possible; setting mesh
* and skeletal weight data. The object will not yet have an actual
* skeleton applied to it.
*/
SkeletalAnimationChildObject3D obj = new SkeletalAnimationChildObject3D();
obj.setData(vertices, normals, uvs, null, indices, false);
int numVertices = vertices.length / 3;
// AWD stipulates all vertices have same # bindings, possibly 0 weighted
int weightsPerVertex = weights.length / numVertices;
// true WPV may be out of range, so clamp
int clampWeightsPerVertex = Math.min(weightsPerVertex, SkeletalAnimationChildObject3D.MAX_WEIGHTS_PER_VERTEX);
// one BoneVertex per actual vertex, maps to N weights & joint indices
BoneVertex[] bvertices = new BoneVertex[numVertices];
ArrayList<BoneWeight> bweights = new ArrayList<BoneWeight>();
int maxWeightsPerVertex = 0;
int vertexWeightIndex = 0;
for (int vert = 0; vert < numVertices; vert++) {
BoneVertex bone = new BoneVertex();
bvertices[vert] = bone;
// we may ignore weights, so map to our custom list
bone.weightIndex = bweights.size();
// true position in raw weight array
vertexWeightIndex = vert * weightsPerVertex;
// only add first [clamp] non-zero weights
for (int wgt = 0; wgt < clampWeightsPerVertex; wgt++) {
if (weights[vertexWeightIndex + wgt] == 0)
continue;
BoneWeight weight = new BoneWeight();
// joints and weights are indexed together
weight.jointIndex = joints[vertexWeightIndex + wgt];
weight.weightValue = weights[vertexWeightIndex + wgt];
bone.numWeights++;
bweights.add(weight);
}
maxWeightsPerVertex = Math.max(maxWeightsPerVertex, bone.numWeights);
}
// extract the clean BoneWeight array
BoneWeight[] boneweights = bweights.toArray(new BoneWeight[bweights.size()]);
obj.setMaxBoneWeightsPerVertex(maxWeightsPerVertex);
obj.setSkeletonMeshData(bvertices, boneweights);
//obj.setInverseZScale(true);
mBaseObjects[parsedSub] = obj;
} else {
mBaseObjects[parsedSub] = new Object3D();
mBaseObjects[parsedSub].setData(vertices, normals, uvs, null, indices, false);
}
}
dis.readUserAttributes(null);
}
use of org.rajawali3d.Object3D in project Rajawali by Rajawali.
the class BlockTriangleGeometry method getBaseObject3D.
@Override
public Object3D getBaseObject3D() {
if (finalObject != null)
return finalObject;
if (mBaseObjects[0] instanceof SkeletalAnimationChildObject3D) {
SkeletalAnimationObject3D container = new SkeletalAnimationObject3D();
for (int i = 0; i < mBaseObjects.length; i++) {
SkeletalAnimationChildObject3D child = (SkeletalAnimationChildObject3D) mBaseObjects[i];
child.setSkeleton(container);
container.addChild(child);
}
finalObject = container;
} else if (mBaseObjects.length == 1)
finalObject = mBaseObjects[0];
else {
final Object3D container = new Object3D(mLookupName);
container.isContainer(true);
for (int i = 0; i < mBaseObjects.length; i++) container.addChild(mBaseObjects[i]);
finalObject = container;
}
return finalObject;
}
Aggregations