Esempio n. 1
0
        private tr_mesh CreateDummyWadMesh(WadMesh oldMesh, bool isStatic, int objectId,
                                           bool isWaterfall = false, bool isOptics = false,
                                           WadMeshLightingType lightType = WadMeshLightingType.PrecalculatedGrayShades)
        {
            int currentMeshSize = 0;
            var newMesh         = new tr_mesh
            {
                Center = new tr_vertex
                {
                    X = (short)oldMesh.BoundingSphere.Center.X,
                    Y = (short)-oldMesh.BoundingSphere.Center.Y,
                    Z = (short)oldMesh.BoundingSphere.Center.Z
                },
                Radius = (short)oldMesh.BoundingSphere.Radius
            };
            int numShades = 0;

            currentMeshSize    += 10;
            newMesh.NumVertices = 0;
            currentMeshSize    += 2;
            int numNormals = 0;

            newMesh.Vertices = new tr_vertex[0];

            newMesh.NumNormals = 0;
            currentMeshSize   += 2;
            short numQuads     = 0;
            short numTriangles = 0;

            newMesh.NumTexturedQuads = numQuads;
            currentMeshSize         += 2;

            newMesh.NumTexturedTriangles = numTriangles;
            currentMeshSize += 2;

            int lastQuad     = 0;
            int lastTriangle = 0;

            newMesh.TexturedQuads     = new tr_face4[numQuads];
            newMesh.TexturedTriangles = new tr_face3[numTriangles];
            if (_level.Settings.GameVersion <= TRVersion.Game.TR3)
            {
                currentMeshSize += 4; // Num colored quads and triangles
            }
            if (currentMeshSize % 4 != 0)
            {
                currentMeshSize += 2;
            }

            newMesh.MeshSize    = currentMeshSize;
            newMesh.MeshPointer = _totalMeshSize;
            _meshPointers.Add((uint)_totalMeshSize);

            _totalMeshSize += currentMeshSize;

            _meshes.Add(newMesh);

            return(newMesh);
        }
