/* * JaamSim Discrete Event Simulation * Copyright (C) 2013 Ausenco Engineering Canada Inc. * Copyright (C) 2015 JaamSim Software Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.jaamsim.MeshFiles; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.URI; import java.nio.charset.Charset; import com.jaamsim.input.Input; import com.jaamsim.math.Vec2d; import com.jaamsim.math.Vec3d; import com.jaamsim.ui.LogBox; public class MeshWriter { private OutputStreamWriter out; private int indentLength = 0; boolean isGood = false; URI baseDirURI; public MeshWriter(String filename) { try { OutputStream os = new FileOutputStream(filename); out = new OutputStreamWriter(os, Charset.forName("UTF-8")); baseDirURI = new File(filename).toURI().resolve("."); } catch (Exception ex) { LogBox.renderLogException(ex); return; } isGood = true; } private void indent() throws IOException { for (int i = 0; i < indentLength; ++i) { out.write(Input.SEPARATOR); } } private void startTag(String tag) throws IOException { indent(); indentLength++; out.write(tag); out.write("\n"); } private void endTag(String tag) throws IOException { indentLength--; indent(); out.write(tag); out.write("\n"); } public boolean write(MeshData data) { try { if (!isGood) { return false; } startTag("<MeshObject version='0.1'>"); startTag("<Geometries>"); int meshNumber = 0; for (MeshData.SubMeshData subMesh : data.getSubMeshData()) { writeSubMesh(subMesh, meshNumber++); } endTag("</Geometries>"); startTag("<Materials>"); int matNumber = 0; for (MeshData.Material mat : data.getMaterials()) { writeMaterial(mat, matNumber++); } endTag("</Materials>"); startTag("<MeshInstances>"); for (MeshData.StaticMeshInstance inst : data.getStaticMeshInstances()) { writeMeshInstance(inst); } endTag("</MeshInstances>"); endTag("</MeshObject>"); out.close(); } catch (IOException ex) { LogBox.renderLogException(ex); return false; } return true; } private void writeSubMesh(MeshData.SubMeshData subMesh, int meshNumber) throws IOException { startTag(String.format("<Geometry vertices='%d' ID='Mesh%d'>", subMesh.verts.size(), meshNumber)); startTag("<Positions dims='3'>"); indent(); for (Vec3d v : subMesh.verts) { out.write(String.format("%f %f %f ", v.x, v.y, v.z)); } out.write("\n"); endTag("</Positions>"); startTag("<Normals dims='3'>"); indent(); for (Vec3d n : subMesh.normals) { out.write(String.format("%f %f %f ", n.x, n.y, n.z)); } out.write("\n"); endTag("</Normals>"); if (subMesh.texCoords != null && subMesh.texCoords.size() != 0) { // This mesh has tex coordinates startTag("<TexCoords index='0' dims='2'>"); indent(); for (Vec2d t : subMesh.texCoords) { out.write(String.format("%f %f ", t.x, t.y)); } out.write("\n"); endTag("</TexCoords>"); } // Output the faces list startTag(String.format("<Faces type='Triangles' count='%d'>", subMesh.indices.length/3)); indent(); for (int i : subMesh.indices) { out.write(String.format("%d ", i)); } out.write("\n"); endTag("</Faces>"); endTag("</Geometry>"); } private void writeMaterial(MeshData.Material mat, int meshNumber) throws IOException { startTag(String.format("<Material ID='Mat%d'>", meshNumber)); startTag("<Diffuse>"); if (mat.colorTex == null) { // Flat color startTag("<Color>"); indent(); out.write(String.format("%f %f %f %f\n", mat.diffuseColor.r, mat.diffuseColor.g, mat.diffuseColor.b, mat.diffuseColor.a)); endTag("</Color>"); } else { startTag("<Texture coordIndex='0'>"); indent(); URI tex = baseDirURI.relativize(mat.colorTex); out.write(tex.toString()); out.write("\n"); endTag("</Texture>"); } endTag("</Diffuse>"); endTag("</Material>"); } private void writeMeshInstance(MeshData.StaticMeshInstance inst) throws IOException { startTag(String.format("<MeshInstance geoIndex='%d' matIndex='%d'>", inst.subMeshIndex, inst.materialIndex)); startTag("<Matrix>"); double[] cmData = inst.transform.toCMDataArray(); indent(); for (double d : cmData) { out.write(String.format("%f ", d)); } out.write("\n"); endTag("</Matrix>"); endTag("</MeshInstance>"); } }