private IVisualizationWireframe GenerateWireframe(ReadOnlyDictionary <string, object> parms) { int offset = Util.GetFromObjDict(parms, P_OFFSET, 0); if (offset < 0 || offset >= mFileData.Length) { // should be caught by editor mAppRef.ReportError("Invalid parameter"); return(null); } VisWireframe vw = new VisWireframe(); const sbyte END_MARKER = -128; // 0x80 try { while (true) { int vx = (sbyte)mFileData[offset++]; if (vx == END_MARKER) { break; } int vy = (sbyte)mFileData[offset++]; int vz = (sbyte)mFileData[offset++]; vw.AddVertex(vx, vy, vz); } while (true) { int v0 = (sbyte)mFileData[offset++]; if (v0 == END_MARKER) { break; } int v1 = mFileData[offset++]; int f0 = mFileData[offset++]; int f1 = mFileData[offset++]; int edge = vw.AddEdge(v0, v1); vw.AddEdgeFace(edge, f0); if (f1 != f0) { vw.AddEdgeFace(edge, f1); } } while (true) { int nx = (sbyte)mFileData[offset++]; if (nx == END_MARKER) { break; } int ny = (sbyte)mFileData[offset++]; int nz = (sbyte)mFileData[offset++]; vw.AddFaceNormal(nx, ny, nz); } } catch (IndexOutOfRangeException) { // assume it was our file data access that caused the failure mAppRef.ReportError("Ran off end of file"); return(null); } string msg; if (!vw.Validate(out msg)) { mAppRef.ReportError("Data error: " + msg); return(null); } return(vw); }
private IVisualizationWireframe GenerateWireframe(ReadOnlyDictionary <string, object> parms) { int offset = Util.GetFromObjDict(parms, P_OFFSET, 0); int lodDist = Util.GetFromObjDict(parms, P_LOD_DISTANCE, DEFAULT_LOD_DIST); bool doFixNormals = Util.GetFromObjDict(parms, P_DO_FIX_NORMALS, true); bool doCullVertices = Util.GetFromObjDict(parms, P_DO_CULL_VERTICES, false); if (offset < 0 || offset >= mFileData.Length) { // should be caught by editor mAppRef.ReportError("Invalid parameter"); return(null); } VisWireframe vw = new VisWireframe(); try { int edgeOffset = offset + (short)(mFileData[offset + 0x03] | (mFileData[offset + 0x10] << 8)); int faceOffset = offset + (short)(mFileData[offset + 0x04] | (mFileData[offset + 0x11] << 8)); int vertexCount = mFileData[offset + 0x08] / 6; int edgeCount = mFileData[offset + 0x09]; int faceCount = mFileData[offset + 0x0c] / 4; //mAppRef.DebugLog("MESH vc=" + vertexCount + " ec=" + edgeCount + " fc=" + faceCount + // " eoff=" + edgeOffset + " foff=" + faceOffset); int vertexOffset = offset + 0x14; for (int i = 0; i < vertexCount; i++) { int xc = mFileData[vertexOffset++]; int yc = mFileData[vertexOffset++]; int zc = mFileData[vertexOffset++]; byte flags = mFileData[vertexOffset++]; byte faces0 = mFileData[vertexOffset++]; byte faces1 = mFileData[vertexOffset++]; if ((flags & 0x80) != 0) { xc = -xc; } if ((flags & 0x40) != 0) { yc = -yc; } if ((flags & 0x20) != 0) { zc = -zc; } int visThresh = flags & 0x1f; if (TURN_TO_FRONT) { xc = -xc; zc = -zc; } int vindex = vw.AddVertex(xc, yc, zc); if (doCullVertices) { AddVertexFace(vw, vindex, faces0 & 0x0f, faceCount); AddVertexFace(vw, vindex, faces0 >> 4, faceCount); AddVertexFace(vw, vindex, faces1 & 0x0f, faceCount); AddVertexFace(vw, vindex, faces1 >> 4, faceCount); } if (visThresh < lodDist) { vw.AddVertexExclusion(vindex); } //mAppRef.DebugLog("v" + i + " " + xc + "," + yc + "," + zc + // " :: " + (faces0 & 0x0f) + "," + (faces0 >> 4) + "," + // (faces1 & 0x0f) + "," + (faces1 >> 4)); } for (int i = 0; i < edgeCount; i++) { byte flags = mFileData[edgeOffset++]; byte faces = mFileData[edgeOffset++]; byte v0 = mFileData[edgeOffset++]; byte v1 = mFileData[edgeOffset++]; int visThresh = flags & 0x1f; int eindex = vw.AddEdge(v0 / 4, v1 / 4); AddEdgeFace(vw, eindex, faces & 0x0f, faceCount); AddEdgeFace(vw, eindex, faces >> 4, faceCount); if (visThresh < lodDist) { vw.AddEdgeExclusion(eindex); } //mAppRef.DebugLog("E" + i + " " + (v0 / 4) + "," + (v1 / 4) + // " :: " + (faces & 0x0f) + "," + (faces >> 4)); } for (int i = 0; i < faceCount; i++) { byte flags = mFileData[faceOffset++]; int xc = mFileData[faceOffset++]; int yc = mFileData[faceOffset++]; int zc = mFileData[faceOffset++]; if ((flags & 0x80) != 0) { xc = -xc; } if ((flags & 0x40) != 0) { yc = -yc; } if ((flags & 0x20) != 0) { zc = -zc; } if (TURN_TO_FRONT) { xc = -xc; zc = -zc; } //int visThresh = flags & 0x1f; // We don't handle the face visibility threshold, which is only used // for the "plate / alloys" hull to disable BFC. if (new Vector3(xc, yc, zc).Magnitude() == 0) { // We have two choices: // (1) Add a placeholder (say, [0,0,1]). Causes the renderer to // get confused if there's no vertex for the face. // (2) Drop it, as it's clearly not used. Potentially problematic if // there are other faces that *are* used, because we throw the // indices off by one. // So far this only seems to be a thing for "plate / alloys" which // doesn't do BFC, so I'm taking approach #2. } else { vw.AddFaceNormal(xc, yc, zc); } //mAppRef.DebugLog("F" + i + " " + xc + "," + yc + "," + zc); } } catch (IndexOutOfRangeException) { // assume it was our file data access that caused the failure mAppRef.ReportError("Ran off end of file"); return(null); } string msg; if (!vw.Validate(out msg)) { mAppRef.ReportError("Data error: " + msg); return(null); } if (doFixNormals) { FixNormals(vw, offset); } return(vw); }