Advertisement
ginkage

Load3DS

Aug 8th, 2012
896
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import java.io.BufferedInputStream;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.FileNotFoundException;
  5. import java.io.IOException;
  6. import java.util.ArrayList;
  7.  
  8. import android.opengl.Matrix;
  9. import android.os.Environment;
  10. import android.util.Log;
  11.  
  12. public class Load3DS {
  13.     private final int CHUNK_MAIN     = 0x4D4D;
  14.     private final int CHUNK_OBJMESH  = 0x3D3D;
  15.     private final int CHUNK_OBJBLOCK = 0x4000;
  16.     private final int CHUNK_TRIMESH  = 0x4100;
  17.     private final int CHUNK_VERTLIST = 0x4110;
  18.     private final int CHUNK_FACELIST = 0x4120;
  19.     private final int CHUNK_FACEMAT  = 0x4130;
  20.     private final int CHUNK_MAPLIST  = 0x4140;
  21.     private final int CHUNK_SMOOTHG  = 0x4150;
  22.     private final int CHUNK_TRMATRIX = 0x4160;
  23.     private final int CHUNK_LIGHT    = 0x4600;
  24.     private final int CHUNK_SPOTL    = 0x4610;
  25.     private final int CHUNK_ONOFF    = 0x4620;
  26.     private final int CHUNK_CAMERA   = 0x4700;
  27.     private final int CHUNK_RGBC     = 0x0010;
  28.     private final int CHUNK_RGB24    = 0x0011;
  29.     private final int CHUNK_SHORT    = 0x0030;
  30.     private final int CHUNK_BACKCOL  = 0x1200;
  31.     private final int CHUNK_AMB      = 0x2100;
  32.     private final int CHUNK_MATERIAL = 0xAFFF;
  33.     private final int CHUNK_MATNAME  = 0xA000;
  34.     private final int CHUNK_AMBIENT  = 0xA010;
  35.     private final int CHUNK_DIFFUSE  = 0xA020;
  36.     private final int CHUNK_SPECULAR = 0xA030;
  37.     private final int CHUNK_SHININES = 0xA040;
  38.     private final int CHUNK_SHINSTRN = 0xA041;
  39.     private final int CHUNK_TRANSP   = 0xA050;
  40.     private final int CHUNK_SELFILL  = 0xA084;
  41.     private final int CHUNK_MTLTYPE  = 0xA100;
  42.     private final int CHUNK_TEXTURE  = 0xA200;
  43.     private final int CHUNK_REFLMAP  = 0xA220;
  44.     private final int CHUNK_BUMPMAP  = 0xA230;
  45.     private final int CHUNK_MAPFILE  = 0xA300;
  46.     private final int CHUNK_MAPPARAM = 0xA351;
  47.     private final int CHUNK_KEYFRAMER = 0xB000;
  48.     private final int CHUNK_TRACKINFO = 0xB002;
  49.     private final int CHUNK_SPOTINFO  = 0xB007;
  50.     private final int CHUNK_FRAMES    = 0xB008;
  51.     private final int CHUNK_OBJNAME   = 0xB010;
  52.     private final int CHUNK_PIVOT     = 0xB013;
  53.     private final int CHUNK_TRACKPOS  = 0xB020;
  54.     private final int CHUNK_TRACKROT  = 0xB021;
  55.     private final int CHUNK_TRACKSCL  = 0xB022;
  56.     private final int CHUNK_HIERARCHY = 0xB030;
  57.  
  58.     private BufferedInputStream file;
  59.     private byte[] bytes = new byte[8];
  60.     private long filePos;
  61.  
  62.     public Scene3D Load(String fileName)
  63.     {
  64.         file = null;
  65.         Scene3D scene = null;
  66.         File dir = new File(Environment.getExternalStorageDirectory().getAbsolutePath());
  67.         File fil = new File(dir.getAbsolutePath() + File.separator + fileName);
  68.         if (!fil.exists()) return scene;
  69.  
  70.         try {
  71.             filePos = 0;
  72.             file = new BufferedInputStream(new FileInputStream(fil));
  73.             scene = ProcessFile(fil.length());
  74.         } catch (FileNotFoundException e) {
  75.             e.printStackTrace();
  76.         } catch (IOException e) {
  77.             e.printStackTrace();
  78.         }
  79.  
  80.         try {
  81.             if (file != null)
  82.                 file.close();
  83.         } catch (IOException e) {
  84.             e.printStackTrace();
  85.         }
  86.  
  87.         return scene;
  88.     }
  89.  
  90.     private void Skip(long count) throws IOException
  91.     {
  92.         file.skip(count);
  93.         filePos += count;
  94.     }
  95.  
  96.     private void Seek(long end) throws IOException
  97.     {
  98.         if (filePos < end) {
  99.             Skip(end - filePos);
  100.             filePos = end;
  101.         }
  102.     }
  103.  
  104.     private byte ReadByte() throws IOException
  105.     {
  106.         file.read(bytes, 0, 1);
  107.         filePos++;
  108.         return bytes[0];
  109.     }
  110.  
  111.     private int ReadUnsignedByte() throws IOException
  112.     {
  113.         file.read(bytes, 0, 1);
  114.         filePos++;
  115.         return (bytes[0]&0xff);
  116.     }
  117.  
  118.     private int ReadUnsignedShort() throws IOException
  119.     {
  120.         file.read(bytes, 0, 2);
  121.         filePos += 2;
  122.         return ((bytes[1]&0xff) << 8 | (bytes[0]&0xff));
  123.     }
  124.  
  125.     private int ReadInt() throws IOException
  126.     {
  127.         file.read(bytes, 0, 4);
  128.         filePos += 4;
  129.         return (bytes[3]) << 24 | (bytes[2]&0xff) << 16 | (bytes[1]&0xff) <<  8 | (bytes[0]&0xff);
  130.     }
  131.  
  132.     private float ReadFloat() throws IOException
  133.     {
  134.         return Float.intBitsToFloat(ReadInt());
  135.     }
  136.  
  137.     private Scene3D ProcessFile(long fileLen) throws IOException
  138.     {
  139.         Scene3D scene = null;
  140.  
  141.         while (filePos < fileLen) {
  142.             int chunkID = ReadUnsignedShort();
  143.             int chunkLen = ReadInt() - 6;
  144.  
  145.             switch (chunkID) {
  146.             case CHUNK_MAIN:
  147.                 if (scene == null)
  148.                     scene = ChunkMain(chunkLen);
  149.                 else
  150.                     Skip(chunkLen);
  151.                 break;
  152.  
  153.             default:
  154.                 Skip(chunkLen);
  155.             }
  156.         }
  157.  
  158.         return scene;
  159.     }
  160.  
  161.     private Scene3D ChunkMain(int len) throws IOException
  162.     {
  163.         Scene3D scene = new Scene3D();
  164.         scene.materials = new ArrayList<Material3D>();
  165.         scene.objects = new ArrayList<Object3D>();
  166.         scene.lights = new ArrayList<Light3D>();
  167.         scene.animations = new ArrayList<Animation>();
  168.  
  169.         long end = filePos + len;
  170.         while (filePos < end) {
  171.             int chunkID = ReadUnsignedShort();
  172.             int chunkLen = ReadInt() - 6;
  173.  
  174.             switch (chunkID) {
  175.             case CHUNK_OBJMESH:
  176.                 Chunk3DEditor(scene, chunkLen);
  177.                 break;
  178.  
  179.             case CHUNK_KEYFRAMER:
  180.                 ChunkKeyframer(scene, chunkLen);
  181.                 break;
  182.  
  183.             case CHUNK_BACKCOL:
  184.                 scene.background = new float[4];
  185.                 ChunkColor(chunkLen, scene.background);
  186.                 break;
  187.  
  188.             case CHUNK_AMB:
  189.                 scene.ambient = new float[4];
  190.                 ChunkColor(chunkLen, scene.ambient);
  191.                 break;
  192.  
  193.             default:
  194.                 Skip(chunkLen);
  195.             }
  196.         }
  197.         Seek(end);
  198.  
  199.         scene.Compute(0);
  200.  
  201.         return scene;
  202.     }
  203.  
  204.     private void Chunk3DEditor(Scene3D scene, int len) throws IOException
  205.     {
  206.         long end = filePos + len;
  207.         while (filePos < end) {
  208.             int chunkID = ReadUnsignedShort();
  209.             int chunkLen = ReadInt() - 6;
  210.  
  211.             switch (chunkID) {
  212.             case CHUNK_OBJBLOCK:
  213.                 ChunkObject(scene, chunkLen);
  214.                 break;
  215.  
  216.             case CHUNK_MATERIAL:
  217.                 Material3D mat = ChunkMaterial(scene, chunkLen);
  218.                 if (mat != null)
  219.                     scene.materials.add(mat);
  220.                 break;
  221.  
  222.             default:
  223.                 Skip(chunkLen);
  224.             }
  225.         }
  226.         Seek(end);
  227.     }
  228.  
  229.     private void ChunkObject(Scene3D scene, int len) throws IOException
  230.     {
  231.         long end = filePos + len;
  232.  
  233.         if (len == 0) return;
  234.         String name = ChunkName(0);
  235.  
  236.         while (filePos < end) {
  237.             int chunkID = ReadUnsignedShort();
  238.             int chunkLen = ReadInt() - 6;
  239.  
  240.             switch (chunkID) {
  241.             case CHUNK_TRIMESH:
  242.                 Object3D obj = ChunkTrimesh(chunkLen, name, scene);
  243.                 if (obj != null)
  244.                     scene.objects.add(obj);
  245.                 break;
  246.  
  247.             case CHUNK_LIGHT:
  248.                 Light3D light = ChunkLight(chunkLen, name);
  249.                 if (light != null)
  250.                     scene.lights.add(light);
  251.                 break;
  252.  
  253.             case CHUNK_CAMERA:
  254.             default:
  255.                 Skip(chunkLen);
  256.             }
  257.         }
  258.         Seek(end);
  259.     }
  260.  
  261.     private Object3D ChunkTrimesh(int len, String name, Scene3D scene) throws IOException
  262.     {
  263.         long end = filePos + len;
  264.  
  265.         Object3D obj = new Object3D();
  266.         obj.name = name;
  267.         obj.faceMats = new ArrayList<FaceMat>();
  268.         obj.indCount = 0;
  269.  
  270.         int i, k, num;
  271.  
  272.         while (filePos < end) {
  273.             int chunkID = ReadUnsignedShort();
  274.             int chunkLen = ReadInt() - 6;
  275.  
  276.             switch (chunkID) {
  277.             case CHUNK_FACELIST:
  278.                 ChunkFaceList(chunkLen, obj, scene);
  279.                 break;
  280.  
  281.             case CHUNK_MAPLIST:
  282.                 num = ReadUnsignedShort();
  283.                 for (i = 0, k = 6; i < num; i++, k += 8) {
  284.                     obj.vertexBuffer[k + 0] = ReadFloat();
  285.                     obj.vertexBuffer[k + 1] = 1 - ReadFloat();
  286.                 }
  287.                 break;
  288.  
  289.             case CHUNK_VERTLIST:
  290.                 num = ReadUnsignedShort();
  291.                 obj.vertCount = num;
  292.                 obj.vertexBuffer = new float[8*num];
  293.                 for (i = 0, k = 0; i < num; i++, k += 8) {
  294.                     ChunkVector(obj.vertexBuffer, k);
  295.                     obj.vertexBuffer[k + 3] = 0;
  296.                     obj.vertexBuffer[k + 4] = 0;
  297.                     obj.vertexBuffer[k + 5] = 0;
  298.                     obj.vertexBuffer[k + 6] = 0;
  299.                     obj.vertexBuffer[k + 7] = 0;
  300.                 }
  301.                 break;
  302.  
  303.             case CHUNK_TRMATRIX:
  304.                 float[] localCoord = new float[16];
  305.                 ChunkVector(localCoord, 4*0);
  306.                 ChunkVector(localCoord, 4*2);
  307.                 ChunkVector(localCoord, 4*1);
  308.                 ChunkVector(localCoord, 4*3);
  309.                 localCoord[3] = localCoord[7] = localCoord[11] = 0;
  310.                 localCoord[15] = 1;
  311.  
  312.                 obj.trMatrix = new float[16];
  313.                 Matrix.invertM(obj.trMatrix, 0, localCoord, 0);
  314.                 break;
  315.  
  316.             default:
  317.                 Skip(chunkLen);
  318.             }
  319.         }
  320.         Seek(end);
  321.  
  322.         return obj;
  323.     }
  324.  
  325.     private static void CrossProduct(float[] res, float[] v1, float[] v2)
  326.     {
  327.         res[0] = v1[1]*v2[2] - v1[2]*v2[1];
  328.         res[1] = v1[2]*v2[0] - v1[0]*v2[2];
  329.         res[2] = v1[0]*v2[1] - v1[1]*v2[0];
  330.     }
  331.  
  332.     private static float DotSquare(float[] v, int offset)
  333.     {
  334.         return v[offset + 0]*v[offset + 0] + v[offset + 1]*v[offset + 1] + v[offset + 2]*v[offset + 2];
  335.     }
  336.  
  337.     private static void VecSubstract(float[] res, float[] v, int offset1, int offset2)
  338.     {
  339.         res[0] = v[offset1 + 0] - v[offset2 + 0];
  340.         res[1] = v[offset1 + 1] - v[offset2 + 1];
  341.         res[2] = v[offset1 + 2] - v[offset2 + 2];
  342.     }
  343.  
  344.     private static void VecAdd(float[] v, int offset, float[] a, int off)
  345.     {
  346.         v[offset + 0] += a[off + 0];
  347.         v[offset + 1] += a[off + 1];
  348.         v[offset + 2] += a[off + 2];
  349.     }
  350.  
  351.     private void VecNormalize(float[] v, int offset)
  352.     {
  353.         double nlen = 1 / Math.sqrt(DotSquare(v, offset));
  354.         v[offset + 0] *= nlen;
  355.         v[offset + 1] *= nlen;
  356.         v[offset + 2] *= nlen;
  357.     }
  358.  
  359.     private void ChunkFaceList(int len, Object3D obj, Scene3D scene) throws IOException
  360.     {
  361.         long end = filePos + len;
  362.  
  363.         int i, j, k, l, m, t, num = ReadUnsignedShort(), unused = num, idx;
  364.  
  365.         int faceCount = num;
  366.         int[] faceBuffer = new int[3*faceCount];
  367.         boolean[] faceUsed = new boolean[faceCount];
  368.         float[] v = new float[3];
  369.         float[] v1 = new float[3];
  370.         float[] v2 = new float[3];
  371.  
  372.         float[] vgNorm = new float[3*3*faceCount]; // per-vertex normal for each face
  373.         int[] vertGroup = new int[3*faceCount]; // per-vertex group for each face
  374.         boolean[] vgUsed = new boolean[3*faceCount]; // per-vertex "group used" bit for each face
  375.         int[] vgNum = new int[obj.vertCount + 1]; // per-vertex face count, and then offset
  376.         int[] faceGroup = new int[faceCount]; // per-face smoothing group
  377.  
  378.         int[] vgUniqs = new int[obj.vertCount + 1]; // per-vertex unique groups count
  379.         int[] vertUGroup = new int[3*faceCount]; // per-vertex unique groups list for each face
  380.  
  381.         for (i = 0; i <= obj.vertCount; i++)
  382.             vgNum[i] = vgUniqs[i] = 0;
  383.  
  384.         for (i = 0, idx = 0; i < faceCount; i++, idx += 3) {
  385.             j = ReadUnsignedShort();
  386.             k = ReadUnsignedShort();
  387.             l = ReadUnsignedShort();
  388.             Skip(2);
  389.  
  390.             faceUsed[i] = false;
  391.             faceBuffer[idx + 0] = j;
  392.             faceBuffer[idx + 2] = k;
  393.             faceBuffer[idx + 1] = l;
  394.  
  395.             // initialize smoothing groups data
  396.             faceGroup[i] = 0;
  397.  
  398.             for (t = 0; t < 9; t++)
  399.                 vgNorm[i * 9 + t] = 0;
  400.  
  401.             for (t = 0; t < 3; t++) {
  402.                 vertGroup[idx + t] = 0;
  403.                 vertUGroup[idx + t] = 0;
  404.                 vgUsed[idx + t] = false;
  405.             }
  406.  
  407.             vgNum[j]++;
  408.             vgNum[k]++;
  409.             vgNum[l]++;
  410.         }
  411.  
  412.         int a, sum = 0;
  413.         for (i = 0; i < obj.vertCount; i++) {
  414.             a = vgNum[i];
  415.             vgNum[i] = sum;
  416.             sum += a;
  417.         }
  418.         vgNum[obj.vertCount] = sum; // now we can store all the faces and their normals and groups per-vertex
  419.  
  420.         for (i = 0, idx = 0; i < faceCount; i++, idx += 3) {
  421.             j = faceBuffer[idx + 0];
  422.             k = faceBuffer[idx + 2];
  423.             l = faceBuffer[idx + 1];
  424.  
  425.             VecSubstract(v1, obj.vertexBuffer, l*8, j*8);
  426.             VecSubstract(v2, obj.vertexBuffer, k*8, j*8);
  427.             CrossProduct(v, v1, v2);
  428.  
  429.             VecAdd(vgNorm, vgNum[j]*3, v, 0);
  430.             VecAdd(vgNorm, vgNum[k]*3, v, 0);
  431.             VecAdd(vgNorm, vgNum[l]*3, v, 0);
  432.            
  433.             vgNum[j]++;
  434.             vgNum[k]++;
  435.             vgNum[l]++;
  436.         }
  437.  
  438.         for (i = obj.vertCount - 1; i > 0; i--) // offsets were shifted, so shift them back
  439.             vgNum[i] = vgNum[i - 1];
  440.         vgNum[0] = 0;
  441.  
  442.         boolean gotSmoothGroups = false;
  443.  
  444.         while (filePos < end) {
  445.             int chunkID = ReadUnsignedShort();
  446.             int chunkLen = ReadInt() - 6;
  447.  
  448.             switch (chunkID) {
  449.             case CHUNK_FACEMAT:
  450.                 FaceMat mat = new FaceMat();
  451.                 String name = ChunkName(0);
  452.                 mat.material = scene.FindMaterial(name);
  453.                 num = ReadUnsignedShort();
  454.                 mat.indCount = num;
  455.                 mat.indexBuffer = new short[3*num];
  456.                 mat.bufOffset = obj.indCount;
  457.                 obj.indCount += 3*num;
  458.                 k = 0;
  459.                 for (i = 0; i < num; i++) {
  460.                     j = ReadUnsignedShort();
  461.                     if (!faceUsed[j]) {
  462.                         faceUsed[j] = true;
  463.                         unused--;
  464.                     }
  465.                     for (t = 0; t < 3; t++)
  466.                         mat.indexBuffer[k++] = (short) j;
  467.                 }
  468.                 obj.faceMats.add(mat);
  469.                 break;
  470.  
  471.             case CHUNK_SMOOTHG:
  472.                 for (i = 0, idx = 0; i < faceCount; i++, idx += 3) {
  473.                     faceGroup[i] = ReadInt();
  474.                    
  475.                     for (t = 0; t < 3; t++) {
  476.                         j = faceBuffer[idx + t];
  477.                         vertGroup[vgNum[j]] = faceGroup[i];
  478.                         vgNum[j]++;
  479.                     }
  480.                 }
  481.                 for (i = obj.vertCount - 1; i > 0; i--)
  482.                     vgNum[i] = vgNum[i - 1];
  483.                 vgNum[0] = 0;
  484.                 gotSmoothGroups = true;
  485.                 break;
  486.  
  487.             default:
  488.                 Skip(chunkLen);
  489.             }
  490.         }
  491.         Seek(end);
  492.  
  493.         int newVertCount = 0, g;
  494.  
  495.         if (gotSmoothGroups) {
  496.             for (i = 0; i < obj.vertCount; i++) {
  497.                 for (m = vgNum[i]; m < vgNum[i + 1]; m++) { // for every normal and face of this vertex
  498.                     if (!vgUsed[m]) {
  499.                         // vertGroup[m] is a new group...
  500.                         vertUGroup[vgNum[i] + vgUniqs[i]] = vertGroup[m];
  501.                         vgUniqs[i]++;
  502.                         newVertCount++;
  503.                     }
  504.    
  505.                     for (t = m; t < vgNum[i + 1]; t++) // mark all equal groups (including this one) as duplicates
  506.                         if (vertGroup[t] == vertGroup[m])
  507.                             vgUsed[t] = true;
  508.                 }
  509.             }
  510.  
  511.             if (newVertCount == obj.vertCount)
  512.                 gotSmoothGroups = false;
  513.         }
  514.  
  515.         if (gotSmoothGroups) {
  516.             // reindex all vertices, build new normals
  517.             int newIndex = 0;
  518.             int[] vertIndex = new int[faceCount*3]; // new vertex indices
  519.             float[] newVertexBuffer = new float[newVertCount*8];
  520.  
  521.             for (i = 0, idx = 0; i < faceCount; i++, idx += 3)
  522.                 for (t = 0; t < 3; t++)
  523.                     vertIndex[idx + t] = 0;
  524.  
  525.             idx = 3;
  526.             for (i = 0; i < obj.vertCount; i++) {
  527.                 for (t = 0; t < vgUniqs[i]; t++) { // for every unique normal and face of this vertex
  528.                     for (m = 0; m < 8; m++)
  529.                         newVertexBuffer[newIndex*8 + m] = obj.vertexBuffer[i*8 + m]; // duplicate all vertex data (including zero normals)
  530.  
  531.                     g = vertUGroup[vgNum[i] + t]; // unique group mask for this vertex
  532.                     for (m = vgNum[i]; m < vgNum[i + 1]; m++) // for every NON-unique normal and face of this vertex
  533.                         if ((vertGroup[m] & g) != 0 || vertGroup[m] == g) // also works for zero group
  534.                             VecAdd(newVertexBuffer, idx, vgNorm, m*3); // add normal to vertex
  535.    
  536.                     vertIndex[vgNum[i] + t] = newIndex;
  537.                     newIndex++;
  538.                     idx += 8;
  539.                 }
  540.             }
  541.  
  542.             int fg, vi;
  543.             for (i = 0, idx = 0; i < faceCount; i++, idx += 3) {
  544.                 fg = faceGroup[i];
  545.                 for (m = 0; m < 3; m++) {
  546.                     vi = faceBuffer[idx + m]; // face vertex
  547.                     for (t = 0; t < vgUniqs[vi]; t++) // for every unique group of this vertex
  548.                         if (fg == vertUGroup[vgNum[vi] + t]) { // found the right one
  549.                             faceBuffer[idx + m] = vertIndex[vgNum[vi] + t];
  550.                             break;
  551.                         }
  552.                 }
  553.             }
  554.  
  555.             Log.i("Load3DS", String.format("Resized object %s from %d to %d vertices", obj.name, obj.vertCount, newVertCount));
  556.             obj.vertCount = newVertCount;
  557.             obj.vertexBuffer = newVertexBuffer;
  558.         }
  559.         else // nothing changed, no need to recalculate anything
  560.             for (i = 0, idx = 3; i < obj.vertCount; i++, idx += 8) // just copy all the normals
  561.                 for (m = vgNum[i]; m < vgNum[i + 1]; m++) // for every NON-unique normal and face of this vertex
  562.                     VecAdd(obj.vertexBuffer, idx, vgNorm, m*3); // add normal to vertex
  563.  
  564.         for (i = 0, k = 3; i < obj.vertCount; i++, k += 8)
  565.             VecNormalize(obj.vertexBuffer, k);
  566.  
  567.         for (m = 0; m < obj.faceMats.size(); m++) {
  568.             FaceMat mat = obj.faceMats.get(m);
  569.             k = 0;
  570.             for (i = 0; i < mat.indCount; i++)
  571.                 for (t = 0; t < 3; t++) {
  572.                     j = 3 * (int) mat.indexBuffer[k];
  573.                     mat.indexBuffer[k++] = (short) faceBuffer[j + t];
  574.                 }
  575.         }
  576.  
  577.         if (unused > 0) {
  578.             FaceMat mat = new FaceMat();
  579.             mat.indexBuffer = new short[3*unused];
  580.             mat.bufOffset = obj.indCount;
  581.             obj.indCount += 3*unused;
  582.             k = 0;
  583.             for (i = 0; i < faceCount; i++)
  584.                 if (!faceUsed[i]) {
  585.                     faceUsed[i] = true;
  586.                     j = i * 3;
  587.                     for (t = 0; t < 3; t++)
  588.                         mat.indexBuffer[k++] = (short) faceBuffer[j + t];
  589.                 }
  590.             obj.faceMats.add(mat);
  591.         }
  592.     }
  593.  
  594.     private Light3D ChunkLight(int len, String name) throws IOException
  595.     {
  596.         long end = filePos + len;
  597.  
  598.         Light3D light = new Light3D();
  599.         light.name = name;
  600.         light.pos = new float[3];
  601.         ChunkVector(light.pos, 0);
  602.  
  603.         while (filePos < end) {
  604.             int chunkID = ReadUnsignedShort();
  605.             int chunkLen = ReadInt() - 6;
  606.  
  607.             switch (chunkID) {
  608.             case CHUNK_RGBC:
  609.                 light.color = new float[4];
  610.                 ChunkRGBC(light.color);
  611.                 break;
  612.  
  613.             case CHUNK_RGB24:
  614.                 light.color = new float[4];
  615.                 ChunkRGB24(light.color);
  616.                 break;
  617.  
  618.             case CHUNK_SPOTL:
  619.                 light.dir = new float[4];
  620.                 ChunkVector(light.dir, 0);
  621.                 light.theta = (float) (ReadFloat() * Math.PI / 180.0f);
  622.                 light.phi = (float) (ReadFloat() * Math.PI / 180.0f);
  623.                 break;
  624.  
  625.             case CHUNK_ONOFF:
  626.             default:
  627.                 Skip(chunkLen);
  628.             }
  629.         }
  630.         Seek(end);
  631.  
  632.         return light;
  633.     }
  634.  
  635.     private Material3D ChunkMaterial(Scene3D scene, int len) throws IOException
  636.     {
  637.         long end = filePos + len;
  638.  
  639.         Material3D mat = new Material3D();
  640.  
  641.         while (filePos < end) {
  642.             int chunkID = ReadUnsignedShort();
  643.             int chunkLen = ReadInt() - 6;
  644.  
  645.             switch (chunkID) {
  646.             case CHUNK_TEXTURE:
  647.                 mat.texture = ChunkMap(chunkLen);
  648.                 break;
  649.  
  650.             case CHUNK_BUMPMAP:
  651.             case CHUNK_REFLMAP:
  652.                 ChunkMap(chunkLen);
  653.                 break;
  654.  
  655.             case CHUNK_AMBIENT:
  656.                 mat.ambient = new float[4];
  657.                 ChunkColor(chunkLen, mat.ambient);
  658.                 break;
  659.  
  660.             case CHUNK_DIFFUSE:
  661.                 mat.diffuse = new float[4];
  662.                 ChunkColor(chunkLen, mat.diffuse);
  663.                 break;
  664.  
  665.             case CHUNK_SPECULAR:
  666.                 mat.specular = new float[4];
  667.                 ChunkColor(chunkLen, mat.specular);
  668.                 break;
  669.  
  670.             case CHUNK_MATNAME:
  671.                 mat.name = ChunkName(chunkLen);
  672.                 break;
  673.  
  674.             case CHUNK_MTLTYPE:
  675.                 mat.type = ReadUnsignedShort();
  676.                 break;
  677.  
  678.             case CHUNK_SHININES:
  679.                 mat.shininess = 100 - ChunkPercent(chunkLen);
  680.                 break;
  681.  
  682.             case CHUNK_SHINSTRN:
  683.                 mat.shinStren = ChunkPercent(chunkLen);
  684.                 break;
  685.  
  686.             case CHUNK_TRANSP:
  687.                 mat.transparency = ChunkPercent(chunkLen);
  688.                 break;
  689.  
  690.             case CHUNK_SELFILL:
  691.                 mat.selfIllum = ChunkPercent(chunkLen);
  692.                 break;
  693.  
  694.             default:
  695.                 Skip(chunkLen);
  696.             }
  697.         }
  698.         Seek(end);
  699.  
  700.         return mat;
  701.     }
  702.  
  703.     private String ChunkMap(int len) throws IOException
  704.     {
  705.         long end = filePos + len;
  706.  
  707.         String name = null;
  708.  
  709.         while (filePos < end) {
  710.             int chunkID = ReadUnsignedShort();
  711.             int chunkLen = ReadInt() - 6;
  712.  
  713.             switch (chunkID) {
  714.             case CHUNK_MAPFILE:
  715.                 name = ChunkName(chunkLen);
  716.                 break;
  717.  
  718.             case CHUNK_MAPPARAM:
  719.             default:
  720.                 Skip(chunkLen);
  721.             }
  722.         }
  723.         Seek(end);
  724.  
  725.         return name;
  726.     }
  727.  
  728.     private void ChunkKeyframer(Scene3D scene, int len) throws IOException
  729.     {
  730.         int fstart = 0, fend = 100;
  731.  
  732.         long end = filePos + len;
  733.         while (filePos < end) {
  734.             int chunkID = ReadUnsignedShort();
  735.             int chunkLen = ReadInt() - 6;
  736.  
  737.             switch (chunkID) {
  738.             case CHUNK_FRAMES:
  739.                 fstart = ReadInt();
  740.                 fend = ReadInt();
  741.                 break;
  742.  
  743.             case CHUNK_TRACKINFO:
  744.                 Animation anim = ChunkMeshTrack(chunkLen, scene);
  745.                 if (anim != null)
  746.                     scene.animations.add(anim);
  747.                 break;
  748.  
  749.             case CHUNK_SPOTINFO:
  750.             default:
  751.                 Skip(chunkLen);
  752.             }
  753.         }
  754.  
  755.         if (fstart < fend)
  756.             for (int i = 0; i < scene.animations.size(); i++) {
  757.                 Animation anim = scene.animations.get(i);
  758.                 if (anim.position != null)
  759.                     for (int j = 0; j < anim.position.length; j++)
  760.                         anim.position[j].time = (anim.position[j].time - fstart) / (fend - fstart);
  761.                 if (anim.rotation != null)
  762.                     for (int j = 0; j < anim.rotation.length; j++)
  763.                         anim.rotation[j].time = (anim.rotation[j].time - fstart) / (fend - fstart);
  764.                 if (anim.scaling != null)
  765.                     for (int j = 0; j < anim.scaling.length; j++)
  766.                         anim.scaling[j].time = (anim.scaling[j].time - fstart) / (fend - fstart);
  767.             }
  768.  
  769.         Seek(end);
  770.     }
  771.  
  772.     private Animation ChunkMeshTrack(int len, Scene3D scene) throws IOException
  773.     {
  774.         Animation anim = new Animation();
  775.         int num, i, j, k;
  776.  
  777.         anim.result = new float[16];
  778.         Matrix.setIdentityM(anim.result, 0);
  779.  
  780.         anim.world = new float[16];
  781.         Matrix.setIdentityM(anim.world, 0);
  782.  
  783.         long end = filePos + len;
  784.         while (filePos < end) {
  785.             int chunkID = ReadUnsignedShort();
  786.             int chunkLen = ReadInt() - 6;
  787.  
  788.             switch (chunkID) {
  789.             case CHUNK_HIERARCHY:
  790.                 anim.id = ReadUnsignedShort();
  791.                 break;
  792.  
  793.             case CHUNK_OBJNAME:
  794.                 String name = ChunkName(0);
  795.                 anim.light = scene.FindLight(name);
  796.                 anim.object = scene.FindObject(name);
  797.                 Skip(4);
  798.                 anim.parent = scene.FindAnimation(ReadUnsignedShort());
  799.                 break;
  800.  
  801.             case CHUNK_PIVOT:
  802.                 anim.pivot = new float[3];
  803.                 ChunkVector(anim.pivot, 0);
  804.                 break;
  805.  
  806.             case CHUNK_TRACKPOS:
  807.                 Skip(10);
  808.                 num = ReadInt();
  809.                 anim.position = new AnimKey[num];
  810.                 for (i = 0; i < num; i++) {
  811.                     anim.position[i] = new AnimKey();
  812.                     anim.position[i].time = ReadInt();
  813.                     k = ReadUnsignedShort();
  814.                     for (j = 0; j < 5; j++)
  815.                         if ((k & (1 << j)) != 0)
  816.                             Skip(4);
  817.                     anim.position[i].data = new float[3];
  818.                     ChunkVector(anim.position[i].data, 0);
  819.                 }
  820.                 break;
  821.  
  822.             case CHUNK_TRACKROT:
  823.                 Skip(10);
  824.                 num = ReadInt();
  825.                 anim.rotation = new AnimKey[num];
  826.                 for (i = 0; i < num; i++) {
  827.                     anim.rotation[i] = new AnimKey();
  828.                     anim.rotation[i].time = ReadInt();
  829.                     k = ReadUnsignedShort();
  830.                     for (j = 0; j < 5; j++)
  831.                         if ((k & (1 << j)) != 0)
  832.                             Skip(4);
  833.                     anim.rotation[i].data = new float[4];
  834.                     anim.rotation[i].data[3] = ReadFloat();
  835.                     ChunkVector(anim.rotation[i].data, 0);
  836.                 }
  837.                 break;
  838.  
  839.             case CHUNK_TRACKSCL:
  840.                 Skip(10);
  841.                 num = ReadInt();
  842.                 anim.scaling = new AnimKey[num];
  843.                 for (i = 0; i < num; i++) {
  844.                     anim.scaling[i] = new AnimKey();
  845.                     anim.scaling[i].time = ReadInt();
  846.                     k = ReadUnsignedShort();
  847.                     for (j = 0; j < 5; j++)
  848.                         if ((k & (1 << j)) != 0)
  849.                             Skip(4);
  850.                     anim.scaling[i].data = new float[3];
  851.                     ChunkVector(anim.scaling[i].data, 0);
  852.                 }
  853.                 break;
  854.  
  855.             default:
  856.                 Skip(chunkLen);
  857.             }
  858.         }
  859.         Seek(end);
  860.  
  861.         return anim;
  862.     }
  863.  
  864.     private void ChunkColor(int len, float[] color) throws IOException
  865.     {
  866.         long end = filePos + len;
  867.         while (filePos < end) {
  868.             int chunkID = ReadUnsignedShort();
  869.             int chunkLen = ReadInt() - 6;
  870.  
  871.             switch (chunkID) {
  872.             case CHUNK_RGBC:
  873.                 ChunkRGBC(color);
  874.                 break;
  875.  
  876.             case CHUNK_RGB24:
  877.                 ChunkRGB24(color);
  878.                 break;
  879.  
  880.             default:
  881.                 Skip(chunkLen);
  882.             }
  883.         }
  884.         Seek(end);
  885.     }
  886.  
  887.     private float ChunkPercent(int len) throws IOException
  888.     {
  889.         float v = 0;
  890.  
  891.         long end = filePos + len;
  892.         while (filePos < end) {
  893.             int chunkID = ReadUnsignedShort();
  894.             int chunkLen = ReadInt() - 6;
  895.  
  896.             switch (chunkID) {
  897.             case CHUNK_SHORT:
  898.                 v = ReadUnsignedShort() / 100.0f;
  899.                 break;
  900.  
  901.             default:
  902.                 Skip(chunkLen);
  903.             }
  904.         }
  905.         Seek(end);
  906.  
  907.         return v;
  908.     }
  909.  
  910.     private String ChunkName(int len) throws IOException
  911.     {
  912.         long end = filePos + len;
  913.         int slen = 0;
  914.         byte[] buffer = new byte[128];
  915.         byte c;
  916.  
  917.         do {
  918.             c = ReadByte();
  919.             if (c != 0)
  920.                 buffer[slen++] = c;
  921.         } while (c != 0);
  922.  
  923.         if (len != 0)
  924.             Seek(end);
  925.  
  926.         String name = new String(buffer, 0, slen);
  927.  
  928.         return name;
  929.     }
  930.  
  931.     private void ChunkVector(float[] vec, int offset) throws IOException
  932.     {
  933.         vec[offset + 0] = ReadFloat();
  934.         vec[offset + 2] = ReadFloat();
  935.         vec[offset + 1] = ReadFloat();
  936.     }
  937.  
  938.     private void ChunkRGBC(float[] c) throws IOException
  939.     {
  940.         c[0] = ReadFloat();
  941.         c[1] = ReadFloat();
  942.         c[2] = ReadFloat();
  943.         c[3] = 1;
  944.     }
  945.  
  946.     private void ChunkRGB24(float[] c) throws IOException
  947.     {
  948.         c[0] = ReadUnsignedByte() / 255.0f;
  949.         c[1] = ReadUnsignedByte() / 255.0f;
  950.         c[2] = ReadUnsignedByte() / 255.0f;
  951.         c[3] = 1;
  952.     }
  953. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement