Max3DSParser.java 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. package min3d.parser;
  2. import java.io.BufferedInputStream;
  3. import java.io.IOException;
  4. import java.io.InputStream;
  5. import min3d.Min3d;
  6. import min3d.Shared;
  7. import min3d.core.Object3dContainer;
  8. import min3d.vos.Number3d;
  9. import min3d.vos.Uv;
  10. import android.content.res.Resources;
  11. import android.graphics.Bitmap;
  12. import android.util.Log;
  13. public class Max3DSParser extends AParser implements IParser {
  14. private final int IDENTIFIER_3DS = 0x4D4D;
  15. private final int MESH_BLOCK = 0x3D3D;
  16. private final int OBJECT_BLOCK = 0x4000;
  17. private final int TRIMESH = 0x4100;
  18. private final int TRI_MATERIAL = 0x4130;
  19. private final int VERTICES = 0x4110;
  20. private final int FACES = 0x4120;
  21. private final int TEXCOORD = 0x4140;
  22. private final int TEX_MAP = 0xA200;
  23. private final int TEX_NAME = 0xA000;
  24. private final int TEX_FILENAME = 0xA300;
  25. private final int MATERIAL = 0xAFFF;
  26. private int chunkID;
  27. private int chunkEndOffset;
  28. private boolean endReached;
  29. private String currentObjName;
  30. public Max3DSParser(Resources resources, String resourceID, boolean generateMipMap) {
  31. super(resources, resourceID, generateMipMap);
  32. }
  33. @Override
  34. public void parse() {
  35. InputStream fileIn = resources.openRawResource(resources.getIdentifier(
  36. resourceID, null, null));
  37. BufferedInputStream stream = new BufferedInputStream(fileIn);
  38. Log.d(Min3d.TAG, "Start parsing object");
  39. co = new ParseObjectData();
  40. parseObjects.add(co);
  41. try {
  42. readHeader(stream);
  43. if(chunkID != IDENTIFIER_3DS)
  44. {
  45. Log.d(Min3d.TAG, "Not a valid .3DS file!");
  46. return;
  47. }
  48. else
  49. {
  50. Log.d(Min3d.TAG, "Found a valid .3DS file");
  51. }
  52. while(!endReached)
  53. {
  54. readChunk(stream);
  55. }
  56. } catch (IOException e) {
  57. e.printStackTrace();
  58. }
  59. Log.d(Min3d.TAG, "End parsing object");
  60. }
  61. private void readHeader(InputStream stream) throws IOException {
  62. chunkID = readShort(stream);
  63. chunkEndOffset = readInt(stream);
  64. endReached = chunkID < 0;
  65. }
  66. private void readChunk(InputStream stream) throws IOException {
  67. readHeader(stream);
  68. switch (chunkID) {
  69. case MESH_BLOCK:
  70. break;
  71. case OBJECT_BLOCK:
  72. currentObjName = readString(stream);
  73. Log.d(Min3d.TAG, "Parsing object " + currentObjName);
  74. break;
  75. case TRIMESH:
  76. if(firstObject)
  77. {
  78. co.name = currentObjName;
  79. firstObject = false;
  80. }
  81. else
  82. {
  83. co = new ParseObjectData();
  84. co.name = currentObjName;
  85. parseObjects.add(co);
  86. }
  87. break;
  88. case VERTICES:
  89. readVertices(stream);
  90. break;
  91. case FACES:
  92. readFaces(stream);
  93. break;
  94. case TEXCOORD:
  95. readTexCoords(stream);
  96. break;
  97. case TEX_NAME:
  98. currentMaterialKey = readString(stream);
  99. break;
  100. case TEX_FILENAME:
  101. String fileName = readString(stream);
  102. StringBuffer texture = new StringBuffer(packageID);
  103. texture.append(":drawable/");
  104. StringBuffer textureName = new StringBuffer(fileName.toLowerCase());
  105. int dotIndex = textureName.lastIndexOf(".");
  106. if (dotIndex > -1)
  107. texture.append(textureName.substring(0, dotIndex));
  108. else
  109. texture.append(textureName);
  110. textureAtlas.addBitmapAsset(new BitmapAsset(currentMaterialKey, texture.toString()));
  111. break;
  112. case TRI_MATERIAL:
  113. String materialName = readString(stream);
  114. int numFaces = readShort(stream);
  115. for(int i=0; i<numFaces; i++)
  116. {
  117. int faceIndex = readShort(stream);
  118. co.faces.get(faceIndex).materialKey = materialName;
  119. }
  120. break;
  121. case MATERIAL:
  122. break;
  123. case TEX_MAP:
  124. break;
  125. default:
  126. skipRead(stream);
  127. }
  128. }
  129. private void skipRead(InputStream stream) throws IOException
  130. {
  131. for(int i=0; (i<chunkEndOffset - 6) && !endReached; i++)
  132. {
  133. endReached = stream.read() < 0;
  134. }
  135. }
  136. private void readVertices(InputStream buffer) throws IOException {
  137. float x, y, z, tmpy;
  138. int numVertices = readShort(buffer);
  139. for (int i = 0; i < numVertices; i++) {
  140. x = readFloat(buffer);
  141. y = readFloat(buffer);
  142. z = readFloat(buffer);
  143. tmpy = y;
  144. y = z;
  145. z = -tmpy;
  146. co.vertices.add(new Number3d(x, y, z));
  147. }
  148. }
  149. private void readFaces(InputStream buffer) throws IOException {
  150. int triangles = readShort(buffer);
  151. for (int i = 0; i < triangles; i++) {
  152. int[] vertexIDs = new int[3];
  153. vertexIDs[0] = readShort(buffer);
  154. vertexIDs[1] = readShort(buffer);
  155. vertexIDs[2] = readShort(buffer);
  156. readShort(buffer);
  157. ParseObjectFace face = new ParseObjectFace();
  158. face.v = vertexIDs;
  159. face.uv = vertexIDs;
  160. face.faceLength = 3;
  161. face.hasuv = true;
  162. co.numFaces++;
  163. co.faces.add(face);
  164. co.calculateFaceNormal(face);
  165. }
  166. }
  167. private void readTexCoords(InputStream buffer) throws IOException {
  168. int numVertices = readShort(buffer);
  169. for (int i = 0; i < numVertices; i++) {
  170. Uv uv = new Uv();
  171. uv.u = readFloat(buffer);
  172. uv.v = readFloat(buffer) * -1f;
  173. co.texCoords.add(uv);
  174. }
  175. }
  176. public Object3dContainer getParsedObject() {
  177. Log.d(Min3d.TAG, "Start object creation");
  178. Object3dContainer obj = new Object3dContainer(0, 0);
  179. int numObjects = parseObjects.size();
  180. Bitmap texture = null;
  181. if(textureAtlas.hasBitmaps())
  182. {
  183. textureAtlas.generate();
  184. texture = textureAtlas.getBitmap();
  185. Shared.textureManager().addTextureId(texture, textureAtlas.getId(), generateMipMap);
  186. }
  187. for (int i = 0; i < numObjects; i++) {
  188. ParseObjectData o = parseObjects.get(i);
  189. Log.d(Min3d.TAG, "Creating object " + o.name);
  190. obj.addChild(o.getParsedObject(materialMap, textureAtlas));
  191. }
  192. if(textureAtlas.hasBitmaps())
  193. {
  194. if(texture != null) texture.recycle();
  195. }
  196. Log.d(Min3d.TAG, "Object creation finished");
  197. super.cleanup();
  198. return obj;
  199. }
  200. }