Example #1
0
        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);
        }