Esempio n. 1
0
        public void DrawMeshDebugLines(BaseMesh mesh, Transform transform, List<Vector3> overrideVertices,
            List<Vector3> overrideNormals, Render render)
        {
            if(render.drawNormals)
            {
                SetColor(0.8f, 0.0f, 0.9f);
                if(overrideVertices.Any())
                {
                    for (var i = 0; i < mesh.Vertices.Count; i++)
                    {
                        var ov = overrideVertices[i];
                        var on = overrideNormals[i];

                        var v = transform * ov;
                        buffer.Add(v.ToArray());
                        buffer.Add(color);
                        v += transform.Basis.MultiplyByVector(on) * 128;
                        buffer.Add(v.ToArray());
                        buffer.Add(color);
                    }
                }
                else
                {
                    foreach (var mv in mesh.Vertices)
                    {
                        var v = transform * mv.Position;
                        buffer.Add(v.ToArray());
                        buffer.Add(color);
                        v += transform.Basis.MultiplyByVector(mv.Normal) * 128;
                        buffer.Add(v.ToArray());
                        buffer.Add(color);
                    }
                }
            }
        }
Esempio n. 2
0
 public static void tr_setupTexturedFace(Mesh trMesh, BaseMesh mesh, ushort[] vertexIndices, Polygon p)
 {
     if (trMesh.Lights.Length == trMesh.Vertices.Length)
     {
         for (var i = 0; i < p.Vertices.Count; i++)
         {
             p.Vertices[i].Color[0] = 1.0f - trMesh.Lights[vertexIndices[i]] / 8192.0f;
             p.Vertices[i].Color[1] = 1.0f - trMesh.Lights[vertexIndices[i]] / 8192.0f;
             p.Vertices[i].Color[2] = 1.0f - trMesh.Lights[vertexIndices[i]] / 8192.0f;
             p.Vertices[i].Color[3] = 1.0f;
         }
     }
     else
     {
         foreach (var v in p.Vertices)
         {
             v.Color = new float[] {1, 1, 1, 1};
         }
     }
 }
Esempio n. 3
0
        public void RenderMesh(BaseMesh mesh)
        {
            if(mesh.AllAnimatedElements.Any())
            {
                // Respecify the tex coord buffer
                GL.BindBuffer(BufferTarget.ArrayBuffer, mesh.AnimatedVBOTexCoordArray);
                // Tell OpenGL to discard the old values
                GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(mesh.AnimatedVertices.Count * 2 * sizeof(float)), IntPtr.Zero, BufferUsageHint.StreamDraw);

                unsafe
                {
                    // Get writable data (to avoid copy)
                    var data = (float*) GL.MapBuffer(BufferTarget.ArrayBuffer, BufferAccess.WriteOnly);

                    var offset = 0;
                    foreach (var p in mesh.Polygons)
                    {
                        if(p.AnimID == 0 || p.IsBroken)
                        {
                            continue;
                        }

                        var seq = EngineWorld.AnimSequences[p.AnimID - 1];

                        var frame = (seq.CurrentFrame + p.FrameOffset) % seq.Frames.Count;
                        var tf = seq.Frames[frame];
                        foreach (var vert in p.Vertices)
                        {
                            var v = vert.TexCoord;
                            data[offset + 0] = tf.Mat[0 + 0 * 2] * v[0] + tf.Mat[0 + 1 * 2] * v[1] + tf.Move[0];
                            data[offset + 1] = tf.Mat[1 + 0 * 2] * v[0] + tf.Mat[1 + 1 * 2] * v[1] + tf.Move[1];

                            offset += 2;
                        }
                    }
                    GL.UnmapBuffer(BufferTarget.ArrayBuffer);
                }

                if(mesh.AnimatedElementCount > 0)
                {
                    mesh.AnimatedVertexArray.Bind();

                    GL.BindTexture(TextureTarget.Texture2D, World.Textures[0]);
                    GL.DrawElements(PrimitiveType.Triangles, (int)mesh.AnimatedElementCount, DrawElementsType.UnsignedInt, IntPtr.Zero);
                }
            }

            if(mesh.Vertices.Any())
            {
                mesh.MainVertexArray.Bind();

                var elementsbase = IntPtr.Zero;

                var offset = 0;
                for (var texture = 0; texture < mesh.TexturePageCount; texture++)
                {
                    if(mesh.ElementsPerTexture[texture] == 0)
                    {
                        continue;
                    }

                    GL.BindTexture(TextureTarget.Texture2D, World.Textures[texture]);
                    mesh.MainVertexArray.Bind();
                    GL.DrawElements(PrimitiveType.Triangles, (int)mesh.ElementsPerTexture[texture], DrawElementsType.UnsignedInt, elementsbase + offset);
                    offset += (int)mesh.ElementsPerTexture[texture];
                }
            }
        }