Esempio n. 2
0
        private tr_mesh ConvertWadMesh(WadMesh oldMesh, bool isStatic, int objectId, int meshIndex,
                                       bool isWaterfall = false, bool isOptics = false,
                                       WadMeshLightingType lightType = WadMeshLightingType.PrecalculatedGrayShades)
        {
            int currentMeshSize = 0;

            var newMesh = new tr_mesh
            {
                Center = new tr_vertex
                {
                    X = (short)oldMesh.BoundingSphere.Center.X,
                    Y = (short)-oldMesh.BoundingSphere.Center.Y,
                    Z = (short)oldMesh.BoundingSphere.Center.Z
                },
                Radius = (short)oldMesh.BoundingSphere.Radius
            };

            currentMeshSize += 10;

            newMesh.NumVertices = (short)oldMesh.VerticesPositions.Count;
            currentMeshSize    += 2;

            newMesh.Vertices = new tr_vertex[oldMesh.VerticesPositions.Count];

            for (int j = 0; j < oldMesh.VerticesPositions.Count; j++)
            {
                var vertex = oldMesh.VerticesPositions[j];
                newMesh.Vertices[j] = new tr_vertex((short)vertex.X, (short)-vertex.Y, (short)vertex.Z);

                currentMeshSize += 6;
            }

            // FIX: the following code will check for valid normals and shades combinations.
            // As last chance, I recalculate the normals on the fly.
            bool useShades = false;

            if (isStatic)
            {
                if (lightType == WadMeshLightingType.Normals)
                {
                    if (oldMesh.VerticesNormals.Count == 0)
                    {
                        _progressReporter.ReportWarn(string.Format("Static {0} is a mesh with invalid lighting data. Normals will be recalculated on the fly.", objectId));
                        oldMesh.CalculateNormals();
                    }
                    useShades = false;
                }
                else
                {
                    if (oldMesh.VerticesShades.Count == 0)
                    {
                        if (oldMesh.VerticesNormals.Count == 0)
                        {
                            _progressReporter.ReportWarn(string.Format("Static {0} is a mesh with invalid lighting data. Normals will be recalculated on the fly.", objectId));
                            oldMesh.CalculateNormals();
                        }
                        useShades = false;
                    }
                    else
                    {
                        useShades = true;
                    }
                }
            }
            else
            {
                if (oldMesh.VerticesNormals.Count == 0)
                {
                    _progressReporter.ReportWarn(string.Format("Mesh {0} of Moveable {1} contains invalid lighting data. Normals will be recalculated on the fly.", meshIndex, objectId));
                    oldMesh.CalculateNormals();
                }
                useShades = false;
            }

            newMesh.NumNormals = (short)(useShades ? -oldMesh.VerticesShades.Count : oldMesh.VerticesNormals.Count);
            currentMeshSize   += 2;

            if (!useShades)
            {
                newMesh.Normals = new tr_vertex[oldMesh.VerticesNormals.Count];

                for (int j = 0; j < oldMesh.VerticesNormals.Count; j++)
                {
                    Vector3 normal = oldMesh.VerticesNormals[j];
                    normal             = Vector3.Normalize(normal);
                    normal            *= 16300.0f;
                    newMesh.Normals[j] = new tr_vertex((short)normal.X, (short)-normal.Y, (short)normal.Z);

                    currentMeshSize += 6;
                }
            }
            else
            {
                newMesh.Lights = new short[oldMesh.VerticesShades.Count];

                for (int j = 0; j < oldMesh.VerticesShades.Count; j++)
                {
                    newMesh.Lights[j] = oldMesh.VerticesShades[j];

                    currentMeshSize += 2;
                }
            }

            short numQuads     = 0;
            short numTriangles = 0;

            foreach (var poly in oldMesh.Polys)
            {
                if (poly.Shape == WadPolygonShape.Quad)
                {
                    numQuads++;
                }
                else
                {
                    numTriangles++;
                }
            }

            newMesh.NumTexturedQuads = numQuads;
            currentMeshSize         += 2;

            newMesh.NumTexturedTriangles = numTriangles;
            currentMeshSize += 2;

            int lastQuad     = 0;
            int lastTriangle = 0;

            newMesh.TexturedQuads     = new tr_face4[numQuads];
            newMesh.TexturedTriangles = new tr_face3[numTriangles];

            for (int j = 0; j < oldMesh.Polys.Count; j++)
            {
                var poly = oldMesh.Polys[j];

                ushort lightingEffect = poly.Texture.BlendMode == BlendMode.Additive ? (ushort)1 : (ushort)0;
                if (poly.ShineStrength > 0)
                {
                    if (useShades && isStatic)
                    {
                        _progressReporter.ReportWarn("Stray shiny effect found on static " + objectId + ", face " + oldMesh.Polys.IndexOf(poly) + ". Ignoring data.");
                    }
                    else
                    {
                        lightingEffect |= 0x02;
                        lightingEffect |= (ushort)(Math.Min((byte)63, poly.ShineStrength) << 2);
                    }
                }

                // Very quirky way to identify 1st face of a waterfall in TR4-TR5 wads.
                bool topmostAndUnpadded = (j == 0) ? isWaterfall : false;

                // Check if we should merge object and room textures in same texture tiles.
                bool agressivePacking = _level.Settings.AgressiveTexturePacking;

                if (poly.Shape == WadPolygonShape.Quad)
                {
                    FixWadTextureCoordinates(ref poly.Texture);

                    var result = _textureInfoManager.AddTexture(poly.Texture, agressivePacking, false, topmostAndUnpadded);
                    if (isOptics)
                    {
                        result.Rotation = 0;           // Very ugly hack for TR4-5 binocular/target optics!
                    }
                    newMesh.TexturedQuads[lastQuad++] = result.CreateFace4(new ushort[] { (ushort)poly.Index0, (ushort)poly.Index1, (ushort)poly.Index2, (ushort)poly.Index3 },
                                                                           poly.Texture.DoubleSided, lightingEffect);
                    currentMeshSize += _level.Settings.GameVersion <= TRVersion.Game.TR3 ? 10 : 12;
                }
                else
                {
                    FixWadTextureCoordinates(ref poly.Texture);

                    var result = _textureInfoManager.AddTexture(poly.Texture, agressivePacking, true, topmostAndUnpadded);
                    if (isOptics)
                    {
                        result.Rotation = 0;           // Very ugly hack for TR4-5 binocular/target optics!
                    }
                    newMesh.TexturedTriangles[lastTriangle++] = result.CreateFace3(new ushort[] { (ushort)poly.Index0, (ushort)poly.Index1, (ushort)poly.Index2 },
                                                                                   poly.Texture.DoubleSided, lightingEffect);
                    currentMeshSize += _level.Settings.GameVersion <= TRVersion.Game.TR3 ? 8 : 10;
                }
            }

            if (_level.Settings.GameVersion <= TRVersion.Game.TR3)
            {
                currentMeshSize += 4; // Num colored quads and triangles
            }
            if (currentMeshSize % 4 != 0)
            {
                currentMeshSize += 2;
            }

            newMesh.MeshSize    = currentMeshSize;
            newMesh.MeshPointer = _totalMeshSize;
            _meshPointers.Add((uint)_totalMeshSize);

            _totalMeshSize += currentMeshSize;

            _meshes.Add(newMesh);

            return(newMesh);
        }