private void saveJF3D(OpenGLModel model, IOStream os) { baos = new ByteArrayStream(); tmp = new byte[8]; int size; writeuint32(MAGIC); writeuint32(VERSION); writeuint32(ID_MODEL); size = 0; int tcnt = model.textures.Size(); for (int a = 0; a < tcnt; a++) { size += model.textures.Get(a).Length + 1; } writeuint32(size); writeuint32(tcnt); for (int a = 0; a < tcnt; a++) { writeString(model.textures.Get(a)); } for (int o = 0; o < model.ol.Size(); o++) { OpenGLObject obj = model.ol.Get(o); writeuint32(ID_OBJECT); int vcnt = obj.GetVertexCount() * 3; int pcnt = obj.GetPolyCount(); size = obj.GetName().Length + 1 + 4 + (4 * 3) + (4 + (vcnt * 4)) + (4 + (pcnt * 4)); writeuint32(size); writeString(obj.GetName()); writeuint32(obj.GetType()); writefloat(obj.GetOrigin().x); writefloat(obj.GetOrigin().y); writefloat(obj.GetOrigin().z); writeuint32(vcnt / 3); float[] xyz = obj.GetVertexBuffer(); for (int a = 0; a < vcnt; a++) { writefloat(xyz[a]); } switch (obj.GetType()) { case GL_TRIANGLES: writeuint32(pcnt / 3); break; case GL_QUADS: writeuint32(pcnt / 4); break; } int[] pts = obj.GetPolyBuffer(); for (int a = 0; a < pcnt; a++) { writeuint32(pts[a]); } int maps = obj.GetUVMaps().Size(); if (maps == 0) { Console.WriteLine("GL_JF3D:Warning:No UVMaps found for object:" + obj.GetName()); } for (int m = 0; m < maps; m++) { OpenGLUVMap map = obj.GetUVMaps().Get(m); writeuint32(ID_UVMAP); int uvcnt = map.GetUVCount() * 2; size = map.GetName().Length + 1 + 4 + (4 + (uvcnt * 4)); writeuint32(size); writeString(map.GetName()); writeuint32(map.GetTextureIndex()); writeuint32(uvcnt / 2); float[] uv = map.GetBuffer(); for (int a = 0; a < uvcnt; a++) { writefloat(uv[a]); } } } os.Write(baos.GetData().ToArray()); }
private void readObject(BlendChunk chunk) { List <BlendVertex> vertexList = new List <BlendVertex>(); List <int> loopList = new List <int>(); setData(chunk.raw); BlendObject bObj = new BlendObject(this); bObj.read(); // Console.WriteLine("bobject.type=" + bObj.type); if (bObj.type != 1) { return; //not a mesh bobject (could be camera, light, etc.) } obj = new OpenGLObject(); model.AddObject(obj); obj.SetName(bObj.id.name.Substring(2)); // Console.WriteLine("bobject=" + obj.name); chunk = findChunkByPtr(bObj.data); if (chunk == null) { throw new Exception("GL_BLEND:Unable to find Mesh for Object"); } BlendMesh mesh = new BlendMesh(this); setData(chunk.raw); // Console.WriteLine("Mesh@" + Int32.toString(raw.fileOffset, 16)); mesh.read(); obj.GetOrigin().x = bObj.loc[0]; org[0] = bObj.loc[0]; obj.GetOrigin().y = bObj.loc[1]; org[1] = bObj.loc[1]; obj.GetOrigin().z = bObj.loc[2]; org[2] = bObj.loc[2]; //find mvert chunk = findChunkByPtr(mesh.mvert); if (chunk == null) { throw new Exception("GL_BLEND:Unable to find MVert for Mesh"); } setData(chunk.raw); for (int a = 0; a < chunk.nr; a++) { BlendMVert mvert = new BlendMVert(this); mvert.read(); // obj.AddVertex(mvert.co); BlendVertex v = new BlendVertex(); v.xyz = mvert.v; vertexList.Add(v); } //find mloop chunk = findChunkByPtr(mesh.mloop); if (chunk == null) { throw new Exception("GL_BLEND:Unable to find MLoop for Mesh"); } setData(chunk.raw); for (int a = 0; a < chunk.nr; a++) { BlendMLoop mloop = new BlendMLoop(this); mloop.read(); loopList.Add(mloop.v); } //find mloopuv /* //use the UVMaps _in the CustomData instead - this fis only the active one * raw = findChunkByPtr(mesh.mloopuv); * if (raw == null) { * throw new Exception("GL_BLEND:Unable to find MLoopUV for Mesh"); * } * setData(raw.raw); * Console.WriteLine("MLoopUV:nr=" + raw.nr); * for(int a=0;a<raw.nr;a++) { * MLoopUV mloopuv = new MLoopUV(); * mloopuv.read(); * } */ //find mpoly chunk = findChunkByPtr(mesh.mpoly); if (chunk == null) { throw new Exception("GL_BLEND:Unable to find MPoly for Mesh"); } setData(chunk.raw); //TODO : calc which vertex needed to be dup'ed for each unique uv value (Blender does this _in their 3ds export script) int type = -1; int pcnt = -1; int vidx = 0; //MPoly = faces for (int a = 0; a < chunk.nr; a++) { BlendMPoly mpoly = new BlendMPoly(this); mpoly.read(); switch (mpoly.totloop) { case 3: if (type == GL_QUADS) { throw new Exception("GL_BLEND:Mixed QUADS/TRIANGLES not supported"); } type = GL_TRIANGLES; pcnt = 3; break; case 4: if (type == GL_TRIANGLES) { throw new Exception("GL_BLEND:Mixed QUADS/TRIANGLES not supported"); } type = GL_QUADS; pcnt = 4; break; default: throw new Exception("GL_BLEND:Polygon not supported:nr=" + mpoly.totloop); } int loopidx = mpoly.loopstart; for (int p = 0; p < pcnt; p++) { int idx = loopList.Get(loopidx++); obj.AddVertex(vertexList.Get(idx).xyz); obj.AddPoly(new int[] { vidx++ }); } } obj.SetType(type); //find customdata types readLayer(mesh.vdata.layers, "vdata"); readLayer(mesh.edata.layers, "edata"); readLayer(mesh.fdata.layers, "fdata"); readLayer(mesh.pdata.layers, "pdata"); readLayer(mesh.ldata.layers, "ldata"); }
private OpenGLModel loadJF3D(IOStream fis) { datapos = 0; fis.Open(OpenMode.ReadOnly); data = fis.ReadAll().ToArray(); int magic = readuint32(); if (magic != MAGIC) { throw new Exception("GL_JF3D:Not JF3D file"); } int version = readuint32(); if (version < VERSION) { throw new Exception("GL_JF3D:Bad version"); } int fcnt, pcnt, vcnt, uvcnt; OpenGLUVMap map; while (!eof()) { int head_id = readuint32(); int head_len = readuint32(); skip = head_len; int head_ver = head_id & 0xffff; head_id &= 0x7fff0000; switch (head_id) { case ID_MODEL: if (model != null) { throw new Exception("GL_JF3D:Multiple Model chunks found"); } model = new OpenGLModel(); fcnt = readuint32(); for (int a = 0; a < fcnt; a++) { String txt = readString(); model.textures.Add(txt); // Console.WriteLine("Texture=" + txt); } if (head_ver > 0) { //future reserved } break; case ID_OBJECT: obj = new OpenGLObject(); model.AddObject(obj); obj.SetName(readString()); obj.SetType(readuint32()); obj.GetOrigin().x = readfloat(); obj.GetOrigin().y = readfloat(); obj.GetOrigin().z = readfloat(); vcnt = readuint32(); //vertex count for (int v = 0; v < vcnt; v++) { float fx = readfloat(); float fy = readfloat(); float fz = readfloat(); obj.AddVertex(new float[] { fx, fy, fz }); } pcnt = readuint32(); //poly count switch (obj.GetType()) { case GL_TRIANGLES: pcnt *= 3; break; case GL_QUADS: pcnt *= 4; break; default: Console.WriteLine("GL_JF3D:Error Unknown GL Type:" + obj.GetType()); return(null); } for (int p = 0; p < pcnt; p++) { int pt = readuint32(); if (pt >= vcnt) { Console.WriteLine("Error:Poly includes invalid vertex !!!"); } obj.AddPoly(new int[] { pt }); } break; case ID_UVMAP: map = obj.CreateUVMap(); map.SetName(readString()); map.SetTextureIndex(readuint32()); uvcnt = readuint32(); if (uvcnt != obj.GetVertexCount()) { Console.WriteLine("Warning:UVMAP size != vertex count"); } for (int i = 0; i < uvcnt; i++) { float u = readfloat(); float v = readfloat(); map.Add(new float[] { u, v }); } break; default: break; } if (skip > 0) { datapos += skip; } } return(model); }
private OpenGLModel load3ds(IOStream fis) { OpenGLObject obj = null; int head_id; int head_len; int _siz; float[] _float; int[] _pts; bool done_vertex = false; bool done_pts = false; int vertexidx = -1; int vertexcnt = -1; String name; List <OpenGL3DS_Material> matlist; //materials (objects refer to material name) List <String> objlist; //object names (keyframe data refers to object name) String objname = ""; int objidx = -1; OpenGL3DS_Material mat; String matname = "", fn; int a, b, keys, u32; bool ok; int u16; OpenGLTranslate trans; OpenGLRotate rot; OpenGLScale scale; OpenGLModel mod; OpenGLUVMap map; int mapidx = -1; int skip = 0; int parent; int frameno; int s; datapos = 0; fis.Open(OpenMode.ReadOnly); data = fis.ReadAll().ToArray(); matlist = new List <OpenGL3DS_Material>(); objlist = new List <String>(); mod = new OpenGLModel(); while (!eof()) { head_id = readuint16(); head_len = readuint32(); if (head_len == -1) { break; //this does happen in some files } if (head_len < 6) { throw new Exception("head_len < 6 (" + head_len + ")"); //bad file } head_len -= 6; switch (head_id) { case 0x4d4d: //main chunk break; case 0x3d3d: //mesh chunk break; case 0xafff: //material chunk matname = ""; break; case 0xa000: //material chunk name matname = readname(head_len); break; case 0xa200: //texture details break; case 0xa300: //texture filename mat = new OpenGL3DS_Material(); fn = readname(head_len); mat.name = matname; mat.filename = fn; matlist.Add(mat); break; case 0x4000: //object chunk objname = readname(-1); //don't skip the whole chunk if (debug) { Console.WriteLine("obj=" + objname); } done_vertex = false; done_pts = false; break; case 0x4100: //triangular object chunk break; case 0x4110: //vertex list of a polygon skip = head_len; if (done_vertex) { Console.WriteLine("Warning : 2 vertex lists found for 1 object?"); break; } obj = new OpenGLObject(); obj.SetType(GL_TRIANGLES); //3ds only supports triangles obj.SetName(objname); mapidx = -1; mod.ol.Add(obj); objlist.Add(objname); _siz = readuint16(); skip -= 2; vertexidx = obj.GetVertexCount() * 3; vertexcnt = _siz; if (_siz == 0) { break; } _float = new float[_siz * 3]; for (a = 0; a < _siz; a++) { for (b = 0; b < 3; b++) { _float[a * 3 + b] = readfloat(); skip -= 4; } if (debug) { // Console.WriteLine(String.format("v=%3.3f,%3.3f,%3.3f", _float[a*3+0] , _float[a*3+1] , _float[a*3+2])); } } obj.AddVertex(_float); _float = null; done_vertex = true; break; case 0x4120: //Points list _siz = readuint16(); skip = _siz * 2 * 4; if (!done_vertex) { Console.WriteLine("Warning : pts list before vertex list?"); break; } if (done_pts) { Console.WriteLine("Warning : 2 pts lists found for 1 object?"); break; } if (_siz == 0) { break; } _pts = new int[3]; //p1,p2,p3,flgs per triangle for (a = 0; a < _siz; a++) { for (b = 0; b < 3; b++) { _pts[b] = (short)readuint16(); skip -= 2; } readuint16(); //skip flgs skip -= 2; obj.AddPoly(_pts); if (debug) { Console.WriteLine("p=" + _pts[0] + "," + _pts[1] + "," + _pts[2]); } } _pts = null; done_pts = true; break; case 0x4130: //object material name name = readname(head_len); mapidx++; map = obj.CreateUVMap(); map.SetName("uvmap" + mapidx); if (obj != null) { //find name in matlist ok = false; for (a = 0; a < matlist.Size(); a++) { if (matlist.Get(a).name.Equals(name)) { int idx = mod.AddTexture(matlist.Get(a).filename); map.SetTextureIndex(idx); ok = true; break; } } // if (!ok) throw new Exception("0x4130 : object material name not found in list : " + name); } if (debug) { Console.WriteLine("mat=" + map.GetTextureIndex()); } break; case 0x4140: //texture vertex list (UV) _siz = readuint16(); skip = _siz * 2 * 4; if (!done_vertex) { Console.WriteLine("Warning:Texture coords (UV) list before vertex list"); break; } if (_siz != vertexcnt) { Console.WriteLine("Warning:texture list siz != vertex list siz"); break; } if (_siz == 0) { break; } _float = new float[2]; for (a = 0; a < _siz; a++) { _float[0] = readfloat(); //U fis okay skip -= 4; _float[1] = 1.0f - readfloat(); //V must be inverted skip -= 4; obj.AddUV(_float, mapidx); if (debug) { // Console.WriteLine(String.format("t=%3.3f,%3.3f", _float[0] , _float[1])); } } _float = null; break; case 0x4160: //obj matrix //read in 3x3 matrix and show for now s = 0; //padding to convert to 4x4 matrix for (a = 0; a < 3 * 3; a++) { u32 = readuint32(); if ((a > 0) && (a % 3 == 0)) { s++; } //not sure what this matrix fis for??? But I don't seem to need it // obj.m.m[a+s] = readfloat(); // if (debug) Console.WriteLine("m=" + obj.m.m[a+s]); } obj.GetOrigin().x = readfloat(); obj.GetOrigin().y = readfloat(); obj.GetOrigin().z = readfloat(); if (debug) { Console.WriteLine("pos=" + obj.GetOrigin().x + "," + obj.GetOrigin().y + "," + obj.GetOrigin().z); } break; case 0xb000: //keyframe header break; case 0xb002: //object node chunk objidx = -1; break; case 0xb010: //keyframe object name name = readname(-1); readuint16(); //f1 readuint16(); //f2 parent = readuint16(); //parent //find name in objlist objidx = 0; ok = false; for (a = 0; a < objlist.Size(); a++) { if (objlist.Get(a).Equals(name)) { ok = true; break; } objidx++; } if (!ok) { objidx = -1; } else { obj = mod.ol.Get(objidx); if (parent != 65535) { obj.SetParent(parent); } obj = null; } //Console.WriteLine("0xb010 : name=" + name + ":objidx=" + objidx + ":parent=" + parent); break; case 0xb020: //keyframe pos skip = head_len; if (objidx == -1) { break; } obj = mod.ol.Get(objidx); u16 = readuint16(); //flgs skip -= 2; u32 = readuint32(); //r1 skip -= 4; u32 = readuint32(); //r2 skip -= 4; keys = readuint32(); //keys skip -= 4; _float = new float[3]; for (a = 0; a < keys; a++) { frameno = readuint32(); //frame # skip -= 4; u16 = readuint16(); //flgs skip -= 2; u32 = 0; if ((u16 & _3DS_FLG_TENSION) != 0) { u32++; } if ((u16 & _3DS_FLG_CONTINUITY) != 0) { u32++; } if ((u16 & _3DS_FLG_BIAS) != 0) { u32++; } if ((u16 & _3DS_FLG_EASE_TO) != 0) { u32++; } if ((u16 & _3DS_FLG_EASE_FROM) != 0) { u32++; } if (u32 > 0) { datapos += u32 * 4; //all ignored skip -= u32 * 4; } trans = new OpenGLTranslate(); for (b = 0; b < 3; b++) { _float[b] = readfloat(); skip -= 4; } trans.x = _float[0]; trans.y = _float[1]; trans.z = _float[2]; //Console.WriteLine("pos["+frameno+"]:"+pos.x+","+pos.y+","+pos.z+":flgs="+u16); obj.GetTranslateMap().Set(frameno, trans); if (obj.GetMaxFrameCount() < frameno) { obj.SetMaxFrameCount(frameno); } } _float = null; obj = null; break; case 0xb021: //keyframe rotate skip = head_len; if (objidx == -1) { break; } obj = mod.ol.Get(objidx); u16 = readuint16(); //flgs skip -= 2; u32 = readuint32(); //r1 skip -= 4; u32 = readuint32(); //r2 skip -= 4; keys = readuint32(); //keys skip -= 4; _float = new float[4]; for (a = 0; a < keys; a++) { frameno = readuint32(); //frame # skip -= 4; u16 = readuint16(); //flgs skip -= 2; u32 = 0; if ((u16 & _3DS_FLG_TENSION) != 0) { u32++; } if ((u16 & _3DS_FLG_CONTINUITY) != 0) { u32++; } if ((u16 & _3DS_FLG_BIAS) != 0) { u32++; } if ((u16 & _3DS_FLG_EASE_TO) != 0) { u32++; } if ((u16 & _3DS_FLG_EASE_FROM) != 0) { u32++; } if (u32 > 0) { datapos += u32 * 4; //all ignored skip -= u32 * 4; } rot = new OpenGLRotate(); for (b = 0; b < 4; b++) { _float[b] = readfloat(); skip -= 4; } rot.angle = _float[0] * 57.2957795f; //convert to degrees rot.x = _float[1]; rot.y = _float[2]; rot.z = _float[3]; //Console.WriteLine("rot["+frameno+"]:"+rot.angle+","+rot.x+","+rot.y+","+rot.z+":flgs="+u16); obj.GetRotateMap().Set(frameno, rot); if (obj.GetMaxFrameCount() < frameno) { obj.SetMaxFrameCount(frameno); } } _float = null; obj = null; break; case 0xb022: //keyframe scale skip = head_len; if (objidx == -1) { break; } obj = mod.ol.Get(objidx); u16 = readuint16(); //flgs skip -= 2; u32 = readuint32(); //r1 skip -= 4; u32 = readuint32(); //r2 skip -= 4; keys = readuint32(); //keys skip -= 4; _float = new float[3]; for (a = 0; a < keys; a++) { frameno = readuint32(); //frame # skip -= 4; u16 = readuint16(); //flgs skip -= 2; u32 = 0; if ((u16 & _3DS_FLG_TENSION) != 0) { u32++; } if ((u16 & _3DS_FLG_CONTINUITY) != 0) { u32++; } if ((u16 & _3DS_FLG_BIAS) != 0) { u32++; } if ((u16 & _3DS_FLG_EASE_TO) != 0) { u32++; } if ((u16 & _3DS_FLG_EASE_FROM) != 0) { u32++; } if (u32 > 0) { datapos += u32 * 4; //all ignored skip -= u32 * 4; } scale = new OpenGLScale(); for (b = 0; b < 3; b++) { _float[b] = readfloat(); skip -= 4; } scale.x = _float[0]; scale.y = _float[1]; scale.z = _float[2]; //Console.WriteLine("scale["+frameno+"]:"+scale.x+","+scale.y+","+scale.z+":flgs="+u16); obj.GetScaleMap().Set(frameno, scale); if (obj.GetMaxFrameCount() < frameno) { obj.SetMaxFrameCount(frameno); } } _float = null; obj = null; break; default: skip = head_len; break; } if (skip > 0) { datapos += skip; skip = 0; } } //setup any lights _siz = mod.ol.Size(); for (a = 0; a < _siz; a++) { obj = mod.ol.Get(a); } //delete temp lists matlist.Clear(); objlist.Clear(); return(mod); }