Esempio n. 4
0
        public static void tr_accumulateNormals(Mesh trMesh, BaseMesh mesh, int numCorners, ushort[] vertexIndices, Polygon p)
        {
            p.Vertices.Resize(numCorners, () => new Vertex());

            for (var i = 0; i < numCorners; i++)
            {
                p.Vertices[i].Position = trMesh.Vertices[vertexIndices[i]].ToVector3();
            }
            p.FindNormal();

            for (var i = 0; i < numCorners; i++)
            {
                mesh.Vertices[vertexIndices[i]].Normal += p.Plane.Normal;
            }
        }
Esempio n. 5
0
        public static void tr_setupColoredFace(Mesh trMesh, Level tr, BaseMesh mesh, ushort[] vertexIndices, int color,
            Polygon p)
        {
            var tmp = trMesh.Lights.Length == trMesh.Vertices.Length;
            for (var i = 0; i < p.Vertices.Count; i++)
            {
                p.Vertices[i].Color[0] = tr.Palette.Colour[color].R / 255.0f;
                p.Vertices[i].Color[1] = tr.Palette.Colour[color].G / 255.0f;
                p.Vertices[i].Color[2] = tr.Palette.Colour[color].B / 255.0f;
                if(tmp)
                {
                    p.Vertices[i].Color[0] = p.Vertices[i].Color[0] * 1.0f - trMesh.Lights[vertexIndices[i]] / 8192.0f;
                    p.Vertices[i].Color[1] = p.Vertices[i].Color[1] * 1.0f - trMesh.Lights[vertexIndices[i]] / 8192.0f;
                    p.Vertices[i].Color[2] = p.Vertices[i].Color[2] * 1.0f - trMesh.Lights[vertexIndices[i]] / 8192.0f;
                }
                p.Vertices[i].Color[3] = 1.0f;

                p.Vertices[i].TexCoord[0] = (i & 2) == 2 ? 1.0f : 0.0f;
                p.Vertices[i].TexCoord[1] = i >= 2 ? 1.0f : 0.0f;
            }
            mesh.UsesVertexColors = true;
        }
Esempio n. 6
0
        public static void tr_setupRoomVertices(World world, Level tr, Loader.Room tr_room, BaseMesh mesh,
            int numCorners, ushort[] vertices, ushort masked_texture, Polygon p)
        {
            p.Vertices.Resize(numCorners, () => new Vertex());

            for (var i = 0; i < numCorners; i++)
            {
                p.Vertices[i].Position = tr_room.Vertices[vertices[i]].Vertex.ToVector3();
            }
            p.FindNormal();

            for (var i = 0; i < numCorners; i++)
            {
                mesh.Vertices[vertices[i]].Normal += p.Plane.Normal;
                p.Vertices[i].Normal = p.Plane.Normal;
                p.Vertices[i].Color = TR_color_to_arr(tr_room.Vertices[vertices[i]].Color);
            }

            var tex = tr.ObjectTextures[masked_texture];
            SetAnimTexture(p, masked_texture, world);
            p.BlendMode = tex.TransparencyFlags;

            world.TextureAtlas.GetCoordinates(masked_texture, false, p);
        }
Esempio n. 7
0
 public static void tr_copyNormals(Polygon polygon, BaseMesh mesh, ushort[] mesh_vertex_indices)
 {
     for (var i = 0; i < polygon.Vertices.Count; i++)
     {
         polygon.Vertices[i].Normal = mesh.Vertices[mesh_vertex_indices[i]].Normal;
     }
 }
Esempio n. 8
0
        public static void TR_GenMesh(World world, int mesh_index, BaseMesh mesh, Level tr)
        {
            var texMask = world.EngineVersion == Loader.Engine.TR4 ? TextureIndexMaskTr4 : TextureIndexMask;

            /* TR WAD FORMAT DOCUMENTATION!
             * tr4_face[3,4]_t:
             * flipped texture & 0x8000 (1 bit  ) - horizontal flipping.
             * shape texture   & 0x7000 (3 bits ) - texture sample shape.
             * index texture   & $0FFF  (12 bits) - texture sample index.
             *
             * if bit [15] is set, as in ( texture and $8000 ), it indicates that the texture
             * sample must be flipped horizontally prior to be used.
             * Bits [14..12] as in ( texture and $7000 ), are used to store the texture
             * shape, given by: ( texture and $7000 ) shr 12.
             * The valid values are: 0, 2, 4, 6, 7, as assigned to a square starting from
             * the top-left corner and going clockwise: 0, 2, 4, 6 represent the positions
             * of the square angle of the triangles, 7 represents a quad.
             */

            var trMesh = tr.Meshes[mesh_index];
            mesh.ID = (uint)mesh_index;
            mesh.Center.X = trMesh.Centre.X;
            mesh.Center.Y = trMesh.Centre.Z;
            mesh.Center.Z = trMesh.Centre.Y;
            mesh.Radius = trMesh.CollisionSize;
            mesh.TexturePageCount = world.TextureAtlas.NumAtlasPages + 1;

            mesh.Vertices.Resize(trMesh.Vertices.Length, () => new Vertex());
            for (var i = 0; i < mesh.Vertices.Count; i++)
            {
                mesh.Vertices[i].Position = trMesh.Vertices[i].ToVector3();
                mesh.Vertices[i].Normal = Vector3.Zero; // paranoid
            }
            
            mesh.FindBB();

            mesh.Polygons.Clear();

            // textured triangles
            foreach (var face3 in trMesh.TexturedTriangles)
            {
                var p = new Polygon();

                var tex = tr.ObjectTextures[face3.Texture & texMask];

                p.DoubleSide = face3.Texture >> 15 != 0; // CORRECT, BUT WRONG IN TR3-5

                SetAnimTexture(p, (uint)face3.Texture & texMask, world);

                p.BlendMode = face3.Lighting.HasFlagUns(0x01) ? BlendingMode.Multiply : tex.TransparencyFlags;

                tr_accumulateNormals(trMesh, mesh, 3, face3.Vertices, p);
                tr_setupTexturedFace(trMesh, mesh, face3.Vertices, p);

                world.TextureAtlas.GetCoordinates((uint) face3.Texture & texMask, false, p);

                mesh.Polygons.Add(p);
            }

            // coloured triangles
            foreach (var face3 in trMesh.ColouredTriangles)
            {
                var p = new Polygon();

                var col = face3.Texture & 0xff;
                p.TexIndex = (ushort)world.TextureAtlas.NumAtlasPages;
                p.BlendMode = BlendingMode.Opaque;
                p.AnimID = 0;

                tr_accumulateNormals(trMesh, mesh, 3, face3.Vertices, p);
                tr_setupColoredFace(trMesh, tr, mesh, face3.Vertices, col, p);

                mesh.Polygons.Add(p);
            }

            // textured rectangles
            foreach (var face4 in trMesh.TexturedRectangles)
            {
                var p = new Polygon();

                var tex = tr.ObjectTextures[face4.Texture & texMask];

                p.DoubleSide = face4.Texture >> 15 != 0; // CORRECT, BUT WRONG IN TR3-5

                SetAnimTexture(p, (uint)face4.Texture & texMask, world);

                p.BlendMode = face4.Lighting.HasFlagUns(0x01) ? BlendingMode.Multiply : tex.TransparencyFlags;

                tr_accumulateNormals(trMesh, mesh, 4, face4.Vertices, p);
                tr_setupTexturedFace(trMesh, mesh, face4.Vertices, p);

                world.TextureAtlas.GetCoordinates((uint)face4.Texture & texMask, false, p);

                mesh.Polygons.Add(p);
            }

            // coloured rectangles
            foreach (var face4 in trMesh.ColouredRectangles)
            {
                var p = new Polygon();

                var col = face4.Texture & 0xff;
                p.TexIndex = (ushort)world.TextureAtlas.NumAtlasPages;
                p.BlendMode = BlendingMode.Opaque;
                p.AnimID = 0;

                tr_accumulateNormals(trMesh, mesh, 4, face4.Vertices, p);
                tr_setupColoredFace(trMesh, tr, mesh, face4.Vertices, col, p);

                mesh.Polygons.Add(p);
            }

            // let us normalise normals %)
            foreach (var v in mesh.Vertices)
            {
                v.Normal = v.Normal.SafeNormalize();
            }

            // triangles
            var j = 0;
            for (var i = 0; i < trMesh.TexturedTriangles.Length; i++, j++)
            {
                tr_copyNormals(mesh.Polygons[j], mesh, trMesh.TexturedTriangles[i].Vertices);
            }

            for (var i = 0; i < trMesh.ColouredTriangles.Length; i++, j++)
            {
                tr_copyNormals(mesh.Polygons[j], mesh, trMesh.ColouredTriangles[i].Vertices);
            }

            // triangles
            for (var i = 0; i < trMesh.TexturedRectangles.Length; i++, j++)
            {
                tr_copyNormals(mesh.Polygons[j], mesh, trMesh.TexturedRectangles[i].Vertices);
            }

            for (var i = 0; i < trMesh.ColouredRectangles.Length; i++, j++)
            {
                tr_copyNormals(mesh.Polygons[j], mesh, trMesh.ColouredRectangles[i].Vertices);
            }

            mesh.Vertices.Clear();
            mesh.GenFaces();
            mesh.PolySortInMesh();
        }
