Esempio n. 1
0
        public override void Write(byte[] data, ref int offset)
        {
            int sortStatPosition = offset;

            PolymodelBuilder.SetShort(data, ref offset, 4); // SORTNORM opcode

            PolymodelBuilder.SetShort(data, ref offset, 0); // int n_points

            PolymodelBuilder.SetFixVector(data, ref offset, Normal);
            PolymodelBuilder.SetFixVector(data, ref offset, Point);

            int frontOffset = offset;

            PolymodelBuilder.SetShort(data, ref offset, 12345); // fix the back offset later

            int backOffset = offset;

            PolymodelBuilder.SetShort(data, ref offset, 12345); // fix the front offset later

            // End
            PolymodelBuilder.SetShort(data, ref offset, ModelOpCode.End); // END opcode

            // Front
            int frontOffsetValue = offset - sortStatPosition;

            FrontInstruction.Write(data, ref offset);

            // Back
            int backOffsetValue = offset - sortStatPosition;

            BackInstruction.Write(data, ref offset);

            // store current position
            int endPosition = offset;

            if (frontOffsetValue > short.MaxValue || backOffsetValue > short.MaxValue)
            {
                throw new ArgumentException("Model is too complex: 32KB displacement limit exceeded when compiling subobjects.");
            }

            offset = frontOffset;
            PolymodelBuilder.SetShort(data, ref offset, (short)frontOffsetValue);

            offset = backOffset;
            PolymodelBuilder.SetShort(data, ref offset, (short)backOffsetValue);

            // Return
            offset = endPosition;
        }
Esempio n. 2
0
        public void CompileInterpreterData(int vertexOffset)
        {
            if (mCompiled)
            {
                return;
            }

            mCompiled = true;
            //one MB of scratch space
            byte[] data   = new byte[1024 * 1024];
            int    offset = 0;

            vertexDict = new Dictionary <FixVector, int>();

            PolymodelBuilder.SetShort(data, ref offset, ModelOpCode.DefinePointStart);

            //Get all points
            //An ordered set would be great here...
            mVertexOffset = vertexOffset;
            GetVertexes(RootNode, data);

            PolymodelBuilder.SetShort(data, ref offset, (short)vertexDict.Count); //Number of points
            PolymodelBuilder.SetShort(data, ref offset, (short)vertexOffset);     //Offset into the vertex list
            PolymodelBuilder.SetShort(data, ref offset, 0);                       //Padding

            NumVertices += vertexDict.Count;

            Console.WriteLine("Subobject generated {0} unique vertices", vertexDict.Count);

            foreach (var point in vertexDict.Keys)
            {
                PolymodelBuilder.SetFixVector(data, ref offset, point);
            }

            // Get faces
            GetFaces(RootNode, data, ref offset);

            InterpreterData = data.Take(offset).ToArray();
        }
Esempio n. 3
0
        public override void Write(byte[] data, ref int offset)
        {
            int index = SubModel.ID;

            int offsetBase = offset;

            PolymodelBuilder.SetShort(data, ref offset, ModelOpCode.SubCall);

            short submodelNum = (short)(index);

            PolymodelBuilder.SetShort(data, ref offset, submodelNum);

            FixVector submodelOffset = SubModel.Offset;

            PolymodelBuilder.SetFixVector(data, ref offset, submodelOffset);

            //The address where we write the new offset value
            int   offsetAddress = offset;
            short offsetValue   = 0;

            PolymodelBuilder.SetShort(data, ref offset, offsetValue);
            offset += 2;

            //Subcall is immediately followed with the end op code
            PolymodelBuilder.SetShort(data, ref offset, ModelOpCode.End);

            // Calculate the new offset
            offsetValue = (short)(offset - offsetBase);

            Instruction.Write(data, ref offset);

            // Store offset
            var endOffset = offset;

            offset = offsetAddress;
            PolymodelBuilder.SetShort(data, ref offset, (short)offsetValue);

            offset = endOffset;
        }
