Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import java.io.BufferedInputStream;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileNotFoundException;
- import java.io.IOException;
- import java.util.ArrayList;
- import android.opengl.Matrix;
- import android.os.Environment;
- public class Load3DS {
- private final int CHUNK_MAIN = 0x4D4D;
- private final int CHUNK_OBJMESH = 0x3D3D;
- private final int CHUNK_OBJBLOCK = 0x4000;
- private final int CHUNK_TRIMESH = 0x4100;
- private final int CHUNK_VERTLIST = 0x4110;
- private final int CHUNK_FACELIST = 0x4120;
- private final int CHUNK_FACEMAT = 0x4130;
- private final int CHUNK_MAPLIST = 0x4140;
- private final int CHUNK_SMOOTHG = 0x4150;
- private final int CHUNK_TRMATRIX = 0x4160;
- private final int CHUNK_LIGHT = 0x4600;
- private final int CHUNK_SPOTL = 0x4610;
- private final int CHUNK_ONOFF = 0x4620;
- private final int CHUNK_CAMERA = 0x4700;
- private final int CHUNK_RGBC = 0x0010;
- private final int CHUNK_RGB24 = 0x0011;
- private final int CHUNK_SHORT = 0x0030;
- private final int CHUNK_BACKCOL = 0x1200;
- private final int CHUNK_AMB = 0x2100;
- private final int CHUNK_MATERIAL = 0xAFFF;
- private final int CHUNK_MATNAME = 0xA000;
- private final int CHUNK_AMBIENT = 0xA010;
- private final int CHUNK_DIFFUSE = 0xA020;
- private final int CHUNK_SPECULAR = 0xA030;
- private final int CHUNK_SHININES = 0xA040;
- private final int CHUNK_SHINSTRN = 0xA041;
- private final int CHUNK_TRANSP = 0xA050;
- private final int CHUNK_SELFILL = 0xA084;
- private final int CHUNK_MTLTYPE = 0xA100;
- private final int CHUNK_TEXTURE = 0xA200;
- private final int CHUNK_REFLMAP = 0xA220;
- private final int CHUNK_BUMPMAP = 0xA230;
- private final int CHUNK_MAPFILE = 0xA300;
- private final int CHUNK_MAPPARAM = 0xA351;
- private final int CHUNK_KEYFRAMER = 0xB000;
- private final int CHUNK_TRACKINFO = 0xB002;
- private final int CHUNK_SPOTINFO = 0xB007;
- private final int CHUNK_FRAMES = 0xB008;
- private final int CHUNK_OBJNAME = 0xB010;
- private final int CHUNK_PIVOT = 0xB013;
- private final int CHUNK_TRACKPOS = 0xB020;
- private final int CHUNK_TRACKROT = 0xB021;
- private final int CHUNK_TRACKSCL = 0xB022;
- private final int CHUNK_HIERARCHY = 0xB030;
- private BufferedInputStream file;
- private byte[] bytes = new byte[8];
- private long filePos;
- public Scene3D Load(String fileName)
- {
- file = null;
- Scene3D scene = null;
- File dir = new File(Environment.getExternalStorageDirectory().getAbsolutePath());
- File fil = new File(dir.getAbsolutePath() + File.separator + fileName);
- if (!fil.exists()) return scene;
- try {
- filePos = 0;
- file = new BufferedInputStream(new FileInputStream(fil));
- scene = ProcessFile(fil.length());
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- try {
- if (file != null)
- file.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return scene;
- }
- private void Skip(long count) throws IOException
- {
- file.skip(count);
- filePos += count;
- }
- private void Seek(long end) throws IOException
- {
- if (filePos < end) {
- Skip(end - filePos);
- filePos = end;
- }
- }
- private byte ReadByte() throws IOException
- {
- file.read(bytes, 0, 1);
- filePos++;
- return bytes[0];
- }
- private int ReadUnsignedByte() throws IOException
- {
- file.read(bytes, 0, 1);
- filePos++;
- return (bytes[0]&0xff);
- }
- private int ReadUnsignedShort() throws IOException
- {
- file.read(bytes, 0, 2);
- filePos += 2;
- return ((bytes[1]&0xff) << 8 | (bytes[0]&0xff));
- }
- private int ReadInt() throws IOException
- {
- file.read(bytes, 0, 4);
- filePos += 4;
- return (bytes[3]) << 24 | (bytes[2]&0xff) << 16 | (bytes[1]&0xff) << 8 | (bytes[0]&0xff);
- }
- private float ReadFloat() throws IOException
- {
- return Float.intBitsToFloat(ReadInt());
- }
- private Scene3D ProcessFile(long fileLen) throws IOException
- {
- Scene3D scene = null;
- while (filePos < fileLen) {
- int chunkID = ReadUnsignedShort();
- int chunkLen = ReadInt() - 6;
- switch (chunkID) {
- case CHUNK_MAIN:
- if (scene == null)
- scene = ChunkMain(chunkLen);
- else
- Skip(chunkLen);
- break;
- default:
- Skip(chunkLen);
- }
- }
- return scene;
- }
- private Scene3D ChunkMain(int len) throws IOException
- {
- Scene3D scene = new Scene3D();
- scene.materials = new ArrayList<Material3D>();
- scene.objects = new ArrayList<Object3D>();
- scene.lights = new ArrayList<Light3D>();
- scene.animations = new ArrayList<Animation>();
- long end = filePos + len;
- while (filePos < end) {
- int chunkID = ReadUnsignedShort();
- int chunkLen = ReadInt() - 6;
- switch (chunkID) {
- case CHUNK_OBJMESH:
- Chunk3DEditor(scene, chunkLen);
- break;
- case CHUNK_KEYFRAMER:
- ChunkKeyframer(scene, chunkLen);
- break;
- case CHUNK_BACKCOL:
- scene.background = new float[4];
- ChunkColor(chunkLen, scene.background);
- break;
- case CHUNK_AMB:
- scene.ambient = new float[4];
- ChunkColor(chunkLen, scene.ambient);
- break;
- default:
- Skip(chunkLen);
- }
- }
- Seek(end);
- scene.Compute(0);
- return scene;
- }
- private void Chunk3DEditor(Scene3D scene, int len) throws IOException
- {
- long end = filePos + len;
- while (filePos < end) {
- int chunkID = ReadUnsignedShort();
- int chunkLen = ReadInt() - 6;
- switch (chunkID) {
- case CHUNK_OBJBLOCK:
- ChunkObject(scene, chunkLen);
- break;
- case CHUNK_MATERIAL:
- Material3D mat = ChunkMaterial(scene, chunkLen);
- if (mat != null)
- scene.materials.add(mat);
- break;
- default:
- Skip(chunkLen);
- }
- }
- Seek(end);
- }
- private void ChunkObject(Scene3D scene, int len) throws IOException
- {
- long end = filePos + len;
- if (len == 0) return;
- String name = ChunkName(0);
- while (filePos < end) {
- int chunkID = ReadUnsignedShort();
- int chunkLen = ReadInt() - 6;
- switch (chunkID) {
- case CHUNK_TRIMESH:
- Object3D obj = ChunkTrimesh(chunkLen, name, scene);
- if (obj != null)
- scene.objects.add(obj);
- break;
- case CHUNK_LIGHT:
- Light3D light = ChunkLight(chunkLen, name);
- if (light != null)
- scene.lights.add(light);
- break;
- case CHUNK_CAMERA:
- default:
- Skip(chunkLen);
- }
- }
- Seek(end);
- }
- private Object3D ChunkTrimesh(int len, String name, Scene3D scene) throws IOException
- {
- long end = filePos + len;
- Object3D obj = new Object3D();
- obj.name = name;
- obj.faceMats = new ArrayList<FaceMat>();
- obj.indCount = 0;
- int i, k, num;
- while (filePos < end) {
- int chunkID = ReadUnsignedShort();
- int chunkLen = ReadInt() - 6;
- switch (chunkID) {
- case CHUNK_FACELIST:
- ChunkFaceList(chunkLen, obj, scene);
- break;
- case CHUNK_MAPLIST:
- num = ReadUnsignedShort();
- for (i = 0, k = 6; i < num; i++, k += 8) {
- obj.vertexBuffer[k + 0] = ReadFloat();
- obj.vertexBuffer[k + 1] = 1 - ReadFloat();
- }
- break;
- case CHUNK_VERTLIST:
- num = ReadUnsignedShort();
- obj.vertCount = num;
- obj.vertexBuffer = new float[8*num];
- for (i = 0, k = 0; i < num; i++, k += 8) {
- ChunkVector(obj.vertexBuffer, k);
- obj.vertexBuffer[k + 3] = 0;
- obj.vertexBuffer[k + 4] = 0;
- obj.vertexBuffer[k + 5] = 0;
- obj.vertexBuffer[k + 6] = 0;
- obj.vertexBuffer[k + 7] = 0;
- }
- break;
- case CHUNK_TRMATRIX:
- float[] localCoord = new float[16];
- ChunkVector(localCoord, 4*0);
- ChunkVector(localCoord, 4*2);
- ChunkVector(localCoord, 4*1);
- ChunkVector(localCoord, 4*3);
- localCoord[3] = localCoord[7] = localCoord[11] = 0;
- localCoord[15] = 1;
- obj.trMatrix = new float[16];
- Matrix.invertM(obj.trMatrix, 0, localCoord, 0);
- break;
- default:
- Skip(chunkLen);
- }
- }
- Seek(end);
- return obj;
- }
- private static void CrossProduct(float[] res, float[] v1, float[] v2)
- {
- res[0] = v1[1]*v2[2] - v1[2]*v2[1];
- res[1] = v1[2]*v2[0] - v1[0]*v2[2];
- res[2] = v1[0]*v2[1] - v1[1]*v2[0];
- }
- private static float DotSquare(float[] v, int offset)
- {
- return v[offset + 0]*v[offset + 0] + v[offset + 1]*v[offset + 1] + v[offset + 2]*v[offset + 2];
- }
- private static void VecSubstract(float[] res, float[] v, int offset1, int offset2)
- {
- res[0] = v[offset1 + 0] - v[offset2 + 0];
- res[1] = v[offset1 + 1] - v[offset2 + 1];
- res[2] = v[offset1 + 2] - v[offset2 + 2];
- }
- private static void VecAdd(float[] v, int offset, float[] a)
- {
- v[offset + 0] += a[0];
- v[offset + 1] += a[1];
- v[offset + 2] += a[2];
- }
- private void VecNormalize(float[] v, int offset)
- {
- double nlen = 1 / Math.sqrt(DotSquare(v, offset));
- v[offset + 0] *= nlen;
- v[offset + 1] *= nlen;
- v[offset + 2] *= nlen;
- }
- private void ChunkFaceList(int len, Object3D obj, Scene3D scene) throws IOException
- {
- long end = filePos + len;
- int i, j, k, l, num = ReadUnsignedShort(), unused = num, idx;
- int faceCount = num;
- int[] faceBuffer = new int[3*num];
- boolean[] faceUsed = new boolean[num];
- float[] v = new float[3];
- float[] v1 = new float[3];
- float[] v2 = new float[3];
- for (i = 0, idx = 0; i < num; i++, idx += 3) {
- j = ReadUnsignedShort();
- k = ReadUnsignedShort();
- l = ReadUnsignedShort();
- Skip(2);
- faceUsed[i] = false;
- faceBuffer[idx + 0] = j;
- faceBuffer[idx + 2] = k;
- faceBuffer[idx + 1] = l;
- j *= 8;
- k *= 8;
- l *= 8;
- VecSubstract(v1, obj.vertexBuffer, l, j);
- VecSubstract(v2, obj.vertexBuffer, k, j);
- CrossProduct(v, v1, v2);
- VecAdd(obj.vertexBuffer, j + 3, v);
- VecAdd(obj.vertexBuffer, k + 3, v);
- VecAdd(obj.vertexBuffer, l + 3, v);
- }
- for (i = 0, k = 3; i < obj.vertCount; i++, k += 8)
- VecNormalize(obj.vertexBuffer, k);
- v = null;
- v1 = null;
- v2 = null;
- while (filePos < end) {
- int chunkID = ReadUnsignedShort();
- int chunkLen = ReadInt() - 6;
- switch (chunkID) {
- case CHUNK_FACEMAT:
- FaceMat mat = new FaceMat();
- String name = ChunkName(0);
- mat.material = scene.FindMaterial(name);
- num = ReadUnsignedShort();
- mat.indexBuffer = new short[3*num];
- mat.bufOffset = obj.indCount;
- obj.indCount += 3*num;
- k = 0;
- for (i = 0; i < num; i++) {
- j = ReadUnsignedShort();
- if (!faceUsed[j]) {
- faceUsed[j] = true;
- unused--;
- }
- j *= 3;
- mat.indexBuffer[k++] = (short) faceBuffer[j + 0];
- mat.indexBuffer[k++] = (short) faceBuffer[j + 1];
- mat.indexBuffer[k++] = (short) faceBuffer[j + 2];
- }
- obj.faceMats.add(mat);
- break;
- case CHUNK_SMOOTHG:
- default:
- Skip(chunkLen);
- }
- }
- Seek(end);
- if (unused > 0) {
- FaceMat mat = new FaceMat();
- mat.indexBuffer = new short[3*unused];
- mat.bufOffset = obj.indCount;
- obj.indCount += 3*unused;
- k = 0;
- for (i = 0; i < faceCount; i++)
- if (!faceUsed[i]) {
- faceUsed[i] = true;
- j = i * 3;
- mat.indexBuffer[k++] = (short) faceBuffer[j + 0];
- mat.indexBuffer[k++] = (short) faceBuffer[j + 1];
- mat.indexBuffer[k++] = (short) faceBuffer[j + 2];
- }
- obj.faceMats.add(mat);
- }
- faceBuffer = null;
- faceUsed = null;
- }
- private Light3D ChunkLight(int len, String name) throws IOException
- {
- long end = filePos + len;
- Light3D light = new Light3D();
- light.name = name;
- light.pos = new float[3];
- ChunkVector(light.pos, 0);
- while (filePos < end) {
- int chunkID = ReadUnsignedShort();
- int chunkLen = ReadInt() - 6;
- switch (chunkID) {
- case CHUNK_RGBC:
- light.color = new float[4];
- ChunkRGBC(light.color);
- break;
- case CHUNK_RGB24:
- light.color = new float[4];
- ChunkRGB24(light.color);
- break;
- case CHUNK_SPOTL:
- light.dir = new float[4];
- ChunkVector(light.dir, 0);
- light.theta = (float) (ReadFloat() * Math.PI / 180.0f);
- light.phi = (float) (ReadFloat() * Math.PI / 180.0f);
- break;
- case CHUNK_ONOFF:
- default:
- Skip(chunkLen);
- }
- }
- Seek(end);
- return light;
- }
- private Material3D ChunkMaterial(Scene3D scene, int len) throws IOException
- {
- long end = filePos + len;
- Material3D mat = new Material3D();
- while (filePos < end) {
- int chunkID = ReadUnsignedShort();
- int chunkLen = ReadInt() - 6;
- switch (chunkID) {
- case CHUNK_TEXTURE:
- mat.texture = ChunkMap(chunkLen);
- break;
- case CHUNK_BUMPMAP:
- case CHUNK_REFLMAP:
- ChunkMap(chunkLen);
- break;
- case CHUNK_AMBIENT:
- mat.ambient = new float[4];
- ChunkColor(chunkLen, mat.ambient);
- break;
- case CHUNK_DIFFUSE:
- mat.diffuse = new float[4];
- ChunkColor(chunkLen, mat.diffuse);
- break;
- case CHUNK_SPECULAR:
- mat.specular = new float[4];
- ChunkColor(chunkLen, mat.specular);
- break;
- case CHUNK_MATNAME:
- mat.name = ChunkName(chunkLen);
- break;
- case CHUNK_MTLTYPE:
- mat.type = ReadUnsignedShort();
- break;
- case CHUNK_SHININES:
- mat.shininess = 100 - ChunkPercent(chunkLen);
- break;
- case CHUNK_SHINSTRN:
- mat.shinStren = ChunkPercent(chunkLen);
- break;
- case CHUNK_TRANSP:
- mat.transparency = ChunkPercent(chunkLen);
- break;
- case CHUNK_SELFILL:
- mat.selfIllum = ChunkPercent(chunkLen);
- break;
- default:
- Skip(chunkLen);
- }
- }
- Seek(end);
- return mat;
- }
- private String ChunkMap(int len) throws IOException
- {
- long end = filePos + len;
- String name = null;
- while (filePos < end) {
- int chunkID = ReadUnsignedShort();
- int chunkLen = ReadInt() - 6;
- switch (chunkID) {
- case CHUNK_MAPFILE:
- name = ChunkName(chunkLen);
- break;
- case CHUNK_MAPPARAM:
- default:
- Skip(chunkLen);
- }
- }
- Seek(end);
- return name;
- }
- private void ChunkKeyframer(Scene3D scene, int len) throws IOException
- {
- int fstart = 0, fend = 100;
- long end = filePos + len;
- while (filePos < end) {
- int chunkID = ReadUnsignedShort();
- int chunkLen = ReadInt() - 6;
- switch (chunkID) {
- case CHUNK_FRAMES:
- fstart = ReadInt();
- fend = ReadInt();
- break;
- case CHUNK_TRACKINFO:
- Animation anim = ChunkMeshTrack(chunkLen, scene);
- if (anim != null)
- scene.animations.add(anim);
- break;
- case CHUNK_SPOTINFO:
- default:
- Skip(chunkLen);
- }
- }
- if (fstart < fend)
- for (int i = 0; i < scene.animations.size(); i++) {
- Animation anim = scene.animations.get(i);
- if (anim.position != null)
- for (int j = 0; j < anim.position.length; j++)
- anim.position[j].time = (anim.position[j].time - fstart) / (fend - fstart);
- if (anim.rotation != null)
- for (int j = 0; j < anim.rotation.length; j++)
- anim.rotation[j].time = (anim.rotation[j].time - fstart) / (fend - fstart);
- if (anim.scaling != null)
- for (int j = 0; j < anim.scaling.length; j++)
- anim.scaling[j].time = (anim.scaling[j].time - fstart) / (fend - fstart);
- }
- Seek(end);
- }
- private Animation ChunkMeshTrack(int len, Scene3D scene) throws IOException
- {
- Animation anim = new Animation();
- int num, i, j, k;
- anim.result = new float[16];
- Matrix.setIdentityM(anim.result, 0);
- anim.world = new float[16];
- Matrix.setIdentityM(anim.world, 0);
- long end = filePos + len;
- while (filePos < end) {
- int chunkID = ReadUnsignedShort();
- int chunkLen = ReadInt() - 6;
- switch (chunkID) {
- case CHUNK_HIERARCHY:
- anim.id = ReadUnsignedShort();
- break;
- case CHUNK_OBJNAME:
- String name = ChunkName(0);
- anim.light = scene.FindLight(name);
- anim.object = scene.FindObject(name);
- Skip(4);
- anim.parent = scene.FindAnimation(ReadUnsignedShort());
- break;
- case CHUNK_PIVOT:
- anim.pivot = new float[3];
- ChunkVector(anim.pivot, 0);
- break;
- case CHUNK_TRACKPOS:
- Skip(10);
- num = ReadInt();
- anim.position = new AnimKey[num];
- for (i = 0; i < num; i++) {
- anim.position[i] = new AnimKey();
- anim.position[i].time = ReadInt();
- k = ReadUnsignedShort();
- for (j = 0; j < 5; j++)
- if ((k & (1 << j)) != 0)
- Skip(4);
- anim.position[i].data = new float[3];
- ChunkVector(anim.position[i].data, 0);
- }
- break;
- case CHUNK_TRACKROT:
- Skip(10);
- num = ReadInt();
- anim.rotation = new AnimKey[num];
- for (i = 0; i < num; i++) {
- anim.rotation[i] = new AnimKey();
- anim.rotation[i].time = ReadInt();
- k = ReadUnsignedShort();
- for (j = 0; j < 5; j++)
- if ((k & (1 << j)) != 0)
- Skip(4);
- anim.rotation[i].data = new float[4];
- anim.rotation[i].data[3] = ReadFloat();
- ChunkVector(anim.rotation[i].data, 0);
- }
- break;
- case CHUNK_TRACKSCL:
- Skip(10);
- num = ReadInt();
- anim.scaling = new AnimKey[num];
- for (i = 0; i < num; i++) {
- anim.scaling[i] = new AnimKey();
- anim.scaling[i].time = ReadInt();
- k = ReadUnsignedShort();
- for (j = 0; j < 5; j++)
- if ((k & (1 << j)) != 0)
- Skip(4);
- anim.scaling[i].data = new float[3];
- ChunkVector(anim.scaling[i].data, 0);
- }
- break;
- default:
- Skip(chunkLen);
- }
- }
- Seek(end);
- return anim;
- }
- private void ChunkColor(int len, float[] color) throws IOException
- {
- long end = filePos + len;
- while (filePos < end) {
- int chunkID = ReadUnsignedShort();
- int chunkLen = ReadInt() - 6;
- switch (chunkID) {
- case CHUNK_RGBC:
- ChunkRGBC(color);
- break;
- case CHUNK_RGB24:
- ChunkRGB24(color);
- break;
- default:
- Skip(chunkLen);
- }
- }
- Seek(end);
- }
- private float ChunkPercent(int len) throws IOException
- {
- float v = 0;
- long end = filePos + len;
- while (filePos < end) {
- int chunkID = ReadUnsignedShort();
- int chunkLen = ReadInt() - 6;
- switch (chunkID) {
- case CHUNK_SHORT:
- v = ReadUnsignedShort() / 100.0f;
- break;
- default:
- Skip(chunkLen);
- }
- }
- Seek(end);
- return v;
- }
- private String ChunkName(int len) throws IOException
- {
- long end = filePos + len;
- int slen = 0;
- byte[] buffer = new byte[128];
- byte c;
- do {
- c = ReadByte();
- if (c != 0)
- buffer[slen++] = c;
- } while (c != 0);
- if (len != 0)
- Seek(end);
- String name = new String(buffer, 0, slen);
- return name;
- }
- private void ChunkVector(float[] vec, int offset) throws IOException
- {
- vec[offset + 0] = ReadFloat();
- vec[offset + 2] = ReadFloat();
- vec[offset + 1] = ReadFloat();
- }
- private void ChunkRGBC(float[] c) throws IOException
- {
- c[0] = ReadFloat();
- c[1] = ReadFloat();
- c[2] = ReadFloat();
- c[3] = 1;
- }
- private void ChunkRGB24(float[] c) throws IOException
- {
- c[0] = ReadUnsignedByte() / 255.0f;
- c[1] = ReadUnsignedByte() / 255.0f;
- c[2] = ReadUnsignedByte() / 255.0f;
- c[3] = 1;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement