public ModelRoot AddLine(ModelRoot model, IEnumerable <GeoPoint> gpxPointsElevated, Vector4 vector4, float trailWidthMeters) { var scene = model.UseScene(TERRAIN_SCENE_NAME); var rnode = scene.FindNode(n => n.Name == TERRAIN_NODE_NAME); var rmesh = rnode.Mesh = FindOrCreateMesh(model, TERRAIN_MESH_NAME); var material = model.CreateMaterial("Line") .WithPBRMetallicRoughness(vector4, null, null, 1, 0.1f) .WithDoubleSide(true); var triangulation = _meshService.GenerateTriangleMesh_Line(gpxPointsElevated, trailWidthMeters); var indexedTriangulation = new IndexedTriangulation(triangulation.positions, triangulation.indexes); var normals = _meshService.ComputeNormals(indexedTriangulation.Positions, indexedTriangulation.Indices); // create mesh primitive var primitive = rmesh.CreatePrimitive() .WithVertexAccessor("POSITION", indexedTriangulation.Positions) .WithVertexAccessor("NORMAL", normals.ToList()) .WithIndicesAccessor(PrimitiveType.TRIANGLES, indexedTriangulation.Indices); primitive = primitive.WithMaterial(material); return(model); }
public ModelRoot AddLine(ModelRoot model, string nodeName, IEnumerable <GeoPoint> gpxPointsElevated, Vector4 color, float trailWidthMeters) { var scene = model.UseScene(TERRAIN_SCENE_NAME); var rnode = scene.FindNode(n => n.Name == nodeName); if (rnode == null) { rnode = scene.CreateNode(nodeName); } var rmesh = rnode.Mesh = FindOrCreateMesh(model, string.Concat(nodeName, "Mesh")); var material = model.CreateMaterial(string.Concat(nodeName, "Material")) .WithPBRMetallicRoughness(color, null, null, 0, 0.9f) .WithDoubleSide(true); material.Alpha = SharpGLTF.Schema2.AlphaMode.BLEND; var triangulation = _meshService.GenerateTriangleMesh_Line(gpxPointsElevated, trailWidthMeters); var normals = _meshService.ComputeMeshNormals(triangulation.Positions, triangulation.Indices); // create mesh primitive var primitive = rmesh.CreatePrimitive() .WithVertexAccessor("POSITION", triangulation.Positions) .WithVertexAccessor("NORMAL", normals.ToList()) .WithIndicesAccessor(PrimitiveType.TRIANGLES, triangulation.Indices); primitive = primitive.WithMaterial(material); return(model); }
public ModelRoot AddMesh(ModelRoot model, string nodeName, IndexedTriangulation indexedTriangulation, IEnumerable <Vector3> normals, PBRTexture textures, bool doubleSided = true) { // create a basic scene model = model ?? CreateNewModel(); var rnode = model.LogicalScenes.First()?.FindNode(n => n.Name == nodeName); if (rnode == null) { rnode = model.LogicalScenes.First().CreateNode(nodeName); } var rmesh = rnode.Mesh = FindOrCreateMesh(model, string.Concat(rnode.Name, "Mesh")); var material = model.CreateMaterial(string.Concat(nodeName, "Material")) .WithPBRMetallicRoughness(Vector4.One, textures?.BaseColorTexture?.FilePath, null, 0, 1) .WithDoubleSide(doubleSided); if (textures != null && textures.NormalTexture != null) { material.WithChannelTexture("NORMAL", 0, textures.NormalTexture.FilePath); } // create mesh primitive MeshPrimitive primitive = rmesh.CreatePrimitive(); if (indexedTriangulation.Colors != null && indexedTriangulation.Colors.Any()) { primitive = primitive.WithVertexAccessor("POSITION", indexedTriangulation.Positions); primitive = primitive.WithVertexAccessor("COLOR_0", indexedTriangulation.Colors); } else { primitive = primitive.WithVertexAccessor("POSITION", indexedTriangulation.Positions); } if (normals != null) { primitive = primitive.WithVertexAccessor("NORMAL", normals.ToList()); } primitive = primitive.WithIndicesAccessor(PrimitiveType.TRIANGLES, indexedTriangulation.Indices); if (textures != null && textures.TextureCoordSets == null) { (Vector3 Min, Vector3 Max)coordBounds = CalculateBounds(indexedTriangulation.Positions); textures.TextureCoordSets = indexedTriangulation.Positions.Select(pos => new Vector2( MathHelper.Map(coordBounds.Min.X, coordBounds.Max.X, 0, 1, pos.X, true) , MathHelper.Map(coordBounds.Min.Z, coordBounds.Max.Z, 0, 1, pos.Z, true) )); primitive = primitive .WithVertexAccessor("TEXCOORD_0", textures.TextureCoordSets.ToList()); } primitive = primitive.WithMaterial(material); return(model); }
public ModelRoot AddMesh(ModelRoot model, string nodeName, TriangulationList <Vector3> triangulation, Vector4 color = default, bool doubleSided = true) { if (color == default || triangulation.HasColors) { color = Vector4.One; } var scene = model.UseScene(TERRAIN_SCENE_NAME); var rnode = scene.FindNode(n => n.Name == nodeName); if (rnode == null) { rnode = scene.CreateNode(nodeName); } var rmesh = rnode.Mesh = FindOrCreateMesh(model, string.Concat(nodeName, "Mesh")); var material = model.CreateMaterial(string.Concat(nodeName, "Material")) .WithPBRMetallicRoughness(color, null, null, 0, 1f) .WithDoubleSide(doubleSided); material.Alpha = (color.W < 1.0 || (triangulation.HasColors && triangulation.Colors.Any(c => c.W < 1.0))) ? SharpGLTF.Schema2.AlphaMode.BLEND : SharpGLTF.Schema2.AlphaMode.OPAQUE; // Rotate for glTF compliance triangulation.Positions.ToGlTFSpace(); var normals = _meshService.ComputeMeshNormals(triangulation.Positions, triangulation.Indices); // create mesh primitive var primitive = rmesh.CreatePrimitive() .WithVertexAccessor("POSITION", triangulation.Positions) .WithVertexAccessor("NORMAL", normals.ToList()) .WithIndicesAccessor(PrimitiveType.TRIANGLES, triangulation.Indices); if (triangulation.HasColors) { primitive = primitive.WithVertexAccessor("COLOR_0", triangulation.Colors); } primitive = primitive.WithMaterial(material); return(model); }
public void AddGeometryResources(ModelRoot root, IEnumerable <SceneBuilder> srcScenes, SceneBuilderSchema2Settings settings) { // gather all unique MeshBuilders var srcMeshes = srcScenes .SelectMany(item => item.Instances) .Select(item => item.Content?.GetGeometryAsset()) .Where(item => item != null) .Distinct() .ToArray(); // gather all unique MaterialBuilders var materialGroups = srcMeshes .SelectMany(item => item.Primitives) .Where(item => !Geometry.MeshBuilderToolkit.IsEmpty(item)) .Select(item => item.Material) .Distinct() .ToList() // group by equal content, to reduce material splitting whenever possible. .GroupBy(item => item, Materials.MaterialBuilder.ContentComparer); // create a Schema2.Material for every MaterialBuilder. foreach (var mg in materialGroups) { var val = root.CreateMaterial(mg.Key); foreach (var key in mg) { _Materials[key] = val; } } // create a Schema2.Mesh for every MeshBuilder. var dstMeshes = root.CreateMeshes(mat => _Materials[mat], settings, srcMeshes); for (int i = 0; i < srcMeshes.Length; ++i) { _Meshes[srcMeshes[i]] = dstMeshes[i]; } // TODO: here we could check that every dstMesh has been correctly created. }
public ModelRoot AddTerrainMesh(ModelRoot model, Triangulation triangulation, PBRTexture textures) { // create a basic scene model = model ?? CreateNewModel(); var rnode = model.LogicalScenes.First()?.FindNode(n => n.Name == TERRAIN_NODE_NAME); var rmesh = rnode.Mesh = FindOrCreateMesh(model, TERRAIN_MESH_NAME); var material = model.CreateMaterial("Default") .WithPBRMetallicRoughness(Vector4.One, textures?.BaseColorTexture?.FilePath, null, 0, 1) .WithDoubleSide(true); if (textures != null && textures.NormalTexture != null) { material.WithChannelTexture("NORMAL", 0, textures.NormalTexture.FilePath); } var indexedTriangulation = new IndexedTriangulation(triangulation); var normals = _meshService.ComputeNormals(indexedTriangulation.Positions, indexedTriangulation.Indices); // create mesh primitive var primitive = rmesh.CreatePrimitive() .WithVertexAccessor("POSITION", indexedTriangulation.Positions) .WithVertexAccessor("NORMAL", normals.ToList()) .WithIndicesAccessor(PrimitiveType.TRIANGLES, indexedTriangulation.Indices); if (textures != null && textures.TextureCoordSets == null) { (Vector3 Min, Vector3 Max)coordBounds = CalculateBounds(indexedTriangulation.Positions); textures.TextureCoordSets = indexedTriangulation.Positions.Select(pos => new Vector2( MathHelper.Map(coordBounds.Min.X, coordBounds.Max.X, 0, 1, pos.X, true) , MathHelper.Map(coordBounds.Min.Z, coordBounds.Max.Z, 0, 1, pos.Z, true) )); primitive = primitive .WithVertexAccessor("TEXCOORD_0", textures.TextureCoordSets.ToList()); } primitive = primitive.WithMaterial(material); return(model); }
private Material GenerateGLTFMaterialFromRenderMaterial(VMaterial renderMaterial, ModelRoot model, string materialName) { var material = model .CreateMaterial(materialName) .WithDefault(); renderMaterial.IntParams.TryGetValue("F_TRANSLUCENT", out var isTranslucent); material.Alpha = isTranslucent > 0 ? AlphaMode.BLEND : AlphaMode.OPAQUE; float metalValue = 0; foreach (var floatParam in renderMaterial.FloatParams) { if (floatParam.Key == "g_flMetalness") { metalValue = floatParam.Value; } } // assume non-metallic unless prompted material.WithPBRMetallicRoughness(Vector4.One, null, metallicFactor: metalValue); foreach (var renderTexture in renderMaterial.TextureParams) { var texturePath = renderTexture.Value; var fileName = Path.GetFileNameWithoutExtension(texturePath); ProgressDialog.SetProgress($"Exporting texture: {texturePath}"); var textureResource = GuiContext.LoadFileByAnyMeansNecessary(texturePath + "_c"); if (textureResource == null) { continue; } var bitmap = ((ValveResourceFormat.ResourceTypes.Texture)textureResource.DataBlock).GenerateBitmap(); if (renderTexture.Key == "g_tColor" && material.Alpha == AlphaMode.OPAQUE) { // expensive transparency workaround for color maps for (int row = 0; row < bitmap.Width; row++) { for (int col = 0; col < bitmap.Height; col++) { var pixelAt = bitmap.GetPixel(row, col); bitmap.SetPixel(row, col, new SKColor(pixelAt.Red, pixelAt.Green, pixelAt.Blue, 255)); } } } var textureImage = SKImage.FromBitmap(bitmap); using var data = textureImage.Encode(SKEncodedImageFormat.Png, 100); var image = model.UseImageWithContent(data.ToArray()); // TODO find a way to change the image's URI to be the image name, right now it turns into (model)_0, (model)_1.... image.Name = fileName + $"_{model.LogicalImages.Count - 1}"; var sampler = model.UseTextureSampler(TextureWrapMode.REPEAT, TextureWrapMode.REPEAT, TextureMipMapFilter.NEAREST, TextureInterpolationFilter.DEFAULT); sampler.Name = fileName; var tex = model.UseTexture(image); tex.Name = fileName + $"_{model.LogicalTextures.Count - 1}"; tex.Sampler = sampler; switch (renderTexture.Key) { case "g_tColor": material.FindChannel("BaseColor")?.SetTexture(0, tex); var indexTexture = new JsonDictionary() { ["index"] = image.LogicalIndex }; var dict = material.TryUseExtrasAsDictionary(true); dict["baseColorTexture"] = indexTexture; break; case "g_tNormal": material.FindChannel("Normal")?.SetTexture(0, tex); break; case "g_tAmbientOcclusion": material.FindChannel("Occlusion")?.SetTexture(0, tex); break; case "g_tEmissive": material.FindChannel("Emissive")?.SetTexture(0, tex); break; case "g_tShadowFalloff": // example: tongue_gman, materials/default/default_skin_shadowwarp_tga_f2855b6e.vtex case "g_tCombinedMasks": // example: models/characters/gman/materials/gman_head_mouth_mask_tga_bb35dc38.vtex case "g_tDiffuseFalloff": // example: materials/default/default_skin_diffusewarp_tga_e58a9ed.vtex case "g_tIris": // example: case "g_tIrisMask": // example: models/characters/gman/materials/gman_eye_iris_mask_tga_a5bb4a1e.vtex case "g_tTintColor": // example: models/characters/lazlo/eyemeniscus_vmat_g_ttintcolor_a00ef19e.vtex case "g_tAnisoGloss": // example: gordon_beard, models/characters/gordon/materials/gordon_hair_normal_tga_272a44e9.vtex case "g_tBentNormal": // example: gman_teeth, materials/default/default_skin_shadowwarp_tga_f2855b6e.vtex case "g_tFresnelWarp": // example: brewmaster_color, materials/default/default_fresnelwarprim_tga_d9279d65.vtex case "g_tMasks1": // example: brewmaster_color, materials/models/heroes/brewmaster/brewmaster_base_metalnessmask_psd_58eaa40f.vtex case "g_tMasks2": // example: brewmaster_color,materials/models/heroes/brewmaster/brewmaster_base_specmask_psd_63e9fb90.vtex default: Console.WriteLine($"Warning: Unsupported Texture Type {renderTexture.Key}"); break; } } return(material); }