Esempio n. 4
0
        public void GetFaces(BSPNode node, byte[] data, ref int modelDataOffset)
        {
            if (node == null)
            {
                return;
            }

            if (node.Front == null && node.Back != null)
            {
                throw new Exception("ModelData::GetFaces: Front is null but back isn't.");
            }
            else if (node.Front != null && node.Back == null)
            {
                throw new Exception("ModelData::GetFaces: Back is null but front isn't.");
            }

            if (node.Front != null && node.Back != null)
            {
                if (node.Point.X == node.Point.Y && node.Point.Y == node.Point.Z && node.Point.Z == 0.0f)
                {
                    //TODO: figure out if this is actually an error condition.
                    throw new Exception("ModelData::GetFaces: splitter point is 0 but this probably isn't a problem. Probably.");
                }

                // Sort start
                int sortStatPosition = modelDataOffset;

                PolymodelBuilder.SetShort(data, ref modelDataOffset, 4); // SORTNORM opcode

                PolymodelBuilder.SetShort(data, ref modelDataOffset, 0); // int n_points

                FixVector normal = new FixVector(node.Normal.X, node.Normal.Y, node.Normal.Z);
                FixVector point  = new FixVector(node.Point.X, node.Point.Y, node.Point.Z);

                PolymodelBuilder.SetFixVector(data, ref modelDataOffset, normal);
                PolymodelBuilder.SetFixVector(data, ref modelDataOffset, point);

                int backOffset = modelDataOffset;
                PolymodelBuilder.SetShort(data, ref modelDataOffset, (short)backOffset); // fix the back offset later

                int frontOffset = modelDataOffset;
                PolymodelBuilder.SetShort(data, ref modelDataOffset, (short)frontOffset); // fix the front offset later

                // Terminator opcode
                PolymodelBuilder.SetShort(data, ref modelDataOffset, ModelOpCode.End);

                // Process front and store offset
                int frontOffsetValue = modelDataOffset - sortStatPosition;
                GetFaces(node.Front, data, ref modelDataOffset);

                // Process back and store offset
                int backOffsetValue = modelDataOffset - sortStatPosition;
                GetFaces(node.Back, data, ref modelDataOffset);


                // Store the end position
                int endPosition = modelDataOffset;

                if (frontOffsetValue > short.MaxValue || backOffsetValue > short.MaxValue || modelDataOffset < 0)
                {
                    throw new ArgumentException("Model is too complex: 32KB displacement limit exceeded.");
                }

                // Correct the back offset
                modelDataOffset = backOffset;
                PolymodelBuilder.SetShort(data, ref modelDataOffset, (short)frontOffsetValue); // fix the back offset later

                // Correct the front offset
                modelDataOffset = frontOffset;
                PolymodelBuilder.SetShort(data, ref modelDataOffset, (short)backOffsetValue); // fix the back offset later


                // Restore the offset to the end position
                modelDataOffset = endPosition;

                if (node.faces != null && node.faces.Any())
                {
                    throw new Exception("Missing faces!");
                }
            }
            else if (node.faces != null)
            {
                int       facesStatPosition = modelDataOffset;
                BSPVertex vert;
                short     vertexNum;
                foreach (var face in node.faces)
                {
                    if (face.TextureID == -1)
                    {
                        // Flat poly opcode
                        PolymodelBuilder.SetShort(data, ref modelDataOffset, ModelOpCode.FlatPoly);

                        short pointc = (short)face.Points.Count();
                        PolymodelBuilder.SetShort(data, ref modelDataOffset, pointc);

                        Fix x = face.Point.X;
                        Fix y = face.Point.Y;
                        Fix z = face.Point.Z;

                        var facePoint = new FixVector(x, y, z);

                        PolymodelBuilder.SetFixVector(data, ref modelDataOffset, facePoint);

                        x = face.Normal.X;
                        y = face.Normal.Y;
                        z = face.Normal.Z;

                        var normal = new FixVector(x, y, z);

                        PolymodelBuilder.SetFixVector(data, ref modelDataOffset, normal);
                        PolymodelBuilder.SetShort(data, ref modelDataOffset, (short)face.Color);
                        for (short i = 0; i < pointc; i++)
                        {
                            vert = face.Points[i];
                            FixVector vec = new FixVector(vert.Point.X, vert.Point.Y, vert.Point.Z);
                            vertexNum = (short)vertexDict[vec];
                            PolymodelBuilder.SetShort(data, ref modelDataOffset, vertexNum);
                        }

                        if (pointc % 2 == 0)
                        {
                            PolymodelBuilder.SetShort(data, ref modelDataOffset, 0);
                        }
                    }
                    else
                    {
                        // tmapped poly opcode
                        PolymodelBuilder.SetShort(data, ref modelDataOffset, ModelOpCode.TexturedPoly);

                        short pointc = (short)face.Points.Count();
                        PolymodelBuilder.SetShort(data, ref modelDataOffset, pointc);

                        Fix x = face.Point.X;
                        Fix y = face.Point.Y;
                        Fix z = face.Point.Z;

                        var facePoint = new FixVector(x, y, z);

                        PolymodelBuilder.SetFixVector(data, ref modelDataOffset, facePoint);

                        x = face.Normal.X;
                        y = face.Normal.Y;
                        z = face.Normal.Z;

                        var normal = new FixVector(x, y, z);

                        PolymodelBuilder.SetFixVector(data, ref modelDataOffset, normal);

                        PolymodelBuilder.SetShort(data, ref modelDataOffset, (short)face.TextureID);

                        for (short i = 0; i < pointc; i++)
                        {
                            vert = face.Points[i];
                            FixVector vec = new FixVector(vert.Point.X, vert.Point.Y, vert.Point.Z);
                            vertexNum = (short)vertexDict[vec];
                            PolymodelBuilder.SetShort(data, ref modelDataOffset, vertexNum);
                        }

                        if (pointc % 2 == 0)
                        {
                            PolymodelBuilder.SetShort(data, ref modelDataOffset, 0);
                        }

                        for (short i = 0; i < pointc; i++)
                        {
                            x = face.Points[i].UVs.X;
                            y = face.Points[i].UVs.Y;
                            z = face.Points[i].UVs.Z;

                            var uv = new FixVector(x, y, z);

                            PolymodelBuilder.SetFixVector(data, ref modelDataOffset, uv);
                        }
                    }
                }

                PolymodelBuilder.SetShort(data, ref modelDataOffset, ModelOpCode.End);
            }
        }