use of net.drewke.tdme.math.Vector3 in project tdme by andreasdr.
the class DAEReader method readLevel.
/**
* Reads Collada DAE file level
* @param path name
* @param file name
* @throws Exception
* @return Model instance
*/
public static LevelEditorLevel readLevel(String pathName, String fileName) throws Exception {
// (re)create tm files folder
File tmFilesFolder = new File(pathName + "/" + fileName + "-models");
if (tmFilesFolder.exists()) {
tmFilesFolder.delete();
}
tmFilesFolder.mkdir();
// create level
LevelEditorLevel levelEditorLevel = new LevelEditorLevel();
LevelPropertyPresets.getInstance().setDefaultLevelProperties(levelEditorLevel);
// load dae xml document
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = builder.parse(FileSystem.getInstance().getInputStream(pathName, fileName));
Element xmlRoot = document.getDocumentElement();
// authoring tool
AuthoringTool authoringTool = getAuthoringTool(xmlRoot);
// up vector and rotation order
UpVector upVector = getUpVector(xmlRoot);
RotationOrder rotationOrder = null;
switch(upVector) {
case Y_UP:
rotationOrder = RotationOrder.ZYX;
case Z_UP:
rotationOrder = RotationOrder.YZX;
}
levelEditorLevel.setRotationOrder(rotationOrder);
// parse scene from xml
String xmlSceneId = null;
Element xmlScene = getChildrenByTagName(xmlRoot, "scene").get(0);
for (Element xmlInstanceVisualscene : getChildrenByTagName(xmlScene, "instance_visual_scene")) {
xmlSceneId = xmlInstanceVisualscene.getAttribute("url").substring(1);
}
// check for xml scene id
if (xmlSceneId == null) {
throw new ModelFileIOException("No scene id found");
}
// parse visual scenes
Element xmlLibraryVisualScenes = getChildrenByTagName(xmlRoot, "library_visual_scenes").get(0);
for (Element xmlLibraryVisualScene : getChildrenByTagName(xmlLibraryVisualScenes, "visual_scene")) {
String xmlVisualSceneId = xmlLibraryVisualScene.getAttribute("id");
if (xmlVisualSceneId.equals(xmlSceneId)) {
// default FPS
float fps = 30f;
// parse frames per second
List<Element> xmlExtraNodes = getChildrenByTagName(xmlLibraryVisualScene, "extra");
if (xmlExtraNodes.isEmpty() == false) {
Element xmlExtraNode = xmlExtraNodes.get(0);
for (Element xmlTechnique : getChildrenByTagName(xmlExtraNode, "technique")) {
List<Element> xmlFrameRateNodes = getChildrenByTagName(xmlTechnique, "frame_rate");
if (xmlFrameRateNodes.isEmpty() == false) {
fps = Float.parseFloat(xmlFrameRateNodes.get(0).getTextContent());
break;
}
}
}
// visual scene root nodes
LevelEditorEntityLibrary entityLibrary = levelEditorLevel.getEntityLibrary();
LevelEditorEntity emptyEntity = null;
int nodeIdx = 0;
for (Element xmlNode : getChildrenByTagName(xmlLibraryVisualScene, "node")) {
// derive model name from node id
String modelName = xmlNode.getAttribute("id");
// replace blender _|-NUMBER, not sure if this is a good idea for all cases, we will see
modelName = modelName.replaceAll("[\\-\\_]{1}+[0-9]+$", "");
// replace number at the end still, not sure if this is a good idea for all cases, we will see
modelName = modelName.replaceAll("[0-9]+$", "");
// check if name is available, if not extend with numbers :DDD
boolean haveName = entityLibrary.getEntityCount() == 0;
if (haveName == false) {
for (int i = 0; i < 10000; i++) {
haveName = true;
String modelNameTry = modelName + (i == 0 ? "" : String.valueOf(i));
for (int entityIdx = 0; entityIdx < entityLibrary.getEntityCount(); entityIdx++) {
LevelEditorEntity entity = entityLibrary.getEntityAt(entityIdx);
if (entity.getName().equals(modelNameTry) == true) {
haveName = false;
break;
}
}
if (haveName == true) {
modelName = modelNameTry;
break;
}
}
}
// do we have a name now?
if (haveName == false) {
// nope, cant imagine this will happen
System.out.println("DAEReader::readLevel(): Skipping model '" + modelName + "' as no name could be created for it.");
continue;
}
// create model
Model model = new Model(pathName + File.separator + fileName + '-' + modelName, fileName + '-' + modelName, upVector, rotationOrder, null);
// import matrix
setupModelImportRotationMatrix(xmlRoot, model);
Matrix4x4 modelImportRotationMatrix = new Matrix4x4(model.getImportTransformationsMatrix());
setupModelImportScaleMatrix(xmlRoot, model);
// translation, scaling, rotation
Vector3 translation = new Vector3();
Vector3 scale = new Vector3();
Vector3 rotation = new Vector3();
Vector3 xAxis = new Vector3();
Vector3 yAxis = new Vector3();
Vector3 zAxis = new Vector3();
// set up local transformations matrix
Matrix4x4 nodeTransformationsMatrix = null;
List<Element> xmlMatrixElements = getChildrenByTagName(xmlNode, "matrix");
if (xmlMatrixElements.size() == 1) {
String xmlMatrix = xmlMatrixElements.get(0).getTextContent();
StringTokenizer t = new StringTokenizer(xmlMatrix, " \n\r");
//
nodeTransformationsMatrix = new Matrix4x4(Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken())).transpose();
}
// check if we have node transformations matrix
if (nodeTransformationsMatrix == null) {
throw new ModelFileIOException("missing node transformations matrix for node " + xmlNode.getAttribute("id"));
}
// extract coordinate system axes
nodeTransformationsMatrix.getAxes(xAxis, yAxis, zAxis);
nodeTransformationsMatrix.getTranslation(translation);
nodeTransformationsMatrix.getScale(scale);
// normalize coordinate axes
xAxis.normalize();
yAxis.normalize();
zAxis.normalize();
// write back normalized x axis
nodeTransformationsMatrix.setAxes(xAxis, yAxis, zAxis);
// TODO: move me into Matrix4x4 decomposing code?
if ((upVector == UpVector.Y_UP && Vector3.computeDotProduct(Vector3.computeCrossProduct(xAxis, yAxis), zAxis) < 0.0f) || (upVector == UpVector.Z_UP && Vector3.computeDotProduct(Vector3.computeCrossProduct(xAxis, zAxis), yAxis) < 0.0f)) {
// negate axes
xAxis.scale(-1f);
yAxis.scale(-1f);
zAxis.scale(-1f);
// and write back to node transformation matrices
nodeTransformationsMatrix.setAxes(xAxis, yAxis, zAxis);
// scale
scale.scale(-1f);
}
// determine rotation
nodeTransformationsMatrix.computeEulerAngles(rotation);
// apply model import matrix
modelImportRotationMatrix.multiply(scale, scale);
modelImportRotationMatrix.multiply(rotation, rotation);
model.getImportTransformationsMatrix().multiply(translation, translation);
// set up frames per seconds
model.setFPS(fps);
// read sub groups
Group group = readVisualSceneNode(authoringTool, pathName, model, null, xmlRoot, xmlNode, fps);
if (group != null) {
group.getTransformationsMatrix().identity();
model.getSubGroups().put(group.getId(), group);
model.getGroups().put(group.getId(), group);
}
// set up joints
ModelHelper.setupJoints(model);
// fix animation length
ModelHelper.fixAnimationLength(model);
// prepare for indexed rendering
ModelHelper.prepareForIndexedRendering(model);
// check if empty model
EntityType entityType = EntityType.MODEL;
ModelStatistics modelStatistics = ModelUtilities.computeModelStatistics(model);
if (modelStatistics.getOpaqueFaceCount() == 0 && modelStatistics.getTransparentFaceCount() == 0) {
entityType = EntityType.EMPTY;
}
// level editor entity
LevelEditorEntity levelEditorEntity = null;
// model
if (entityType == EntityType.MODEL) {
// check if we have that model already
for (int i = 0; i < levelEditorLevel.getEntityLibrary().getEntityCount(); i++) {
LevelEditorEntity levelEditorEntityCompare = levelEditorLevel.getEntityLibrary().getEntityAt(i);
if (levelEditorEntityCompare.getType() != EntityType.MODEL)
continue;
if (ModelUtilities.equals(model, levelEditorEntityCompare.getModel()) == true) {
levelEditorEntity = levelEditorEntityCompare;
break;
}
}
// create level editor model, if not yet exists
if (levelEditorEntity == null) {
// save model
TMWriter.write(model, pathName + "/" + fileName + "-models", modelName + ".tm");
// create level editor entity
levelEditorEntity = entityLibrary.addModel(nodeIdx++, modelName, modelName, pathName + "/" + fileName + "-models", modelName + ".tm", new Vector3());
}
} else // empty
if (entityType == EntityType.EMPTY) {
if (emptyEntity == null) {
emptyEntity = entityLibrary.addEmpty(nodeIdx++, "Default Empty", "");
}
levelEditorEntity = emptyEntity;
} else {
System.out.println("DAEReader::readLevel(): unknown entity type. Skipping");
continue;
}
// level editor object transformations
Transformations levelEditorObjectTransformations = new Transformations();
levelEditorObjectTransformations.getTranslation().set(translation);
levelEditorObjectTransformations.getRotations().add(new Rotation(rotation.getArray()[rotationOrder.getAxis0VectorIndex()], rotationOrder.getAxis0()));
levelEditorObjectTransformations.getRotations().add(new Rotation(rotation.getArray()[rotationOrder.getAxis1VectorIndex()], rotationOrder.getAxis1()));
levelEditorObjectTransformations.getRotations().add(new Rotation(rotation.getArray()[rotationOrder.getAxis2VectorIndex()], rotationOrder.getAxis2()));
levelEditorObjectTransformations.getScale().set(scale);
levelEditorObjectTransformations.update();
// level editor object
LevelEditorObject object = new LevelEditorObject(xmlNode.getAttribute("id"), xmlNode.getAttribute("id"), levelEditorObjectTransformations, levelEditorEntity);
// add object to level
levelEditorLevel.addObject(object);
}
}
}
// save level
LevelFileExport.export(pathName + "/" + fileName + ".tl", levelEditorLevel);
//
return levelEditorLevel;
}
use of net.drewke.tdme.math.Vector3 in project tdme by andreasdr.
the class TMReader method read.
/**
* TDME model format reader
* @param path name
* @param file name
* @throws IOException
* @throws ModelIOException
* @return model
*/
public static Model read(String pathName, String fileName) throws IOException, ModelFileIOException {
InputStream is = null;
try {
is = FileSystem.getInstance().getInputStream(pathName, fileName);
// version major.minor = 1.0
String fileId = readString(is);
if (fileId == null || fileId.equals("TDME Model") == false) {
throw new ModelFileIOException("File is not a TDME model file, file id = '" + fileId + "'");
}
byte[] version = new byte[3];
version[0] = readByte(is);
version[1] = readByte(is);
version[2] = readByte(is);
if (version[0] != 1 || version[1] != 0 || version[2] != 0) {
throw new ModelFileIOException("Version mismatch, should be 1.0.0, but is " + version[0] + "." + version[1] + "." + version[2]);
}
// meta data
String name = readString(is);
// up vector, rotation order, bounding box
UpVector upVector = UpVector.valueOf(readString(is));
RotationOrder rotationOrder = RotationOrder.valueOf(readString(is));
BoundingBox boundingBox = new BoundingBox(new Vector3(readFloatArray(is)), new Vector3(readFloatArray(is)));
// create object
Model model = new Model(pathName + File.separator + fileName, fileName, upVector, rotationOrder, boundingBox);
// set additional data
model.setFPS(readFloat(is));
model.getImportTransformationsMatrix().set(readFloatArray(is));
// materials
int materialCount = readInt(is);
for (int i = 0; i < materialCount; i++) {
Material material = readMaterial(is);
model.getMaterials().put(material.getId(), material);
}
// sub groups
readSubGroups(is, model, null, model.getSubGroups());
//
return model;
} catch (IOException ioe) {
throw ioe;
} catch (ModelFileIOException mfioe) {
throw mfioe;
} finally {
if (is != null) {
is.close();
}
}
}
use of net.drewke.tdme.math.Vector3 in project tdme by andreasdr.
the class PartitionQuadTree method createPartition.
/**
* Creates a partition
* @param parent
* @param x
* @param y
* @param z
* @param partition size
* @return partition tree node
*/
public PartitionTreeNode createPartition(PartitionTreeNode parent, int x, int y, int z, float partitionSize) {
PartitionTreeNode node;
node = new PartitionTreeNode();
node.partitionSize = partitionSize;
node.x = x;
node.y = y;
node.z = z;
node.parent = parent;
node.bv = new BoundingBox(new Vector3(x * partitionSize, y * partitionSize, z * partitionSize), new Vector3(x * partitionSize + partitionSize, y * partitionSize + partitionSize, z * partitionSize + partitionSize));
// System.out.println(this.hashCode() + ":" + "FrumstumPartition::createPartition()::" + node.bv);
node.subNodes = null;
node.subNodesByCoordinate = null;
node.partitionObjects = null;
// register in parent sub nodes
if (parent.subNodes == null) {
parent.subNodes = new ArrayList<PartitionTreeNode>();
}
parent.subNodes.add(node);
// register in parent sub nodes by coordinate
if (parent.subNodesByCoordinate == null) {
parent.subNodesByCoordinate = new HashMap<Key, PartitionTreeNode>();
}
Key key = new Key();
key.reset();
key.append(node.x);
key.append(",");
key.append(node.y);
key.append(",");
key.append(node.z);
parent.subNodesByCoordinate.put(key, node);
// create sub nodes
if (partitionSize > PARTITION_SIZE_MIN) {
for (int _y = 0; _y < 2; _y++) for (int _x = 0; _x < 2; _x++) for (int _z = 0; _z < 2; _z++) {
createPartition(node, (int) ((x * partitionSize) / (partitionSize / 2f)) + _x, (int) ((y * partitionSize) / (partitionSize / 2f)) + _y, (int) ((z * partitionSize) / (partitionSize / 2f)) + _z, partitionSize / 2f);
}
} else {
node.partitionObjects = new ArrayList<Entity>();
}
//
return node;
}
use of net.drewke.tdme.math.Vector3 in project tdme by andreasdr.
the class WFObjReader method read.
/**
* Reads a wave front object file
* @param path name
* @param file name
* @return model
* @throws IOException
* @throws ModelIOException
*/
public static Model read(String pathName, String fileName) throws IOException, ModelFileIOException {
// create object
Model model = new Model(pathName + File.separator + fileName, fileName, UpVector.Y_UP, RotationOrder.XYZ, null);
ArrayList<Vector3> vertices = new ArrayList<Vector3>();
ArrayList<TextureCoordinate> textureCoordinates = new ArrayList<TextureCoordinate>();
HashMap<String, Material> materials = model.getMaterials();
HashMap<String, Group> subGroups = model.getSubGroups();
HashMap<String, Group> groups = model.getGroups();
// current group
Group group = null;
// model vertices -> group vertices mapping
HashMap<Integer, Integer> modelGroupVerticesMapping = null;
// model texture coordinates -> group texture coordinates mapping
HashMap<Integer, Integer> modelGroupTextureCoordinatesMapping = null;
// current group data
ArrayList<Face> groupFacesEntityFaces = null;
ArrayList<Vector3> groupVertices = null;
ArrayList<Vector3> groupNormals = null;
ArrayList<TextureCoordinate> groupTextureCoordinates = null;
// current group's faces entity
ArrayList<FacesEntity> groupFacesEntities = null;
FacesEntity groupFacesEntity = null;
//
DataInputStream inputStream = new DataInputStream(FileSystem.getInstance().getInputStream(pathName, fileName));
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
//
try {
//
String line;
while ((line = reader.readLine()) != null) {
line = line.trim();
// skip on comments
if (line.startsWith("#")) {
continue;
}
// determine index of first ' ' which will separate command from arguments
int commandEndIdx = line.indexOf(' ');
if (commandEndIdx == -1)
commandEndIdx = line.length();
// determine command
String command = line.substring(0, commandEndIdx).trim().toLowerCase();
// determine arguments if any exist
String arguments = command.length() + 1 > line.length() ? "" : line.substring(command.length() + 1);
// parse
if (command.equals("mtllib")) {
String materialFileName = arguments;
materials = WFObjReader.readMaterials(pathName, materialFileName);
} else if (command.equals("v")) {
StringTokenizer t = new StringTokenizer(arguments, " ");
float x = Float.parseFloat(t.nextToken());
float y = Float.parseFloat(t.nextToken());
float z = Float.parseFloat(t.nextToken());
// add vertex
vertices.add(new Vector3(x, y, z));
} else if (command.equals("vt")) {
StringTokenizer t = new StringTokenizer(arguments, " ");
float u = Float.parseFloat(t.nextToken());
float v = Float.parseFloat(t.nextToken());
textureCoordinates.add(new TextureCoordinate(u, v));
} else if (command.equals("f")) {
StringTokenizer t2;
StringTokenizer t = new StringTokenizer(arguments, " ");
int v0 = -1;
int v1 = -1;
int v2 = -1;
int vt0 = -1;
int vt1 = -1;
int vt2 = -1;
// parse vertex index 0, vertex texture index 0
t2 = new StringTokenizer(t.nextToken(), "/");
v0 = Integer.parseInt(t2.nextToken()) - 1;
if (t2.hasMoreTokens()) {
vt0 = Integer.parseInt(t2.nextToken()) - 1;
}
// parse vertex index 1, vertex texture index 1
t2 = new StringTokenizer(t.nextToken(), "/");
v1 = Integer.parseInt(t2.nextToken()) - 1;
if (t2.hasMoreTokens()) {
vt1 = Integer.parseInt(t2.nextToken()) - 1;
}
// parse vertex index 2, vertex texture index 2
t2 = new StringTokenizer(t.nextToken(), "/");
v2 = Integer.parseInt(t2.nextToken()) - 1;
if (t2.hasMoreTokens()) {
vt2 = Integer.parseInt(t2.nextToken()) - 1;
}
// check if triangulated
if (t.hasMoreTokens()) {
throw new ModelFileIOException("We only support triangulated meshes");
}
Integer mappedVertex = null;
// map v0 to group
mappedVertex = modelGroupVerticesMapping.get(v0);
if (mappedVertex == null) {
groupVertices.add(vertices.get(v0).clone());
v0 = groupVertices.size() - 1;
} else {
v0 = mappedVertex.intValue();
}
// map v1 to group
mappedVertex = modelGroupVerticesMapping.get(v1);
if (mappedVertex == null) {
groupVertices.add(vertices.get(v1).clone());
v1 = groupVertices.size() - 1;
} else {
v1 = mappedVertex.intValue();
}
// map v2 to group
mappedVertex = modelGroupVerticesMapping.get(v2);
if (mappedVertex == null) {
groupVertices.add(vertices.get(v2).clone());
v2 = groupVertices.size() - 1;
} else {
v2 = mappedVertex.intValue();
}
//
Integer mappedTextureCoordinate = null;
// map vt0 to group
mappedTextureCoordinate = modelGroupTextureCoordinatesMapping.get(vt0);
if (mappedTextureCoordinate == null) {
groupTextureCoordinates.add(textureCoordinates.get(vt0).clone());
vt0 = groupTextureCoordinates.size() - 1;
} else {
vt0 = mappedTextureCoordinate.intValue();
}
// map vt1 to group
mappedTextureCoordinate = modelGroupTextureCoordinatesMapping.get(vt1);
if (mappedTextureCoordinate == null) {
groupTextureCoordinates.add(textureCoordinates.get(vt1).clone());
vt1 = groupTextureCoordinates.size() - 1;
} else {
vt1 = mappedTextureCoordinate.intValue();
}
// map vt2 to group
mappedTextureCoordinate = modelGroupTextureCoordinatesMapping.get(vt2);
if (mappedTextureCoordinate == null) {
groupTextureCoordinates.add(textureCoordinates.get(vt2).clone());
vt2 = groupTextureCoordinates.size() - 1;
} else {
vt2 = mappedTextureCoordinate.intValue();
}
// compute vertex normal
Vector3[] faceVertexNormals = ModelHelper.computeNormals(new Vector3[] { groupVertices.get(v0), groupVertices.get(v1), groupVertices.get(v2) });
// store group normals
int n0 = groupNormals.size();
groupNormals.add(faceVertexNormals[0]);
int n1 = groupNormals.size();
groupNormals.add(faceVertexNormals[1]);
int n2 = groupNormals.size();
groupNormals.add(faceVertexNormals[2]);
// create face with vertex indices
// we only support triangulated faces
Face face = new Face(group, v0, v1, v2, n0, n1, n2);
if (vt0 != -1 && vt1 != -1 && vt2 != -1) {
// set optional texture coordinate index
face.setTextureCoordinateIndices(vt0, vt1, vt2);
}
groupFacesEntityFaces.add(face);
} else if (command.equals("g")) {
if (group != null) {
// current faces entity
if (groupFacesEntityFaces.isEmpty() == false) {
groupFacesEntity.setFaces(groupFacesEntityFaces);
groupFacesEntities.add(groupFacesEntity);
}
// group
group.setVertices(groupVertices);
group.setNormals(groupNormals);
group.setTextureCoordinates(groupTextureCoordinates);
group.setFacesEntities(groupFacesEntities);
group.determineFeatures();
}
StringTokenizer t = new StringTokenizer(arguments, " ");
String name = t.nextToken();
groupVertices = new ArrayList<Vector3>();
groupNormals = new ArrayList<Vector3>();
groupTextureCoordinates = new ArrayList<TextureCoordinate>();
groupFacesEntityFaces = new ArrayList<Face>();
group = new Group(model, null, name, name);
groupFacesEntity = new FacesEntity(group, name);
groupFacesEntities = new ArrayList<FacesEntity>();
modelGroupVerticesMapping = new HashMap<Integer, Integer>();
modelGroupTextureCoordinatesMapping = new HashMap<Integer, Integer>();
subGroups.put(name, group);
groups.put(name, group);
} else if (command.equals("usemtl")) {
if (group != null) {
// current faces entity
if (groupFacesEntityFaces.isEmpty() == false) {
groupFacesEntity.setFaces(groupFacesEntityFaces);
groupFacesEntities.add(groupFacesEntity);
}
// set up new one
groupFacesEntity = new FacesEntity(group, "#" + groupFacesEntities.size());
groupFacesEntityFaces = new ArrayList<Face>();
}
groupFacesEntity.setMaterial(materials.get(arguments));
} else {
// not supported
}
}
// finish last group
if (group != null) {
// current faces entity
if (groupFacesEntityFaces.isEmpty() == false) {
groupFacesEntity.setFaces(groupFacesEntityFaces);
groupFacesEntities.add(groupFacesEntity);
}
// group
group.setVertices(groupVertices);
group.setNormals(groupNormals);
group.setTextureCoordinates(groupTextureCoordinates);
group.setFacesEntities(groupFacesEntities);
group.determineFeatures();
}
} finally {
// close resouces
reader.close();
inputStream.close();
}
// prepare for indexed rendering
ModelHelper.prepareForIndexedRendering(model);
//
return model;
}
use of net.drewke.tdme.math.Vector3 in project tdme by andreasdr.
the class ModelHelper method computeNormals.
/**
* Computes face normals for given face vertices
* these normals will not be smooth
* @param face vertices
* @return face normals
*/
public static Vector3[] computeNormals(Vector3[] vertices) {
// face normal
Vector3 normal = computeNormal(vertices);
// compute vertex normal
Vector3[] normals = new Vector3[3];
for (int i = 0; i < vertices.length; i++) {
// TODO: vertex normals for smooth shading is currently broken
// but its only used for primitives models and wf obj parser
// vertices[i].clone().add(normal).normalize();
normals[i] = normal.clone();
}
//
return normals;
}
Aggregations