ginkage

Load3DS

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