Beispiel #1
0
        /// <summary>
        /// Only one copy of the model is loaded regardless of how many copies are placed in the scene.
        /// </summary>
        void LoadContent()
        {
            Trace.Write("S");
            var filePath = FilePath;
            // commented lines allow reading the animation block from an additional file in an Openrails subfolder
            //           string dir = Path.GetDirectoryName(filePath);
            //            string file = Path.GetFileName(filePath);
            //            string orFilePath = dir + @"\openrails\" + file;
            var sFile = new ShapeFile(filePath, viewer.Settings.SuppressShapeWarnings);
            //            if (file.ToLower().Contains("turntable") && File.Exists(orFilePath))
            //            {
            //                sFile.ReadAnimationBlock(orFilePath);
            //            }


            var textureFlags = Helpers.TextureFlags.None;

            if (File.Exists(FilePath + "d"))
            {
                var sdFile = new ShapeDescriptorFile(FilePath + "d");
                textureFlags = (Helpers.TextureFlags)sdFile.Shape.EsdAlternativeTexture;
                if (FilePath != null && FilePath.Contains("\\global\\"))
                {
                    textureFlags |= Helpers.TextureFlags.SnowTrack;                                                     //roads and tracks are in global, as MSTS will always use snow texture in snow weather
                }
                HasNightSubObj = sdFile.Shape.EsdSubObject;
                if ((textureFlags & Helpers.TextureFlags.Night) != 0 && FilePath.Contains("\\trainset\\"))
                {
                    textureFlags |= Helpers.TextureFlags.Underground;
                }
                SoundFileName    = sdFile.Shape.EsdSoundFileName;
                BellAnimationFPS = sdFile.Shape.EsdBellAnimationFps;
            }

            Matrices    = sFile.Shape.Matrices.ToArray();
            MatrixNames = sFile.Shape.Matrices.MatrixNames;
            //var matrixCount = sFile.shape.matrices.Count;
            //MatrixNames.Capacity = matrixCount;
            //Matrices = new Matrix[matrixCount];
            //for (var i = 0; i < matrixCount; ++i)
            //{
            //    MatrixNames.Add(sFile.shape.matrices[i].Name.ToUpper());
            //    Matrices[i] = XNAMatrixFromMSTS(sFile.shape.matrices[i]);
            //}
            Animations = sFile.Shape.Animations;

#if DEBUG_SHAPE_HIERARCHY
            var debugShapeHierarchy = new StringBuilder();
            debugShapeHierarchy.AppendFormat("Shape {0}:\n", Path.GetFileNameWithoutExtension(FilePath).ToUpper());
            for (var i = 0; i < MatrixNames.Count; ++i)
            {
                debugShapeHierarchy.AppendFormat("  Matrix {0,-2}: {1}\n", i, MatrixNames[i]);
            }
            for (var i = 0; i < sFile.shape.prim_states.Count; ++i)
            {
                debugShapeHierarchy.AppendFormat("  PState {0,-2}: flags={1,-8:X8} shader={2,-15} alpha={3,-2} vstate={4,-2} lstate={5,-2} zbias={6,-5:F3} zbuffer={7,-2} name={8}\n", i, sFile.shape.prim_states[i].flags, sFile.shape.shader_names[sFile.shape.prim_states[i].ishader], sFile.shape.prim_states[i].alphatestmode, sFile.shape.prim_states[i].ivtx_state, sFile.shape.prim_states[i].LightCfgIdx, sFile.shape.prim_states[i].ZBias, sFile.shape.prim_states[i].ZBufMode, sFile.shape.prim_states[i].Name);
            }
            for (var i = 0; i < sFile.shape.vtx_states.Count; ++i)
            {
                debugShapeHierarchy.AppendFormat("  VState {0,-2}: flags={1,-8:X8} lflags={2,-8:X8} lstate={3,-2} material={4,-3} matrix2={5,-2}\n", i, sFile.shape.vtx_states[i].flags, sFile.shape.vtx_states[i].LightFlags, sFile.shape.vtx_states[i].LightCfgIdx, sFile.shape.vtx_states[i].LightMatIdx, sFile.shape.vtx_states[i].Matrix2);
            }
            for (var i = 0; i < sFile.shape.light_model_cfgs.Count; ++i)
            {
                debugShapeHierarchy.AppendFormat("  LState {0,-2}: flags={1,-8:X8} uv_ops={2,-2}\n", i, sFile.shape.light_model_cfgs[i].flags, sFile.shape.light_model_cfgs[i].uv_ops.Count);
                for (var j = 0; j < sFile.shape.light_model_cfgs[i].uv_ops.Count; ++j)
                {
                    debugShapeHierarchy.AppendFormat("    UV OP {0,-2}: texture_address_mode={1,-2}\n", j, sFile.shape.light_model_cfgs[i].uv_ops[j].TexAddrMode);
                }
            }
            Trace.Write(debugShapeHierarchy.ToString());
#endif
            LodControls = (from Formats.Msts.Models.LodControl lod in sFile.Shape.LodControls
                           select new LodControl(lod, textureFlags, sFile, this)).ToArray();
            if (LodControls.Length == 0)
            {
                throw new InvalidDataException("Shape file missing lod_control section");
            }
            else if (LodControls[0].DistanceLevels.Length > 0 && LodControls[0].DistanceLevels[0].SubObjects.Length > 0)
            {
                // Zero the position offset of the root matrix for compatibility with MSTS
                if (LodControls[0].DistanceLevels[0].SubObjects[0].ShapePrimitives.Length > 0 && LodControls[0].DistanceLevels[0].SubObjects[0].ShapePrimitives[0].Hierarchy[0] == -1)
                {
                    Matrices[0].M41 = 0;
                    Matrices[0].M42 = 0;
                    Matrices[0].M43 = 0;
                }
                // Look for root subobject, it is not necessarily the first (see ProTrain signal)
                for (int soIndex = 0; soIndex <= LodControls[0].DistanceLevels[0].SubObjects.Length - 1; soIndex++)
                {
                    Formats.Msts.Models.SubObject subObject = sFile.Shape.LodControls[0].DistanceLevels[0].SubObjects[soIndex];
                    if (subObject.SubObjectHeader.GeometryInfo.GeometryNodeMap[0] == 0)
                    {
                        RootSubObjectIndex = soIndex;
                        break;
                    }
                }
            }
        }
