internal static void AddPointBillboard(string material, Vector4 color, Vector3D origin, float radius, float angle, int customViewProjection = -1) { if (!MyRender11.DebugOverrides.BillboardsDynamic) { return; } Debug.Assert(material != null); origin.AssertIsValid(); angle.AssertIsValid(); MyQuadD quad; if (MyUtils.GetBillboardQuadAdvancedRotated(out quad, origin, radius, angle, MyRender11.Environment.Matrices.CameraPosition) != false) { MyBillboard billboard = MyBillboardRenderer.AddBillboardOnce(); if (billboard == null) { return; } billboard.BlendType = MyBillboard.BlenType.Standard; billboard.CustomViewProjection = customViewProjection; CreateBillboard(billboard, ref quad, material, ref color, ref origin); } }
internal static void AddBillboardOriented(string material, Vector4 color, Vector3D origin, Vector3 leftVector, Vector3 upVector, float radius, MyBillboard.BlenType blendType = MyBillboard.BlenType.Standard, float softParticleDistanceScale = 1.0f, int customViewProjection = -1) { if (!MyRender11.DebugOverrides.BillboardsDynamic) { return; } Debug.Assert(material != null); origin.AssertIsValid(); leftVector.AssertIsValid(); upVector.AssertIsValid(); radius.AssertIsValid(); MyDebug.AssertDebug(radius > 0); MyBillboard billboard = MyBillboardRenderer.AddBillboardOnce(); if (billboard == null) { return; } billboard.CustomViewProjection = customViewProjection; billboard.BlendType = blendType; MyQuadD quad; MyUtils.GetBillboardQuadOriented(out quad, ref origin, radius, ref leftVector, ref upVector); CreateBillboard(billboard, ref quad, material, ref color, ref origin, softParticleDistanceScale); }
internal MyVertexFormatTexcoordNormalTangent(Vector2 texcoord, Vector3 normal, Vector3 tangent) { Texcoord = new HalfVector2(texcoord.X, texcoord.Y); Normal = VF_Packer.PackNormalB4(ref normal); Vector4 T = new Vector4(tangent, 1); Tangent = VF_Packer.PackTangentSignB4(ref T); }
internal static void ParseAtlasDescription(string textureDir, string atlasFile, Dictionary <string, MyTextureAtlasElement> atlasDict) { try { //var atlas = new MyTextureAtlas(64); var fsPath = Path.Combine(MyFileSystem.ContentPath, atlasFile); using (var file = MyFileSystem.OpenRead(fsPath)) using (StreamReader sr = new StreamReader(file)) { while (!sr.EndOfStream) { string line = sr.ReadLine(); if (line.StartsWith("#")) { continue; } if (line.Trim(' ').Length == 0) { continue; } string[] parts = line.Split(new char[] { ' ', '\t', ',' }, StringSplitOptions.RemoveEmptyEntries); string name = parts[0]; string atlasName = parts[1]; Vector4 uv = new Vector4( Convert.ToSingle(parts[4], System.Globalization.CultureInfo.InvariantCulture), Convert.ToSingle(parts[5], System.Globalization.CultureInfo.InvariantCulture), Convert.ToSingle(parts[7], System.Globalization.CultureInfo.InvariantCulture), Convert.ToSingle(parts[8], System.Globalization.CultureInfo.InvariantCulture)); name = textureDir + System.IO.Path.GetFileName(name); var atlasTexture = textureDir + atlasName; var element = new MyTextureAtlasElement(); element.TextureId = MyTextures.GetTexture(atlasTexture, MyTextureEnum.GUI, true); element.UvOffsetScale = uv; atlasDict[name] = element; } } } catch (Exception e) { MyLog.Default.WriteLine("Warning: " + e.ToString()); } }
internal static void ParseAtlasDescription(string textureDir, string atlasFile, Dictionary<string, MyTextureAtlasElement> atlasDict) { try { //var atlas = new MyTextureAtlas(64); var fsPath = Path.Combine(MyFileSystem.ContentPath, atlasFile); using (var file = MyFileSystem.OpenRead(fsPath)) using (StreamReader sr = new StreamReader(file)) { while (!sr.EndOfStream) { string line = sr.ReadLine(); if (line.StartsWith("#")) continue; if (line.Trim(' ').Length == 0) continue; string[] parts = line.Split(new char[] { ' ', '\t', ',' }, StringSplitOptions.RemoveEmptyEntries); string name = parts[0]; string atlasName = parts[1]; Vector4 uv = new Vector4( Convert.ToSingle(parts[4], System.Globalization.CultureInfo.InvariantCulture), Convert.ToSingle(parts[5], System.Globalization.CultureInfo.InvariantCulture), Convert.ToSingle(parts[7], System.Globalization.CultureInfo.InvariantCulture), Convert.ToSingle(parts[8], System.Globalization.CultureInfo.InvariantCulture)); name = textureDir + System.IO.Path.GetFileName(name); var atlasTexture = textureDir + atlasName; var element = new MyTextureAtlasElement(); element.TextureId = MyTextures.GetTexture(atlasTexture, MyTextureEnum.GUI, true); element.UvOffsetScale = uv; atlasDict[name] = element; } } } catch (Exception e) { MyLog.Default.WriteLine("Warning: " + e.ToString()); } }
static void RenderDirectionalEnvironmentLight() { MySunlightConstantsLayout constants; constants.Direction = MyEnvironment.DirectionalLightDir; constants.Color = MyEnvironment.DirectionalLightIntensity; var mapping = MyMapping.MapDiscard(m_sunlightConstants); mapping.stream.Write(constants); mapping.Unmap(); //context.VertexShader.Set(MyCommon.FullscreenShader.VertexShader); RC.SetPS(DirectionalEnvironmentLight_Pixel); RC.SetCB(1, m_sunlightConstants); RC.SetCB(4, MyShadows.m_csmConstants); RC.Context.PixelShader.SetSamplers(0, MyRender11.StandardSamplers); RC.Context.PixelShader.SetSampler(MyCommon.SHADOW_SAMPLER_SLOT, MyRender11.m_shadowmapSamplerState); RC.Context.PixelShader.SetShaderResource(MyCommon.CASCADES_SM_SLOT, MyShadows.m_cascadeShadowmapArray.ShaderView); var z = Vector4.Transform(new Vector4(0.5f, 0.5f, -MyEnvironment.FarClipping, 1), MyEnvironment.Projection); RC.Context.PixelShader.SetShaderResource(MyCommon.SKYBOX_SLOT, MyTextures.GetView(MyTextures.GetTexture(MyEnvironment.DaySkybox, MyTextureEnum.CUBEMAP, true))); //RC.Context.PixelShader.SetShaderResource(MyCommon.SKYBOX_IBL_SLOT, MyTextures.GetView(MyTextures.GetTexture(MyEnvironment.DaySkyboxPrefiltered, MyTextureEnum.CUBEMAP, true))); RC.Context.PixelShader.SetShaderResource(MyCommon.SKYBOX_IBL_SLOT, MyRender11.IsIntelBrokenCubemapsWorkaround ? MyTextures.GetView(MyTextures.IntelFallbackCubeTexId) : MyGeometryRenderer.m_envProbe.cubemapPrefiltered.ShaderView); RC.Context.PixelShader.SetShaderResource(MyCommon.SKYBOX2_SLOT, MyTextures.GetView(MyTextures.GetTexture(MyEnvironment.NightSkybox, MyTextureEnum.CUBEMAP, true))); RC.Context.PixelShader.SetShaderResource(MyCommon.SKYBOX2_IBL_SLOT, MyTextures.GetView(MyTextures.GetTexture(MyEnvironment.NightSkyboxPrefiltered, MyTextureEnum.CUBEMAP, true))); RC.Context.PixelShader.SetShaderResource(MyCommon.SHADOW_SLOT, MyRender11.m_shadowsHelper.ShaderView); RC.Context.PixelShader.SetShaderResource(MyCommon.AMBIENT_BRDF_LUT_SLOT, MyCommon.GetAmbientBrdfLut()); RC.BindSRV(MyCommon.AO_SLOT, MyScreenDependants.m_ambientOcclusion); MyScreenPass.RunFullscreenPixelFreq(MyGBuffer.Main.Get(MyGbufferSlot.LBuffer)); if (MyRender11.MultisamplingEnabled) { RC.SetPS(DirectionalEnvironmentLight_Sample); MyScreenPass.RunFullscreenSampleFreq(MyGBuffer.Main.Get(MyGbufferSlot.LBuffer)); } }
// http://web.stanford.edu/class/cs248/pdf/class_13_skinning.pdf private Matrix ComputeSkinning(Vector4UByte indices, ref VRageMath.Vector4 weights) { // TODO: Optmize Matrix ret = new Matrix(); for (int it = 0; it < 4; it++) { float weight = weights[it]; if (weight == 0) { break; } // NOTE: m_skinTransforms are already transposed Matrix transform; Matrix.Transpose(ref m_skinTransforms[m_skeletonIndices[indices[it]]], out transform); transform *= weight; ret += transform; } return(ret); }
internal void Synchronize(MyRenderSettings settings) { CheckArrays(settings); EnableHWOcclusionQueries = settings.EnableHWOcclusionQueries; SkipLOD_NEAR = settings.SkipLOD_NEAR; SkipLOD_0 = settings.SkipLOD_0; SkipLOD_1 = settings.SkipLOD_1; SkipVoxels = settings.SkipVoxels; VoxelQuality = settings.VoxelQuality; //Debug properties ShowEnvironmentScreens = settings.ShowEnvironmentScreens; ShowBlendedScreens = settings.ShowBlendedScreens; ShowGreenBackground = settings.ShowGreenBackground; ShowLod1WithRedOverlay = settings.ShowLod1WithRedOverlay; EnableLightsRuntime = settings.EnableLightsRuntime; ShowEnhancedRenderStatsEnabled = settings.ShowEnhancedRenderStatsEnabled; ShowResourcesStatsEnabled = settings.ShowResourcesStatsEnabled; ShowTexturesStatsEnabled = settings.ShowTexturesStatsEnabled; EnableSun = settings.EnableSun; EnableShadows = settings.EnableShadows; EnableAsteroidShadows = settings.EnableAsteroidShadows; EnableFog = settings.EnableFog; DebugRenderClipmapCells = settings.DebugRenderClipmapCells; EnableVoxelMerging = settings.EnableVoxelMerging; DebugRenderMergedCells = settings.DebugRenderMergedCells; EnableEnvironmentMapAmbient = settings.EnableEnvironmentMapAmbient; EnableEnvironmentMapReflection = settings.EnableEnvironmentMapReflection; ShadowCascadeCount = settings.ShadowCascadeCount; ShowShadowCascadeSplits = settings.ShowShadowCascadeSplits; EnableShadowBlur = settings.EnableShadowBlur; ShadowInterleaving = settings.ShadowInterleaving; UpdateCascadesEveryFrame = settings.UpdateCascadesEveryFrame; ShadowCascadeMaxDistanceMultiplierMedium = settings.ShadowCascadeMaxDistanceMultiplierMedium; ShadowCascadeMaxDistanceMultiplierHigh = settings.ShadowCascadeMaxDistanceMultiplierHigh; ShadowCascadeZOffset = settings.ShadowCascadeZOffset; ShadowCascadeSpreadFactor = settings.ShadowCascadeSpreadFactor; ShadowFadeoutMultiplier = settings.ShadowFadeoutMultiplier; ShadowCascadeMaxDistance = settings.ShadowCascadeMaxDistance; //for (int index = 0; index < settings.ShadowCascadeCount; ++index) //{ // ShadowCascadeFrozen[index] = settings.ShadowCascadeFrozen[index]; // ShadowCascadeSmallSkipThresholds[index] = settings.ShadowCascadeSmallSkipThresholds[index]; //} Wireframe = settings.Wireframe; EnableStencilOptimization = settings.EnableStencilOptimization; EnableStencilOptimizationLOD1 = settings.EnableStencilOptimizationLOD1; ShowStencilOptimization = settings.ShowStencilOptimization; CheckDiffuseTextures = settings.CheckDiffuseTextures; CheckNormalTextures = settings.CheckNormalTextures; ShowSpecularIntensity = settings.ShowSpecularIntensity; ShowSpecularPower = settings.ShowSpecularPower; ShowEmissivity = settings.ShowEmissivity; ShowReflectivity = settings.ShowReflectivity; EnableSpotShadows = settings.EnableSpotShadows; VisualizeOverdraw = settings.VisualizeOverdraw; MultimonTest = settings.MultimonTest; EnableCameraInterpolation = settings.EnableCameraInterpolation; EnableObjectInterpolation = settings.EnableObjectInterpolation; InterpolationLagMs = settings.InterpolationLagMs; LagFeedbackMult = settings.LagFeedbackMult; DisplayGbufferColor = settings.DisplayGbufferColor; DisplayGbufferColorLinear = settings.DisplayGbufferColorLinear; DisplayGbufferNormal = settings.DisplayGbufferNormal; DisplayGbufferGlossiness = settings.DisplayGbufferGlossiness; DisplayGbufferMetalness = settings.DisplayGbufferMetalness; DisplayGbufferMaterialID = settings.DisplayGbufferMaterialID; DisplayGbufferAO = settings.DisplayGbufferAO; DisplayEmissive = settings.DisplayEmissive; DisplayEdgeMask = settings.DisplayEdgeMask; DisplayDepth = settings.DisplayDepth; DisplayStencil = settings.DisplayStencil; RgbMultiplier = settings.RgbMultiplier; MetalnessMultiplier = settings.MetalnessMultiplier; GlossMultiplier = settings.GlossMultiplier; AoMultiplier = settings.AoMultiplier; EmissiveMultiplier = settings.EmissiveMultiplier; ColorMaskMultiplier = settings.ColorMaskMultiplier; DisplayAmbientDiffuse = settings.DisplayAmbientDiffuse; DisplayAmbientSpecular = settings.DisplayAmbientSpecular; DrawParticleRenderTarget = settings.DrawParticleRenderTarget; DisplayIDs = settings.DisplayIDs; DisplayAabbs = settings.DisplayAabbs; DrawMergeInstanced = settings.DrawMergeInstanced; DrawNonMergeInstanced = settings.DrawNonMergeInstanced; TerrainDetailD0 = settings.TerrainDetailD0; TerrainDetailD1 = settings.TerrainDetailD1; TerrainDetailD2 = settings.TerrainDetailD2; TerrainDetailD3 = settings.TerrainDetailD3; FreezeTerrainQueries = settings.FreezeTerrainQueries; GrassPostprocess = settings.GrassPostprocess; GrassPostprocessCloseDistance = settings.GrassPostprocessCloseDistance; GrassGeometryClippingDistance = settings.GrassGeometryClippingDistance; GrassGeometryScalingNearDistance = settings.GrassGeometryScalingNearDistance; GrassGeometryScalingFarDistance = settings.GrassGeometryScalingFarDistance; GrassGeometryDistanceScalingFactor = settings.GrassGeometryDistanceScalingFactor; GrassDensityFactor = settings.GrassDensityFactor; WindStrength = settings.WindStrength; WindAzimuth = settings.WindAzimuth; DisplayShadowsWithDebug = settings.DisplayShadowsWithDebug; DrawCascadeTextures = settings.DrawCascadeTextures; DisplayNDotL = settings.DisplayNDotL; EnableParallelRendering = settings.EnableParallelRendering; ForceImmediateContext = settings.ForceImmediateContext; RenderBatchSize = settings.RenderBatchSize; AmortizeBatchWork = settings.AmortizeBatchWork; LoopObjectThenPass = settings.LoopObjectThenPass; RenderThreadAsWorker = settings.RenderThreadAsWorker; //EnableTonemapping = settings.EnableTonemapping; DisplayHdrDebug = settings.DisplayHdrDebug; AdaptationTau = settings.AdaptationTau; LuminanceExposure = settings.LuminanceExposure; Contrast = settings.Contrast; Brightness = settings.Brightness; MiddleGrey = settings.MiddleGrey; BloomExposure = settings.BloomExposure; BloomMult = settings.BloomMult; MiddleGreyCurveSharpness = settings.MiddleGreyCurveSharpness; MiddleGreyAt0 = settings.MiddleGreyAt0; BlueShiftRapidness = settings.BlueShiftRapidness; BlueShiftScale = settings.BlueShiftScale; BacklightMult = settings.BacklightMult; EnvMult = settings.EnvMult; FogDensity = settings.FogDensity; FogMult = settings.FogMult; FogYOffset = settings.FogYOffset; FogColor = settings.FogColor; FoliageLod0Distance = settings.FoliageLod0Distance; FoliageLod1Distance = settings.FoliageLod1Distance; FoliageLod2Distance = settings.FoliageLod2Distance; FoliageLod3Distance = settings.FoliageLod3Distance; EnableFoliageDebug = settings.EnableFoliageDebug; FreezeFoliageViewer = settings.FreezeFoliageViewer; }
private static void CreateBillboard(VRageRender.MyBillboard billboard, ref MyQuadD quad, string material, ref Vector4 color, ref Vector3D origin, float softParticleDistanceScale = 1.0f, Vector2 uvOffset = new Vector2(), float reflectivity = 0) { Debug.Assert(material != null); if (string.IsNullOrEmpty(material) || !MyTransparentMaterials.ContainsMaterial(material)) { material = "ErrorMaterial"; color = Vector4.One; } billboard.Material = material; quad.Point0.AssertIsValid(); quad.Point1.AssertIsValid(); quad.Point2.AssertIsValid(); quad.Point3.AssertIsValid(); // Billboard vertexes billboard.Position0 = quad.Point0; billboard.Position1 = quad.Point1; billboard.Position2 = quad.Point2; billboard.Position3 = quad.Point3; billboard.UVOffset = uvOffset; billboard.UVSize = Vector2.One; // Distance for sorting // IMPORTANT: Must be calculated before we do color and alpha misting, because we need distance there billboard.DistanceSquared = (float)Vector3D.DistanceSquared(MyRender11.Environment.Matrices.CameraPosition, origin); // Color billboard.Color = color; billboard.Reflectivity = reflectivity; billboard.ColorIntensity = 1; billboard.ParentID = -1; // Alpha depends on distance to camera. Very close bilboards are more transparent, so player won't see billboard errors or rotating billboards var mat = MyTransparentMaterials.GetMaterial(billboard.Material); if (mat.AlphaMistingEnable) { billboard.Color *= MathHelper.Clamp(((float)Math.Sqrt(billboard.DistanceSquared) - mat.AlphaMistingStart) / (mat.AlphaMistingEnd - mat.AlphaMistingStart), 0, 1); } billboard.Color *= mat.Color; billboard.SoftParticleDistanceScale = softParticleDistanceScale; }
private Vector4 GetUvScaleOffset(Vector2I uvTiles, Vector2I tileIndex) { Vector4 scaleOffset = new Vector4(uvTiles.X, uvTiles.Y, (1.0f / uvTiles.X) * tileIndex.X, (1.0f / uvTiles.Y) * tileIndex.Y); return scaleOffset; }
internal MyVertexFormatTexcoordNormalTangent(HalfVector2 texcoord, Vector3 normal, Vector4 tangent) { Texcoord = texcoord; Normal = VF_Packer.PackNormalB4(ref normal); Tangent = VF_Packer.PackTangentSignB4(ref tangent); }
internal MyVertexFormatTexcoordNormalTangentTexindices(Vector2 texcoord, Vector3 normal, Vector3 tangent, Byte4 texIndices) { Texcoord = new HalfVector2(texcoord.X, texcoord.Y); Normal = VF_Packer.PackNormalB4(ref normal); Vector4 T = new Vector4(tangent, 1); Tangent = VF_Packer.PackTangentSignB4(ref T); TexIndices = texIndices; }
internal MyVertexFormatPositionSkinning(HalfVector4 position, Byte4 indices, Vector4 weights) { Position = position; BoneIndices = indices; BoneWeights = new HalfVector4(weights); }
internal MyVertexFormatPositionTextureSkinning(HalfVector4 position, HalfVector2 texcoord, Byte4 indices, Vector4 weights) { Position = position; Texcoord = texcoord; BoneIndices = indices; BoneWeights = new HalfVector4(weights); }
//internal void SetModel(MyMesh mesh) //{ // m_mesh = mesh; // //m_currentLod = 0; // //m_lodState = 0; // //m_currentLod = 0; // // todo: consider if ok when changing during lod transition // // copy material data // //m_lodMaterials = new MyRenderLodMaterialInfo[mesh.LODs.Length]; // //for(int i=0; i<mesh.LODs.Length; i++) // //{ // // m_lodMaterials[i] = new MyRenderLodMaterialInfo(mesh.LODs[i].m_meshInfo); // //} // //SetLocalAabbToModelLod(0); // m_owner.MarkRenderDirty(); //} // for now internal void SetKeyColor(Vector4 keyColor) { m_keyColor.X = keyColor.X; m_keyColor.Y = keyColor.Y; m_keyColor.Z = keyColor.Z; UpdateProxiesObjectData(); }
// Sort of lazy-load, where constructor just saves information about what this model should be, but real load is done here - and only one time. // This loads only vertex data, doesn't touch GPU // Can be called from main and background thread public void LoadData() { if (m_loadedData) return; if (m_loadedContent) return; lock (this) { if (m_loadedData) return; if (m_loadedContent) return; MyRender.GetRenderProfiler().StartProfilingBlock("MyModel::LoadData"); MyRender.Log.WriteLine("MyModel.LoadData -> START", LoggingOptions.LOADING_MODELS); MyRender.Log.IncreaseIndent(LoggingOptions.LOADING_MODELS); MyRender.Log.WriteLine("m_assetName: " + m_assetName, LoggingOptions.LOADING_MODELS); // Read data from model TAG parameter. There are stored vertex positions, triangle indices, vectors, ... everything we need. MyRender.GetRenderProfiler().StartProfilingBlock("Model - load data - import data"); string assetForImport = AssetName; var fsPath = Path.IsPathRooted(AssetName) ? AssetName : Path.Combine(MyFileSystem.ContentPath, AssetName); if (!MyFileSystem.FileExists(fsPath)) { MyRender.Log.WriteLine("ERROR: Asset " + AssetName + "not exists!"); assetForImport = @"Models\Debug\Error.mwm"; } MyRender.Log.WriteLine(String.Format("Importing asset {0}, path: {1}", assetForImport, AssetName), LoggingOptions.LOADING_MODELS); try { m_importer.ImportData(assetForImport); } catch { MyRender.Log.WriteLine(String.Format("Importing asset failed {0}", m_assetName)); throw; } MyRender.GetRenderProfiler().EndProfilingBlock(); MyRender.GetRenderProfiler().StartProfilingBlock("Model - load data - load tag data"); Dictionary<string, object> tagData = m_importer.GetTagData(); if (tagData.Count == 0) { throw new Exception(String.Format("Uncompleted tagData for asset: {0}, path: {1}", m_assetName, AssetName)); } MyRender.GetRenderProfiler().EndProfilingBlock(); MyRender.GetRenderProfiler().StartProfilingBlock("Model - load data - vertex, normals, texture coords"); object patternScale; if (tagData.TryGetValue(MyImporterConstants.TAG_PATTERN_SCALE, out patternScale)) { PatternScale = (float)patternScale; } HalfVector4[] vertices = (HalfVector4[])tagData[MyImporterConstants.TAG_VERTICES]; //Dont assert, it can be animation //System.Diagnostics.Debug.Assert(vertices.Length > 0); Byte4[] normals = (Byte4[])tagData[MyImporterConstants.TAG_NORMALS]; m_vertices = new MyCompressedVertexNormal[vertices.Length]; if (normals.Length > 0) { for (int v = 0; v < vertices.Length; v++) { m_vertices[v] = new MyCompressedVertexNormal() { Position = vertices[v],// VF_Packer.PackPosition(ref vertices[v]), Normal = normals[v]//VF_Packer.PackNormalB4(ref normals[v]) }; } } else { for (int v = 0; v < vertices.Length; v++) { m_vertices[v] = new MyCompressedVertexNormal() { Position = vertices[v],// VF_Packer.PackPosition(ref vertices[v]), }; } } m_verticesCount = vertices.Length; HalfVector2[] forLoadingTexCoords0 = (HalfVector2[])tagData[MyImporterConstants.TAG_TEXCOORDS0]; m_forLoadingTexCoords0 = new HalfVector2[forLoadingTexCoords0.Length]; for (int t = 0; t < forLoadingTexCoords0.Length; t++) { m_forLoadingTexCoords0[t] = forLoadingTexCoords0[t];// new HalfVector2(forLoadingTexCoords0[t]); m_forLoadingTexCoords0[t] = new HalfVector2(m_forLoadingTexCoords0[t].ToVector2() / PatternScale); } MyRender.GetRenderProfiler().EndProfilingBlock(); MyRender.GetRenderProfiler().StartProfilingBlock("Model - load data - mesh"); m_meshContainer.Clear(); if (tagData.ContainsKey(MyImporterConstants.TAG_MESH_PARTS)) { List<int> indices = new List<int>(GetVerticesCount()); // Default capacity estimation int maxIndex = 0; List<MyMeshPartInfo> meshParts = tagData[MyImporterConstants.TAG_MESH_PARTS] as List<MyMeshPartInfo>; foreach (MyMeshPartInfo meshPart in meshParts) { if (meshPart.m_MaterialDesc != null) MyRenderModels.Materials[meshPart.m_MaterialDesc.MaterialName] = meshPart.m_MaterialDesc; MyRenderMesh mesh = new MyRenderMesh(meshPart, m_assetName); mesh.IndexStart = indices.Count; mesh.TriCount = meshPart.m_indices.Count / 3; System.Diagnostics.Debug.Assert(mesh.TriCount > 0); foreach (var i in meshPart.m_indices) { indices.Add(i); if (i > maxIndex) { maxIndex = i; } } m_meshContainer.Add(mesh); if (meshPart.m_MaterialDesc != null && meshPart.Technique == MyMeshDrawTechnique.GLASS) { float minimumGlassShadow = 0.0f; if (string.IsNullOrEmpty(meshPart.m_MaterialDesc.GlassCW)) continue; if (string.IsNullOrEmpty(meshPart.m_MaterialDesc.GlassCCW)) continue; var materialCW = MyTransparentMaterials.GetMaterial(meshPart.m_MaterialDesc.GlassCW); var materialCCW = MyTransparentMaterials.GetMaterial(meshPart.m_MaterialDesc.GlassCCW); mesh.GlassDithering = System.Math.Max(materialCW.Color.W, minimumGlassShadow); MyRenderMesh glassMesh = new MyRenderMesh(meshPart, m_assetName); glassMesh.GlassDithering = System.Math.Max(materialCCW.Color.W, minimumGlassShadow); glassMesh.IndexStart = indices.Count; glassMesh.TriCount = meshPart.m_indices.Count / 3; System.Diagnostics.Debug.Assert(glassMesh.TriCount > 0); for (int i = 0; i < meshPart.m_indices.Count; i += 3) { indices.Add(meshPart.m_indices[i + 0]); indices.Add(meshPart.m_indices[i + 2]); indices.Add(meshPart.m_indices[i + 1]); } m_meshContainer.Add(glassMesh); } } if (maxIndex <= ushort.MaxValue) { // create 16 bit indices m_Indices_16bit = new ushort[indices.Count]; for (int i = 0; i < indices.Count; i++) { m_Indices_16bit[i] = (ushort)indices[i]; } } else { // use 32bit indices m_Indices = indices.ToArray(); } m_trianglesCount = indices.Count / 3; } MyRender.GetRenderProfiler().EndProfilingBlock(); MyRender.GetRenderProfiler().StartProfilingBlock("Model - load data - other data"); if (MyRenderConstants.RenderQualityProfile.UseNormals && m_forLoadingTexCoords0.Length > 0) { var verticesNum = vertices.Length; Byte4[] forLoadingTangents = (Byte4[])tagData[MyImporterConstants.TAG_TANGENTS]; Byte4[] forLoadingBitangents = (Byte4[])tagData[MyImporterConstants.TAG_BINORMALS]; m_forLoadingTangents = new Byte4[forLoadingTangents.Length]; for (int v = 0; v < forLoadingTangents.Length; v++) { var N = VF_Packer.UnpackNormal(m_vertices[v].Normal.PackedValue); var T = VF_Packer.UnpackNormal(forLoadingTangents[v].PackedValue); var B = VF_Packer.UnpackNormal(forLoadingBitangents[v].PackedValue); var tangentSign = new Vector4(T.X, T.Y, T.Z, 0); tangentSign.W = T.Cross(N).Dot(B) < 0 ? -1 : 1; m_forLoadingTangents[v] = VF_Packer.PackTangentSignB4(ref tangentSign); } } m_specularShininess = (float)tagData[MyImporterConstants.TAG_SPECULAR_SHININESS]; m_specularPower = (float)tagData[MyImporterConstants.TAG_SPECULAR_POWER]; m_rescaleFactor = (float)tagData[MyImporterConstants.TAG_RESCALE_FACTOR]; BoneIndices = (Vector4I[])tagData[MyImporterConstants.TAG_BLENDINDICES]; BoneWeights = (Vector4[])tagData[MyImporterConstants.TAG_BLENDWEIGHTS]; Animations = (ModelAnimations)tagData[MyImporterConstants.TAG_ANIMATIONS]; Bones = (MyModelBone[])tagData[MyImporterConstants.TAG_BONES]; if(BoneIndices.Length > 0 && Bones.Length > MyRenderConstants.MAX_SHADER_BONES) { List<MyMeshPartInfo> meshParts = tagData[MyImporterConstants.TAG_MESH_PARTS] as List<MyMeshPartInfo>; Dictionary<int, int> vertexChanged = new Dictionary<int,int>(); for(int p=0; p<meshParts.Count; p++) { var meshPart = meshParts[p]; Dictionary<int, int> bonesUsed = new Dictionary<int, int>(); int trianglesNum = meshPart.m_indices.Count / 3; for (int i = 0; i < trianglesNum; i++) { for (int j = 0; j < 3; j++) { int index = meshPart.m_indices[i * 3 + j]; if(BoneWeights[index].X > 0) bonesUsed[BoneIndices[index].X] = 1; if (BoneWeights[index].Y > 0) bonesUsed[BoneIndices[index].Y] = 1; if (BoneWeights[index].Z > 0) bonesUsed[BoneIndices[index].Z] = 1; if (BoneWeights[index].W > 0) bonesUsed[BoneIndices[index].W] = 1; } } var partBones = new List<int>(bonesUsed.Keys); partBones.Sort(); if (partBones.Count > 0 && partBones[partBones.Count - 1] >= MyRenderConstants.MAX_SHADER_BONES) { for(int i=0; i<partBones.Count; i++) { bonesUsed[partBones[i]] = i; } Dictionary<int, int> vertexTouched = new Dictionary<int, int>(); for (int i = 0; i < trianglesNum; i++) { for (int j = 0; j < 3; j++) { int index = meshPart.m_indices[i * 3 + j]; if(!vertexTouched.ContainsKey(index)) { if (BoneWeights[index].X > 0) BoneIndices[index].X = bonesUsed[BoneIndices[index].X]; if (BoneWeights[index].Y > 0) BoneIndices[index].Y = bonesUsed[BoneIndices[index].Y]; if (BoneWeights[index].Z > 0) BoneIndices[index].Z = bonesUsed[BoneIndices[index].Z]; if (BoneWeights[index].W > 0) BoneIndices[index].W = bonesUsed[BoneIndices[index].W]; vertexTouched[index] = 1; int changes = 0; vertexChanged.TryGetValue(index, out changes); vertexChanged[index] = changes + 1; } } } m_meshContainer[p].BonesUsed = partBones.ToArray(); } } if (vertexChanged.Values.Count > 0) Debug.Assert(vertexChanged.Values.Max() < 2, "Vertex shared between model parts, will likely result in wrong skinning"); } BoundingBox = (BoundingBox)tagData[MyImporterConstants.TAG_BOUNDING_BOX]; BoundingSphere = (BoundingSphere)tagData[MyImporterConstants.TAG_BOUNDING_SPHERE]; BoundingBoxSize = BoundingBox.Max - BoundingBox.Min; BoundingBoxSizeHalf = BoundingBoxSize / 2.0f; Dictionary<string, MyModelDummy> Dummies = tagData[MyImporterConstants.TAG_DUMMIES] as Dictionary<string, MyModelDummy>; MyRender.GetRenderProfiler().EndProfilingBlock(); if (tagData.ContainsKey(MyImporterConstants.TAG_LODS)) { var tagLODs = tagData[MyImporterConstants.TAG_LODS]; LODs.Clear(); LODs.AddArray((MyLODDescriptor[])tagLODs); foreach (var lodDesc in LODs) { if (!string.IsNullOrEmpty(lodDesc.RenderQuality)) { lodDesc.RenderQualityList = new List<int>(); string[] qualityStrings = lodDesc.RenderQuality.ToUpper().Split(new char[] {','}, StringSplitOptions.RemoveEmptyEntries); foreach (string qs in qualityStrings) { string qs2 = qs.Trim(); if (qs2 == "LOW") lodDesc.RenderQualityList.Add((int)MyRenderQualityEnum.LOW); else if (qs2 == "NORMAL") lodDesc.RenderQualityList.Add((int)MyRenderQualityEnum.NORMAL); else if (qs2 == "HIGH") lodDesc.RenderQualityList.Add((int)MyRenderQualityEnum.HIGH); else if (qs2 == "EXTREME") lodDesc.RenderQualityList.Add((int)MyRenderQualityEnum.EXTREME); } } } } MyRender.Log.WriteLine("Vertexes.Length: " + GetVerticesCount(), LoggingOptions.LOADING_MODELS); MyRender.Log.WriteLine("Centered: " + (bool)tagData[MyImporterConstants.TAG_CENTERED], LoggingOptions.LOADING_MODELS); MyRender.Log.WriteLine("UseChannelTextures: " + (bool)tagData[MyImporterConstants.TAG_USE_CHANNEL_TEXTURES], LoggingOptions.LOADING_MODELS); MyRender.Log.WriteLine("Length in meters: " + (float)tagData[MyImporterConstants.TAG_LENGTH_IN_METERS], LoggingOptions.LOADING_MODELS); MyRender.Log.WriteLine("Rescale to length in meters?: " + (bool)tagData[MyImporterConstants.TAG_RESCALE_TO_LENGTH_IN_METERS], LoggingOptions.LOADING_MODELS); MyRender.Log.WriteLine("SpecularShininess: " + m_specularShininess, LoggingOptions.LOADING_MODELS); MyRender.Log.WriteLine("SpecularPower: " + m_specularPower, LoggingOptions.LOADING_MODELS); MyRender.Log.WriteLine("RescaleFactor: " + m_rescaleFactor, LoggingOptions.LOADING_MODELS); MyRender.Log.WriteLine("BoundingBox: " + BoundingBox, LoggingOptions.LOADING_MODELS); MyRender.Log.WriteLine("BoundingSphere: " + BoundingSphere, LoggingOptions.LOADING_MODELS); MyPerformanceCounter.PerAppLifetime.MyModelsCount++; MyPerformanceCounter.PerAppLifetime.MyModelsMeshesCount += m_meshContainer.Count; MyPerformanceCounter.PerAppLifetime.MyModelsVertexesCount += GetVerticesCount(); MyPerformanceCounter.PerAppLifetime.MyModelsTrianglesCount += m_trianglesCount; ModelInfo = new MyModelInfo(GetTrianglesCount(), GetVerticesCount(), BoundingBoxSize); m_loadedData = true; m_importer.Clear(); MyRender.Log.DecreaseIndent(LoggingOptions.LOADING_MODELS); MyRender.Log.WriteLine("MyModel.LoadData -> END", LoggingOptions.LOADING_MODELS); MyRender.GetRenderProfiler().EndProfilingBlock(); } }