Advertisement
ginkage

Load3DS

May 31st, 2012
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 19.04 KB | None | 0 0
  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 = 2 * ReadUnsignedShort();
  282.                 obj.textureBuffer = new float[num];
  283.                 for (i = 0; i < num; i++)
  284.                     obj.textureBuffer[i] = ReadFloat();
  285.                 break;
  286.  
  287.             case CHUNK_VERTLIST:
  288.                 num = ReadUnsignedShort();
  289.                 obj.vertCount = num;
  290.                 obj.vertexBuffer = new float[6*num];
  291.                 for (i = 0, k = 0; i < num; i++, k += 6) {
  292.                     ChunkVector(obj.vertexBuffer, k);
  293.                     obj.vertexBuffer[k + 3] = 0;
  294.                     obj.vertexBuffer[k + 4] = 0;
  295.                     obj.vertexBuffer[k + 5] = 0;
  296.                 }
  297.                 break;
  298.  
  299.             case CHUNK_TRMATRIX:
  300.                 float[] localCoord = new float[16];
  301.                 ChunkVector(localCoord, 4*0);
  302.                 ChunkVector(localCoord, 4*2);
  303.                 ChunkVector(localCoord, 4*1);
  304.                 ChunkVector(localCoord, 4*3);
  305.                 localCoord[3] = localCoord[7] = localCoord[11] = 0;
  306.                 localCoord[15] = 1;
  307.  
  308.                 obj.trMatrix = new float[16];
  309.                 Matrix.invertM(obj.trMatrix, 0, localCoord, 0);
  310.                 break;
  311.  
  312.             default:
  313.                 Skip(chunkLen);
  314.             }
  315.         }
  316.         Seek(end);
  317.  
  318.         return obj;
  319.     }
  320.    
  321.     private static void CrossProduct(float[] res, float[] v1, float[] v2)
  322.     {
  323.         res[0] = v1[1]*v2[2] - v1[2]*v2[1];
  324.         res[1] = v1[2]*v2[0] - v1[0]*v2[2];
  325.         res[2] = v1[0]*v2[1] - v1[1]*v2[0];
  326.     }
  327.  
  328.     private static float DotSquare(float[] v, int offset)
  329.     {
  330.         return v[offset + 0]*v[offset + 0] + v[offset + 1]*v[offset + 1] + v[offset + 2]*v[offset + 2];
  331.     }
  332.  
  333.     private static void VecSubstract(float[] res, float[] v, int offset1, int offset2)
  334.     {
  335.         res[0] = v[offset1 + 0] - v[offset2 + 0];
  336.         res[1] = v[offset1 + 1] - v[offset2 + 1];
  337.         res[2] = v[offset1 + 2] - v[offset2 + 2];
  338.     }
  339.  
  340.     private static void VecAdd(float[] v, int offset, float[] a)
  341.     {
  342.         v[offset + 0] += a[0];
  343.         v[offset + 1] += a[1];
  344.         v[offset + 2] += a[2];
  345.     }
  346.    
  347.     private void VecNormalize(float[] v, int offset)
  348.     {
  349.         double nlen = 1 / Math.sqrt(DotSquare(v, offset));
  350.         v[offset + 0] *= nlen;
  351.         v[offset + 1] *= nlen;
  352.         v[offset + 2] *= nlen;
  353.     }
  354.  
  355.     private void ChunkFaceList(int len, Object3D obj, Scene3D scene) throws IOException
  356.     {
  357.         long end = filePos + len;
  358.  
  359.         int i, j, k, l, num = ReadUnsignedShort(), unused = num, idx;
  360.  
  361.         obj.faceCount = num;
  362.         obj.faceBuffer = new int[3*num];
  363.         obj.faceUsed = new boolean[num];
  364.         float[] v = new float[3];
  365.         float[] v1 = new float[3];
  366.         float[] v2 = new float[3];
  367.  
  368.         for (i = 0, idx = 0; i < num; i++, idx += 3) {
  369.             j = ReadUnsignedShort();
  370.             k = ReadUnsignedShort();
  371.             l = ReadUnsignedShort();
  372.             Skip(2);
  373.  
  374.             obj.faceUsed[i] = false;
  375.             obj.faceBuffer[idx + 0] = j;
  376.             obj.faceBuffer[idx + 2] = k;
  377.             obj.faceBuffer[idx + 1] = l;
  378.  
  379.             j *= 6;
  380.             k *= 6;
  381.             l *= 6;
  382.             VecSubstract(v1, obj.vertexBuffer, l, j);
  383.             VecSubstract(v2, obj.vertexBuffer, k, j);
  384.             CrossProduct(v, v1, v2);
  385.  
  386.             VecAdd(obj.vertexBuffer, j + 3, v);
  387.             VecAdd(obj.vertexBuffer, k + 3, v);
  388.             VecAdd(obj.vertexBuffer, l + 3, v);
  389.         }
  390.  
  391.         for (i = 0, k = 3; i < obj.vertCount; i++, k += 6)
  392.             VecNormalize(obj.vertexBuffer, k);
  393.  
  394.         v = null;
  395.         v1 = null;
  396.         v2 = null;
  397.  
  398.         while (filePos < end) {
  399.             int chunkID = ReadUnsignedShort();
  400.             int chunkLen = ReadInt() - 6;
  401.  
  402.             switch (chunkID) {
  403.             case CHUNK_FACEMAT:
  404.                 FaceMat mat = new FaceMat();
  405.                 String name = ChunkName(0);
  406.                 mat.material = scene.FindMaterial(name);
  407.                 num = ReadUnsignedShort();
  408.                 mat.faces = num;
  409.                 mat.indexBuffer = new short[3*num];
  410.                 mat.bufOffset = obj.indCount;
  411.                 obj.indCount += 3*num;
  412.                 k = 0;
  413.                 for (i = 0; i < num; i++) {
  414.                     j = ReadUnsignedShort();
  415.                     if (!obj.faceUsed[j]) {
  416.                         obj.faceUsed[j] = true;
  417.                         unused--;
  418.                     }
  419.                     j *= 3;
  420.                     mat.indexBuffer[k++] = (short) obj.faceBuffer[j + 0];
  421.                     mat.indexBuffer[k++] = (short) obj.faceBuffer[j + 1];
  422.                     mat.indexBuffer[k++] = (short) obj.faceBuffer[j + 2];
  423.                 }
  424.                 obj.faceMats.add(mat);
  425.                 break;
  426.  
  427.             case CHUNK_SMOOTHG:
  428.             default:
  429.                 Skip(chunkLen);
  430.             }
  431.         }
  432.         Seek(end);
  433.        
  434.         if (unused > 0) {
  435.             FaceMat mat = new FaceMat();
  436.             mat.faces = unused;
  437.             mat.indexBuffer = new short[3*unused];
  438.             mat.bufOffset = obj.indCount;
  439.             obj.indCount += 3*unused;
  440.             k = 0;
  441.             for (i = 0; i < obj.faceCount; i++)
  442.                 if (!obj.faceUsed[i]) {
  443.                     obj.faceUsed[i] = true;
  444.                     j = i * 3;
  445.                     mat.indexBuffer[k++] = (short) obj.faceBuffer[j + 0];
  446.                     mat.indexBuffer[k++] = (short) obj.faceBuffer[j + 1];
  447.                     mat.indexBuffer[k++] = (short) obj.faceBuffer[j + 2];
  448.                 }
  449.             obj.faceMats.add(mat);
  450.         }
  451.  
  452.         obj.faceBuffer = null;
  453.         obj.faceUsed = null;
  454.     }
  455.  
  456.     private Light3D ChunkLight(int len, String name) throws IOException
  457.     {
  458.         long end = filePos + len;
  459.  
  460.         Light3D light = new Light3D();
  461.         light.name = name;
  462.         light.pos = new float[3];
  463.         ChunkVector(light.pos, 0);
  464.  
  465.         while (filePos < end) {
  466.             int chunkID = ReadUnsignedShort();
  467.             int chunkLen = ReadInt() - 6;
  468.  
  469.             switch (chunkID) {
  470.             case CHUNK_RGBC:
  471.                 light.color = new float[4];
  472.                 ChunkRGBC(light.color);
  473.                 break;
  474.  
  475.             case CHUNK_RGB24:
  476.                 light.color = new float[4];
  477.                 ChunkRGB24(light.color);
  478.                 break;
  479.  
  480.             case CHUNK_SPOTL:
  481.                 light.dir = new float[4];
  482.                 ChunkVector(light.dir, 0);
  483.                 light.theta = (float) (ReadFloat() * Math.PI / 180.0f);
  484.                 light.phi = (float) (ReadFloat() * Math.PI / 180.0f);
  485.                 break;
  486.  
  487.             case CHUNK_ONOFF:
  488.             default:
  489.                 Skip(chunkLen);
  490.             }
  491.         }
  492.         Seek(end);
  493.        
  494.         return light;
  495.     }
  496.  
  497.     private Material3D ChunkMaterial(Scene3D scene, int len) throws IOException
  498.     {
  499.         long end = filePos + len;
  500.        
  501.         Material3D mat = new Material3D();
  502.  
  503.         while (filePos < end) {
  504.             int chunkID = ReadUnsignedShort();
  505.             int chunkLen = ReadInt() - 6;
  506.  
  507.             switch (chunkID) {
  508.             case CHUNK_TEXTURE:
  509.                 mat.texture = ChunkMap(chunkLen);
  510.                 break;
  511.  
  512.             case CHUNK_BUMPMAP:
  513.             case CHUNK_REFLMAP:
  514.                 ChunkMap(chunkLen);
  515.                 break;
  516.  
  517.             case CHUNK_AMBIENT:
  518.                 mat.ambient = new float[4];
  519.                 ChunkColor(chunkLen, mat.ambient);
  520.                 break;
  521.  
  522.             case CHUNK_DIFFUSE:
  523.                 mat.diffuse = new float[4];
  524.                 ChunkColor(chunkLen, mat.diffuse);
  525.                 break;
  526.  
  527.             case CHUNK_SPECULAR:
  528.                 mat.specular = new float[4];
  529.                 ChunkColor(chunkLen, mat.specular);
  530.                 break;
  531.  
  532.             case CHUNK_MATNAME:
  533.                 mat.name = ChunkName(chunkLen);
  534.                 break;
  535.  
  536.             case CHUNK_MTLTYPE:
  537.                 mat.type = ReadUnsignedShort();
  538.                 break;
  539.  
  540.             case CHUNK_SHININES:
  541.                 mat.shininess = ChunkPercent(chunkLen) * 1000;
  542.                 break;
  543.  
  544.             case CHUNK_SHINSTRN:
  545.                 mat.shinStren = ChunkPercent(chunkLen);
  546.                 break;
  547.  
  548.             case CHUNK_TRANSP:
  549.                 mat.transparency = ChunkPercent(chunkLen);
  550.                 break;
  551.  
  552.             case CHUNK_SELFILL:
  553.                 mat.selfIllum = ChunkPercent(chunkLen);
  554.                 break;
  555.  
  556.             default:
  557.                 Skip(chunkLen);
  558.             }
  559.         }
  560.         Seek(end);
  561.        
  562.         return mat;
  563.     }
  564.  
  565.     private String ChunkMap(int len) throws IOException
  566.     {
  567.         long end = filePos + len;
  568.  
  569.         String name = null;
  570.  
  571.         while (filePos < end) {
  572.             int chunkID = ReadUnsignedShort();
  573.             int chunkLen = ReadInt() - 6;
  574.  
  575.             switch (chunkID) {
  576.             case CHUNK_MAPFILE:
  577.                 name = ChunkName(chunkLen);
  578.                 break;
  579.  
  580.             case CHUNK_MAPPARAM:
  581.             default:
  582.                 Skip(chunkLen);
  583.             }
  584.         }
  585.         Seek(end);
  586.        
  587.         return name;
  588.     }
  589.  
  590.     private void ChunkKeyframer(Scene3D scene, int len) throws IOException
  591.     {
  592.         int fstart = 0, fend = 100;
  593.  
  594.         long end = filePos + len;
  595.         while (filePos < end) {
  596.             int chunkID = ReadUnsignedShort();
  597.             int chunkLen = ReadInt() - 6;
  598.  
  599.             switch (chunkID) {
  600.             case CHUNK_FRAMES:
  601.                 fstart = ReadInt();
  602.                 fend = ReadInt();
  603.                 break;
  604.  
  605.             case CHUNK_TRACKINFO:
  606.                 Animation anim = ChunkMeshTrack(chunkLen, scene);
  607.                 if (anim != null)
  608.                     scene.animations.add(anim);
  609.                 break;
  610.  
  611.             case CHUNK_SPOTINFO:
  612.             default:
  613.                 Skip(chunkLen);
  614.             }
  615.         }
  616.  
  617.         if (fstart < fend)
  618.             for (int i = 0; i < scene.animations.size(); i++) {
  619.                 Animation anim = scene.animations.get(i);
  620.                 if (anim.position != null)
  621.                     for (int j = 0; j < anim.position.length; j++)
  622.                         anim.position[j].time = (anim.position[j].time - fstart) / (fend - fstart);
  623.                 if (anim.rotation != null)
  624.                     for (int j = 0; j < anim.rotation.length; j++)
  625.                         anim.rotation[j].time = (anim.rotation[j].time - fstart) / (fend - fstart);
  626.                 if (anim.scaling != null)
  627.                     for (int j = 0; j < anim.scaling.length; j++)
  628.                         anim.scaling[j].time = (anim.scaling[j].time - fstart) / (fend - fstart);
  629.             }
  630.  
  631.         Seek(end);
  632.     }
  633.  
  634.     private Animation ChunkMeshTrack(int len, Scene3D scene) throws IOException
  635.     {
  636.         Animation anim = new Animation();
  637.         int num, i, j, k;
  638.        
  639.         anim.result = new float[16];
  640.         Matrix.setIdentityM(anim.result, 0);
  641.  
  642.         anim.world = new float[16];
  643.         Matrix.setIdentityM(anim.world, 0);
  644.  
  645.         long end = filePos + len;
  646.         while (filePos < end) {
  647.             int chunkID = ReadUnsignedShort();
  648.             int chunkLen = ReadInt() - 6;
  649.  
  650.             switch (chunkID) {
  651.             case CHUNK_HIERARCHY:
  652.                 anim.id = ReadUnsignedShort();
  653.                 break;
  654.  
  655.             case CHUNK_OBJNAME:
  656.                 String name = ChunkName(0);
  657.                 anim.light = scene.FindLight(name);
  658.                 anim.object = scene.FindObject(name);
  659.                 Skip(4);
  660.                 anim.idParent = ReadUnsignedShort();
  661.                 anim.parent = scene.FindAnimation(anim.idParent);
  662.                 if (anim.parent != null) {
  663.                     anim.parent.childNext = anim.parent.childFirst;
  664.                     anim.parent.childFirst = anim;
  665.                 }
  666.                 break;
  667.  
  668.             case CHUNK_PIVOT:
  669.                 anim.pivot = new float[3];
  670.                 ChunkVector(anim.pivot, 0);
  671.                 break;
  672.  
  673.             case CHUNK_TRACKPOS:
  674.                 Skip(10);
  675.                 num = ReadInt();
  676.                 anim.position = new AnimKey[num];
  677.                 for (i = 0; i < num; i++) {
  678.                     anim.position[i] = new AnimKey();
  679.                     anim.position[i].time = ReadInt();
  680.                     k = ReadUnsignedShort();
  681.                     for (j = 0; j < 5; j++)
  682.                         if ((k & (1 << j)) != 0)
  683.                             Skip(4);
  684.                     anim.position[i].data = new float[3];
  685.                     ChunkVector(anim.position[i].data, 0);
  686.                 }
  687.                 break;
  688.  
  689.             case CHUNK_TRACKROT:
  690.                 Skip(10);
  691.                 num = ReadInt();
  692.                 anim.rotation = new AnimKey[num];
  693.                 for (i = 0; i < num; i++) {
  694.                     anim.rotation[i] = new AnimKey();
  695.                     anim.rotation[i].time = ReadInt();
  696.                     k = ReadUnsignedShort();
  697.                     for (j = 0; j < 5; j++)
  698.                         if ((k & (1 << j)) != 0)
  699.                             Skip(4);
  700.  
  701.                     anim.rotation[i].data = new float[4];
  702.                     anim.rotation[i].data[3] = ReadFloat();
  703.                     ChunkVector(anim.rotation[i].data, 0);
  704.                 }
  705.                 break;
  706.  
  707.             case CHUNK_TRACKSCL:
  708.                 Skip(10);
  709.                 num = ReadInt();
  710.                 anim.scaling = new AnimKey[num];
  711.                 for (i = 0; i < num; i++) {
  712.                     anim.scaling[i] = new AnimKey();
  713.                     anim.scaling[i].time = ReadInt();
  714.                     k = ReadUnsignedShort();
  715.                     for (j = 0; j < 5; j++)
  716.                         if ((k & (1 << j)) != 0)
  717.                             Skip(4);
  718.                     anim.scaling[i].data = new float[3];
  719.                     ChunkVector(anim.scaling[i].data, 0);
  720.                 }
  721.                 break;
  722.  
  723.             default:
  724.                 Skip(chunkLen);
  725.             }
  726.         }
  727.         Seek(end);
  728.  
  729.         return anim;
  730.     }
  731.  
  732.     private void ChunkColor(int len, float[] color) throws IOException
  733.     {
  734.         long end = filePos + len;
  735.         while (filePos < end) {
  736.             int chunkID = ReadUnsignedShort();
  737.             int chunkLen = ReadInt() - 6;
  738.  
  739.             switch (chunkID) {
  740.             case CHUNK_RGBC:
  741.                 ChunkRGBC(color);
  742.                 break;
  743.  
  744.             case CHUNK_RGB24:
  745.                 ChunkRGB24(color);
  746.                 break;
  747.  
  748.             default:
  749.                 Skip(chunkLen);
  750.             }
  751.         }
  752.         Seek(end);
  753.     }
  754.  
  755.     private float ChunkPercent(int len) throws IOException
  756.     {
  757.         float v = 0;
  758.  
  759.         long end = filePos + len;
  760.         while (filePos < end) {
  761.             int chunkID = ReadUnsignedShort();
  762.             int chunkLen = ReadInt() - 6;
  763.  
  764.             switch (chunkID) {
  765.             case CHUNK_SHORT:
  766.                 v = ReadUnsignedShort() / 100.0f;
  767.                 break;
  768.  
  769.             default:
  770.                 Skip(chunkLen);
  771.             }
  772.         }
  773.         Seek(end);
  774.  
  775.         return v;
  776.     }
  777.  
  778.     private String ChunkName(int len) throws IOException
  779.     {
  780.         long end = filePos + len;
  781.         int slen = 0;
  782.         byte[] buffer = new byte[128];
  783.         byte c;
  784.  
  785.         do {
  786.             c = ReadByte();
  787.             if (c != 0)
  788.                 buffer[slen++] = c;
  789.         } while (c != 0);
  790.  
  791.         if (len != 0)
  792.             Seek(end);
  793.  
  794.         String name = new String(buffer, 0, slen);
  795.  
  796.         return name;
  797.     }
  798.  
  799.     private void ChunkVector(float[] vec, int offset) throws IOException
  800.     {
  801.         vec[offset + 0] = ReadFloat();
  802.         vec[offset + 2] = ReadFloat();
  803.         vec[offset + 1] = ReadFloat();
  804.     }
  805.  
  806.     private void ChunkRGBC(float[] c) throws IOException
  807.     {
  808.         c[0] = ReadFloat();
  809.         c[1] = ReadFloat();
  810.         c[2] = ReadFloat();
  811.         c[3] = 1;
  812.     }
  813.  
  814.     private void ChunkRGB24(float[] c) throws IOException
  815.     {
  816.         c[0] = ReadUnsignedByte() / 255.0f;
  817.         c[1] = ReadUnsignedByte() / 255.0f;
  818.         c[2] = ReadUnsignedByte() / 255.0f;
  819.         c[3] = 1;
  820.     }
  821. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement