/******************************************************************************* * Copyright 2012 Daniel Heinrich. * * 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.badlogic.gdx.graphics.g3d.loaders.openctm; import java.util.ArrayList; import java.util.List; import darwin.jopenctm.data.AttributeData; import darwin.jopenctm.io.CtmFileReader; import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.graphics.*; import com.badlogic.gdx.graphics.VertexAttributes.Usage; import com.badlogic.gdx.graphics.g3d.ModelLoaderHints; import com.badlogic.gdx.graphics.g3d.loaders.ModelLoader; import com.badlogic.gdx.graphics.g3d.model.Model; import com.badlogic.gdx.graphics.g3d.model.still.StillModel; import com.badlogic.gdx.graphics.g3d.model.still.StillSubMesh; import com.badlogic.gdx.graphics.glutils.ShaderProgram; import com.badlogic.gdx.utils.GdxRuntimeException; import static darwin.jopenctm.data.Mesh.*; /** * * @author Daniel Heinrich <dannynullzwo@gmail.com> */ public class CtmModelLoader implements ModelLoader { @Override public Model load(FileHandle file, ModelLoaderHints hints) { CtmFileReader reader = new CtmFileReader(file.read()); try { darwin.jopenctm.data.Mesh ctmMesh = reader.decode(); Mesh mesh = convert(ctmMesh); StillSubMesh ssm = new StillSubMesh(reader.getFileComment(), mesh, GL10.GL_TRIANGLES); StillModel model = new StillModel(new StillSubMesh[]{ssm}); return model; } catch (Throwable ex) { throw new GdxRuntimeException("An error occured while loading model: " + file.name(), ex); } } private Mesh convert(darwin.jopenctm.data.Mesh ctmMesh) { if (ctmMesh.getVertexCount() > Short.MAX_VALUE) { throw new GdxRuntimeException("The indices exceed the range of SHORT!"); } List<VertexAttribute> vas = new ArrayList<VertexAttribute>(); VertexAttribute position = new VertexAttribute(Usage.Position, CTM_POSITION_ELEMENT_COUNT, ShaderProgram.POSITION_ATTRIBUTE); vas.add(position); VertexAttribute normal = null; if (ctmMesh.hasNormals()) { normal = new VertexAttribute(Usage.Normal, CTM_NORMAL_ELEMENT_COUNT, ShaderProgram.NORMAL_ATTRIBUTE); vas.add(normal); } VertexAttribute[] uvs = new VertexAttribute[ctmMesh.getUVCount()]; if (ctmMesh.getUVCount() > 0) { uvs[0] = new VertexAttribute(Usage.TextureCoordinates, CTM_UV_ELEMENT_COUNT, ShaderProgram.TEXCOORD_ATTRIBUTE); vas.add(uvs[0]); if (ctmMesh.getUVCount() > 1) { for (int i = 1; i < ctmMesh.getUVCount(); ++i) { AttributeData ad = ctmMesh.texcoordinates[i]; uvs[i] = new VertexAttribute(Usage.TextureCoordinates, CTM_UV_ELEMENT_COUNT, ad.name); vas.add(uvs[i]); } } } VertexAttribute[] others = new VertexAttribute[ctmMesh.getAttrCount()]; for (int i = 0; i < ctmMesh.getAttrCount(); ++i) { others[i] = new VertexAttribute(Usage.Generic, CTM_ATTR_ELEMENT_COUNT, ctmMesh.attributs[i].name); vas.add(others[i]); } Mesh m = new Mesh(true, ctmMesh.getVertexCount(), ctmMesh.getTriangleCount() * 3, vas.toArray(new VertexAttribute[0])); m.setIndices(convertIndices(ctmMesh.indices)); int vsize = m.getVertexSize() / 4; float[] data = new float[vsize * ctmMesh.getVertexCount()]; for (int i = 0; i < ctmMesh.getVertexCount(); i++) { //position data System.arraycopy(ctmMesh.vertices, i * CTM_POSITION_ELEMENT_COUNT, data, i * vsize, CTM_POSITION_ELEMENT_COUNT); //normal if (normal != null) { System.arraycopy(ctmMesh.normals, i * CTM_NORMAL_ELEMENT_COUNT, data, i * vsize + normal.offset / 4, CTM_NORMAL_ELEMENT_COUNT); } //uvs for(VertexAttribute va: uvs) { AttributeData ad=ctmMesh.texcoordinates[i]; System.arraycopy(ad.values, i * CTM_UV_ELEMENT_COUNT, data, i * vsize + va.offset / 4, CTM_UV_ELEMENT_COUNT); } //other for(VertexAttribute va: others) { AttributeData ad=ctmMesh.attributs[i]; System.arraycopy(ad.values, i * CTM_ATTR_ELEMENT_COUNT, data, i * vsize + va.offset / 4, CTM_ATTR_ELEMENT_COUNT); } } m.setVertices(data); return m; } private static short[] convertIndices(int[] ind) { short[] r = new short[ind.length]; for (int i = 0; i < r.length; i++) { r[i] = (short) ind[i]; } return r; } }