Esempio n. 9
0
        private void createHairMesh(SkeletalModel model)
        {
            Mesh = new BaseMesh();
            Mesh.ElementsPerTexture.Resize(EngineWorld.Textures.Count);
            var totalElements = 0;

            // Gather size information
            for (var i = 0; i < model.MeshCount; i++)
            {
                var original = model.MeshTree[i].MeshBase;

                Mesh.TexturePageCount = Math.Max(Mesh.TexturePageCount, original.TexturePageCount);

                for (var j = 0; j < original.TexturePageCount; j++)
                {
                    Mesh.ElementsPerTexture[j] += original.ElementsPerTexture[j];
                    totalElements += (int) original.ElementsPerTexture[j];
                }
            }

            // Create arrays
            Mesh.Elements.Resize(totalElements);

            // - with matrix index information
            Mesh.MatrixIndices.Resize(Mesh.Vertices.Count, () => new BaseMesh.MatrixIndex());

            // Copy information
            var elementsStartPerTexture = new List<uint>();
            elementsStartPerTexture.Resize((int)Mesh.TexturePageCount);
            Mesh.Vertices.Clear();
            for (var i = 0; i < model.MeshCount; i++)
            {
                var original = model.MeshTree[i].MeshBase;

                // Copy vertices
                var verticesStart = Mesh.Vertices.Count; // TODO: Wut... size == 0 (cf. L328)
                Mesh.Vertices.AddRange(original.Vertices);

                // Copy elements
                var originalElementsStart = 0;
                for (var page = 0; page < original.TexturePageCount; page++)
                {
                    if (original.ElementsPerTexture[page] == 0)
                        continue;

                    Assert(originalElementsStart < original.Elements.Count);
                    Assert(originalElementsStart + original.ElementsPerTexture[page] <= original.Elements.Count);

                    Assert(elementsStartPerTexture[page] < Mesh.Elements.Count);
                    Assert(elementsStartPerTexture[page] + original.ElementsPerTexture[page] <= Mesh.Elements.Count);

                    Helper.ListCopy(original.Elements, originalElementsStart, Mesh.Elements,
                        (int) elementsStartPerTexture[page], (int) original.ElementsPerTexture[page]);

                    for (var j = 0; j < original.ElementsPerTexture[page]; j++)
                    {
                        Mesh.Elements[(int) elementsStartPerTexture[page]] =
                            (uint) (verticesStart + original.Elements[originalElementsStart]);
                        originalElementsStart++;
                        elementsStartPerTexture[page]++;
                    }
                }

                // Apply total offset from parent.
                // The resulting mesh will have all the hair in default position
                // (i.e. as one big rope). The shader and matrix then transform it
                // correctly.
                Elements[i].Position = model.MeshTree[i].Offset;
                if(i > 0)
                {
                    // TODO: This assumes the parent is always the preceding mesh.
                    // True for hair, obviously wrong for everything else. Can stay
                    // here, but must go when we start generalizing the whole thing.
                    Elements[i].Position += Elements[i - 1].Position;
                }

                // And create vertex data (including matrix indices)
                for (var j = 0; j < original.Vertices.Count; j++)
                {
                    Mesh.MatrixIndices.Add(new BaseMesh.MatrixIndex());
                    Assert(Mesh.MatrixIndices.Count > verticesStart + j);
                    if (original.Vertices[j].Position[1] <= 0)
                    {
                        Mesh.MatrixIndices[verticesStart + j].I = (sbyte) i;
                        Mesh.MatrixIndices[verticesStart + j].J = (sbyte) (i + 1);
                    }
                    else
                    {
                        Mesh.MatrixIndices[verticesStart + j].I = (sbyte) (i + 1);
                        Mesh.MatrixIndices[verticesStart + j].J = Math.Min((sbyte) (i + 2), (sbyte) model.MeshCount);
                    }

                    // Now move all the hair vertices
                    Mesh.Vertices[verticesStart + j].Position += Elements[i].Position;

                    // If the normal isn't fully in y direction, cancel its y component
                    // This is perhaps a bit dubious.
                    if (Mesh.Vertices[verticesStart + j].Normal.X != 0 || Mesh.Vertices[verticesStart + j].Normal.Z != 0)
                    {
                        Mesh.Vertices[verticesStart + j].Normal.Y = 0;
                        Mesh.Vertices[verticesStart + j].Normal.Normalize();
                    }
                }
            }

            Mesh.GenVBO(Renderer);
        }