Beispiel #2
0
            public SubObject(Formats.Msts.Models.SubObject sub_object, ref int totalPrimitiveIndex, int[] hierarchy, Helpers.TextureFlags textureFlags, ShapeFile sFile, SharedShape sharedShape)
#endif
            {
#if DEBUG_SHAPE_HIERARCHY
                var debugShapeHierarchy = new StringBuilder();
                debugShapeHierarchy.AppendFormat("      Sub object {0}:\n", subObjectIndex);
#endif
                var vertexBufferSet = new VertexBufferSet(sub_object, sFile, viewer.RenderProcess.GraphicsDevice);
#if DEBUG_SHAPE_NORMALS
                var debugNormalsMaterial = viewer.MaterialManager.Load("DebugNormals");
#endif

#if OPTIMIZE_SHAPES_ON_LOAD
                var primitiveMaterials = sub_object.primitives.Cast <primitive>().Select((primitive) =>
#else
                var primitiveIndex = 0;
#if DEBUG_SHAPE_NORMALS
                ShapePrimitives = new ShapePrimitive[sub_object.primitives.Count * 2];
#else
                ShapePrimitives = new ShapePrimitive[sub_object.Primitives.Count];
#endif
                foreach (Primitive primitive in sub_object.Primitives)
#endif
                {
                    var primitiveState          = sFile.Shape.PrimaryStates[primitive.PrimitiveStateIndex];
                    var vertexState             = sFile.Shape.VertexStates[primitiveState.VertexStateIndex];
                    var lightModelConfiguration = sFile.Shape.LightModelConfigs[vertexState.LightConfigIndex];
                    var options = SceneryMaterialOptions.None;

                    // Validate hierarchy position.
                    var hierarchyIndex = vertexState.MatrixIndex;
                    while (hierarchyIndex != -1)
                    {
                        if (hierarchyIndex < 0 || hierarchyIndex >= hierarchy.Length)
                        {
                            var hierarchyList = new List <int>();
                            hierarchyIndex    = vertexState.MatrixIndex;
                            while (hierarchyIndex >= 0 && hierarchyIndex < hierarchy.Length)
                            {
                                hierarchyList.Add(hierarchyIndex);
                                hierarchyIndex = hierarchy[hierarchyIndex];
                            }
                            hierarchyList.Add(hierarchyIndex);
                            Trace.TraceWarning("Ignored invalid primitive hierarchy {1} in shape {0}", sharedShape.FilePath, String.Join(" ", hierarchyList.Select(hi => hi.ToString()).ToArray()));
                            break;
                        }
                        hierarchyIndex = hierarchy[hierarchyIndex];
                    }

                    if (lightModelConfiguration.UVOperations.Count > 0)
                    {
                        if (lightModelConfiguration.UVOperations[0].TextureAddressMode - 1 >= 0 && lightModelConfiguration.UVOperations[0].TextureAddressMode - 1 < UVTextureAddressModeMap.Length)
                        {
                            options |= UVTextureAddressModeMap[lightModelConfiguration.UVOperations[0].TextureAddressMode - 1];
                        }
                        else if (!shapeWarnings.Contains("texture_addressing_mode:" + lightModelConfiguration.UVOperations[0].TextureAddressMode))
                        {
                            Trace.TraceInformation("Skipped unknown texture addressing mode {1} first seen in shape {0}", sharedShape.FilePath, lightModelConfiguration.UVOperations[0].TextureAddressMode);
                            shapeWarnings.Add("texture_addressing_mode:" + lightModelConfiguration.UVOperations[0].TextureAddressMode);
                        }
                    }

                    if (primitiveState.AlphaTestMode == 1)
                    {
                        options |= SceneryMaterialOptions.AlphaTest;
                    }

                    if (ShaderNames.ContainsKey(sFile.Shape.ShaderNames[primitiveState.ShaderIndex]))
                    {
                        options |= ShaderNames[sFile.Shape.ShaderNames[primitiveState.ShaderIndex]];
                    }
                    else if (!shapeWarnings.Contains("shader_name:" + sFile.Shape.ShaderNames[primitiveState.ShaderIndex]))
                    {
                        Trace.TraceInformation("Skipped unknown shader name {1} first seen in shape {0}", sharedShape.FilePath, sFile.Shape.ShaderNames[primitiveState.ShaderIndex]);
                        shapeWarnings.Add("shader_name:" + sFile.Shape.ShaderNames[primitiveState.ShaderIndex]);
                    }

                    if (12 + vertexState.LightMatrixIndex >= 0 && 12 + vertexState.LightMatrixIndex < VertexLightModeMap.Length)
                    {
                        options |= VertexLightModeMap[12 + vertexState.LightMatrixIndex];
                    }
                    else if (!shapeWarnings.Contains("lighting_model:" + vertexState.LightMatrixIndex))
                    {
                        Trace.TraceInformation("Skipped unknown lighting model index {1} first seen in shape {0}", sharedShape.FilePath, vertexState.LightMatrixIndex);
                        shapeWarnings.Add("lighting_model:" + vertexState.LightMatrixIndex);
                    }

                    if ((textureFlags & Helpers.TextureFlags.Night) != 0)
                    {
                        options |= SceneryMaterialOptions.NightTexture;
                    }

                    if ((textureFlags & Helpers.TextureFlags.Underground) != 0)
                    {
                        options |= SceneryMaterialOptions.UndergroundTexture;
                    }

                    Material material;
                    if (primitiveState.TextureIndices.Length != 0)
                    {
                        var texture   = sFile.Shape.Textures[primitiveState.TextureIndices[0]];
                        var imageName = sFile.Shape.ImageNames[texture.ImageIndex];
                        if (String.IsNullOrEmpty(sharedShape.ReferencePath))
                        {
                            material = viewer.MaterialManager.Load("Scenery", Helpers.GetRouteTextureFile(viewer.Simulator, textureFlags, imageName), (int)options, texture.MipMapLODBias);
                        }
                        else
                        {
                            material = viewer.MaterialManager.Load("Scenery", Helpers.GetTextureFile(viewer.Simulator, textureFlags, sharedShape.ReferencePath, imageName), (int)options, texture.MipMapLODBias);
                        }
                    }
                    else
                    {
                        material = viewer.MaterialManager.Load("Scenery", null, (int)options);
                    }

#if DEBUG_SHAPE_HIERARCHY
                    debugShapeHierarchy.AppendFormat("        Primitive {0,-2}: pstate={1,-2} vstate={2,-2} lstate={3,-2} matrix={4,-2}", primitiveIndex, primitive.prim_state_idx, primitiveState.ivtx_state, vertexState.LightCfgIdx, vertexState.imatrix);
                    var debugMatrix = vertexState.imatrix;
                    while (debugMatrix >= 0)
                    {
                        debugShapeHierarchy.AppendFormat(" {0}", sharedShape.MatrixNames[debugMatrix]);
                        debugMatrix = hierarchy[debugMatrix];
                    }
                    debugShapeHierarchy.Append("\n");
#endif

#if OPTIMIZE_SHAPES_ON_LOAD
                    return(new { Key = material.ToString() + "/" + vertexState.imatrix.ToString(), Primitive = primitive, Material = material, HierachyIndex = vertexState.imatrix });
                }).ToArray();