Esempio n. 10
0
        public void GenMesh(World world, uint roomID, Level tr)
        {
            var texMask = world.EngineVersion == Loader.Engine.TR4 ? TextureIndexMaskTr4 : TextureIndexMask;

            var trRoom = tr.Rooms[roomID];

            if(trRoom.Triangles.Length == 0 && trRoom.Rectangles.Length == 0)
            {
                Mesh = null;
                return;
            }

            Mesh = new BaseMesh
            {
                ID = roomID,
                TexturePageCount = world.TextureAtlas.NumAtlasPages + 1,
                UsesVertexColors = true // This is implicitly true on room meshes
            };

            Mesh.Vertices.Resize(trRoom.Vertices.Length, () => new Vertex());
            for (var i = 0; i < Mesh.Vertices.Count; i++)
            {
                Mesh.Vertices[i].Position = trRoom.Vertices[i].Vertex.ToVector3();
                Mesh.Vertices[i].Normal = Vector3.Zero; // paranoid
            }

            Mesh.FindBB();

            Mesh.Polygons.Resize(trRoom.Triangles.Length + trRoom.Rectangles.Length, () => new Polygon());
            var p = 0;

            // triangles
            for (var i = 0; i < trRoom.Triangles.Length; i++, p++)
            {
                tr_setupRoomVertices(world, tr, trRoom, Mesh, 3, trRoom.Triangles[i].Vertices,
                    (ushort)(trRoom.Triangles[i].Texture & texMask), Mesh.Polygons[p]);
                Mesh.Polygons[p].DoubleSide = (trRoom.Triangles[i].Texture & 0x8000) != 0;
            }

            // rectangles
            for (var i = 0; i < trRoom.Rectangles.Length; i++, p++)
            {
                tr_setupRoomVertices(world, tr, trRoom, Mesh, 4, trRoom.Rectangles[i].Vertices,
                    (ushort)(trRoom.Rectangles[i].Texture & texMask), Mesh.Polygons[p]);
                Mesh.Polygons[p].DoubleSide = (trRoom.Rectangles[i].Texture & 0x8000) != 0;
            }

            // let us normalise normals %)
            foreach (var v in Mesh.Vertices)
            {
                v.Normal = v.Normal.SafeNormalize();
            }

            p = 0;
            // triangles
            for (var i = 0; i < trRoom.Triangles.Length; i++, p++)
            {
                tr_copyNormals(Mesh.Polygons[p], Mesh, trRoom.Triangles[i].Vertices);
            }

            // rectangles
            for (var i = 0; i < trRoom.Rectangles.Length; i++, p++)
            {
                tr_copyNormals(Mesh.Polygons[p], Mesh, trRoom.Rectangles[i].Vertices);
            }

            Mesh.Vertices.Clear();
            Mesh.GenFaces();
            Mesh.PolySortInMesh();
        }
Esempio n. 11
0
        public void Empty()
        {
            Containers.Clear();
            NearRoomList.Clear();
            Portals.Clear();
            Frustum.Clear();
            Mesh = null;

            if (StaticMesh.Count > 0)
            {
                foreach(var sm in StaticMesh)
                {
                    RigidBody body = null;
                    if((body = sm.BtBody) != null)
                    {
                        if(body.MotionState != null)
                        {
                            body.MotionState.Dispose();
                            body.MotionState = null;
                        }
                        body.CollisionShape = null;

                        BtEngineDynamicsWorld.RemoveRigidBody(body);
                        body.Dispose();
                        body = null;
                        sm.BtBody = null;
                    }

                    if(sm.Self != null)
                    {
                        sm.Self.Room = null;
                        sm.Self = null;
                    }
                }
                StaticMesh.Clear();
            }

            if(BtBody != null)
            {
                BtBody.UserObject = null;
                if(BtBody.MotionState != null)
                {
                    BtBody.MotionState.Dispose();
                    BtBody.MotionState = null;
                }
                if(BtBody.CollisionShape != null)
                {
                    BtBody.CollisionShape.Dispose();
                    //BtBody.CollisionShape = null;
                }

                BtEngineDynamicsWorld.RemoveRigidBody(BtBody);
                BtBody = null;
            }

            Sectors.Clear();
            SectorsX = 0;
            SectorsY = 0;

            Sprites.Clear();

            Lights.Clear();

            Self = null;
        }
Esempio n. 12
0
 public static Vertex FindVertexInMesh(BaseMesh mesh, Vector3 v)
 {
     return mesh.Vertices.FirstOrDefault(mv => (v - mv.Position).LengthSquared < 4.0f);
 }