public GFModel(H3DModel mdl, H3DDict <H3DLUT> H3DLUTs) : this() { Name = mdl.Name; foreach (H3DBone Bone in mdl.Skeleton) { Skeleton.Add(new GFBone(Bone, mdl.Skeleton)); } foreach (H3DMaterial Material in mdl.Materials) { H3DMesh Mesh = null; foreach (H3DMesh M in mdl.Meshes) { if (mdl.Materials[M.MaterialIndex] == Material) { Mesh = M; break; } } Materials.Add(new GFMaterial(Material, Mesh)); } Transform = mdl.WorldTransform; PokemonBBoxGen.CreateModelBBox(mdl); H3DMetaDataValue BBox = mdl.MetaData[mdl.MetaData.Find(PokemonBBoxGen.BBOX_MIN_MAX)]; List <float> BBoxMinMax = (List <float>)BBox.Values; BBoxMinVector = new Vector4(BBoxMinMax[0], BBoxMinMax[1], BBoxMinMax[2], 1); BBoxMaxVector = new Vector4(BBoxMinMax[3], BBoxMinMax[4], BBoxMinMax[5], 1); foreach (H3DLUT LUT in H3DLUTs) { if (LUT.Name.Equals(DefaultLUTName)) { foreach (H3DLUTSampler Sampler in LUT.Samplers) { LUTs.Add(new GFLUT() { Type = GetLUTType(Sampler.Name, mdl.Materials), Name = Sampler.Name, Table = Sampler.Table }); } } } foreach (H3DMesh Mesh in mdl.Meshes) { Meshes.Add(new GFMesh(Mesh, mdl)); } }
public GFSubMesh(H3DSubMesh SubMesh, H3DMesh Parent, List <PICAVertex> Vertices, string Name) : this() { this.Name = Name; BoneIndicesCount = (byte)SubMesh.BoneIndicesCount; BoneIndices = new byte[SubMesh.BoneIndicesCount]; for (int i = 0; i < SubMesh.BoneIndicesCount; i++) { BoneIndices[i] = (byte)SubMesh.BoneIndices[i]; } Indices = SubMesh.Indices; PrimitiveMode = SubMesh.PrimitiveMode; VertexStride = Parent.VertexStride; Attributes = Parent.Attributes; foreach (PICAFixedAttribute Old in Parent.FixedAttributes) { PICAFixedAttribute New = new PICAFixedAttribute() { Name = Old.Name, Value = Old.Value }; FixedAttributes.Add(New); } List <PICAVertex> NewVertices = new List <PICAVertex>(); Dictionary <ushort, ushort> OldNewIndexMap = new Dictionary <ushort, ushort>(); ushort[] NewIndices = new ushort[Indices.Length]; for (int i = 0; i < NewIndices.Length; i++) { if (OldNewIndexMap.ContainsKey(Indices[i])) { NewIndices[i] = OldNewIndexMap[Indices[i]]; } else { PICAVertex Vertex = Vertices[Indices[i]]; ushort NewIndex = (ushort)NewVertices.Count; NewVertices.Add(Vertex); NewIndices[i] = NewIndex; OldNewIndexMap.Add(Indices[i], NewIndex); } } Indices = NewIndices; IsIdx8Bits = /*NewIndices.Length <= 0x100*/ false; RawBuffer = VerticesConverter.GetBuffer(NewVertices, Attributes); }
private static void CreateMetaDataAndAddValue(H3DMesh Mesh, H3DMetaDataValue Value) { if (Mesh.MetaData == null) { Mesh.MetaData = new H3DMetaData(); } int Find = Mesh.MetaData.Find(Value.Name); if (Find != -1) { Mesh.MetaData.Remove(Mesh.MetaData[Find]); } Mesh.MetaData.Add(Value); }
public static PICAVertex[] GetWorldSpaceVertices(H3DDict <H3DBone> Skeleton, H3DMesh Mesh) { PICAVertex[] Vertices = Mesh.GetVertices(); bool[] TransformedVertices = new bool[Vertices.Length]; //Smooth meshes are already in World Space, so we don't need to do anything. if (Mesh.Skinning != H3DMeshSkinning.Smooth) { foreach (H3DSubMesh SM in Mesh.SubMeshes) { foreach (ushort i in SM.Indices) { if (TransformedVertices[i]) { continue; } TransformedVertices[i] = true; PICAVertex v = Vertices[i]; if (Skeleton != null && Skeleton.Count > 0 && SM.Skinning != H3DSubMeshSkinning.Smooth) { int b = SM.BoneIndices[v.Indices[0]]; Matrix4x4 Transform = Skeleton[b].GetWorldTransform(Skeleton); v.Position = Vector4.Transform(new Vector3( v.Position.X, v.Position.Y, v.Position.Z), Transform); v.Normal.W = 0; v.Normal = Vector4.Transform(v.Normal, Transform); v.Normal = Vector4.Normalize(v.Normal); } Vertices[i] = v; } } } return(Vertices); }
private static void UpdateMeshListItem(H3DMesh mesh, ListViewItem item) { string materialName = ""; if (mesh.Parent.Materials.Count > mesh.MaterialIndex) { materialName = mesh.Parent.Materials[mesh.MaterialIndex].Name; } item.SubItems.Clear(); item.Tag = mesh; item.Text = mesh.NodeIndex.ToString(); item.SubItems.Add(materialName); item.SubItems.Add($"mesh_{materialName}"); item.SubItems.Add(GetLayerString(mesh.Layer)); item.SubItems.Add(mesh.Priority.ToString()); }
public GFSubMesh(H3DSubMesh SubMesh, H3DMesh Parent, List <PICAVertex> Vertices, string Name) { this.Name = Name; BoneIndicesCount = (byte)SubMesh.BoneIndicesCount; BoneIndices = new byte[SubMesh.BoneIndicesCount]; for (int i = 0; i < SubMesh.BoneIndicesCount; i++) { BoneIndices[i] = (byte)SubMesh.BoneIndices[i]; } Indices = SubMesh.Indices; IsIdx8Bits = true; foreach (ushort Index in Indices) { if (Index > 0xFF) { IsIdx8Bits = false; break; } } PrimitiveMode = SubMesh.PrimitiveMode; VertexStride = Parent.VertexStride; Attributes = Parent.Attributes; FixedAttributes = Parent.FixedAttributes; List <PICAVertex> NewVertices = new List <PICAVertex>(); ushort[] NewIndices = new ushort[Indices.Length]; for (int i = 0; i < NewIndices.Length; i++) { PICAVertex Vertex = Vertices[Indices[i]]; int NewIndex = NewVertices.IndexOf(Vertex); if (NewIndex == -1) { NewIndex = NewVertices.Count; NewVertices.Add(Vertex); } NewIndices[i] = (ushort)NewIndex; } Indices = NewIndices; RawBuffer = VerticesConverter.GetBuffer(NewVertices, Attributes); }
public static List <PICAVertex> GetVerticesList(H3DDict <H3DBone> Skeleton, H3DMesh Mesh) { List <PICAVertex> Output = new List <PICAVertex>(); PICAVertex[] Vertices = Mesh.GetVertices(); foreach (H3DSubMesh SM in Mesh.SubMeshes) { foreach (ushort i in SM.Indices) { PICAVertex v = Vertices[i]; if (Skeleton != null && Skeleton.Count > 0 && SM.Skinning != H3DSubMeshSkinning.Smooth) { int b = SM.BoneIndices[v.Indices[0]]; Matrix4x4 Transform = Skeleton[b].GetWorldTransform(Skeleton); v.Position = Vector4.Transform(new Vector3( v.Position.X, v.Position.Y, v.Position.Z), Transform); v.Normal.W = 0; v.Normal = Vector4.Transform(v.Normal, Transform); v.Normal = Vector4.Normalize(v.Normal); } for (int b = 0; b < 4 && v.Weights[b] > 0; b++) { v.Indices[b] = SM.BoneIndices[v.Indices[b]]; } Output.Add(v); } } return(Output); }
public GFMesh(H3DMesh Mesh, H3DModel Parent) : this() { if (Mesh.NodeIndex >= 0 && Mesh.NodeIndex < Parent.MeshNodesTree.Count) { Name = Parent.MeshNodesTree.Find(Mesh.NodeIndex); } else { Name = "Mesh_" + Parent.Meshes.IndexOf(Mesh); } if (Mesh.MetaData.Find(PokemonBBoxGen.BBOX_MIN_MAX) == -1) { PokemonBBoxGen.CreateModelBBox(Parent); } H3DMetaDataValue BBox = Mesh.MetaData[Mesh.MetaData.Find(PokemonBBoxGen.BBOX_MIN_MAX)]; List <float> BBoxMinMax = (List <float>)BBox.Values; BBoxMinVector = new Vector4(BBoxMinMax[0], BBoxMinMax[1], BBoxMinMax[2], 1); BBoxMaxVector = new Vector4(BBoxMinMax[3], BBoxMinMax[4], BBoxMinMax[5], 1); BoneIndicesPerVertex = 4; int SubMeshIdx = 0; List <PICAVertex> Vertices = Mesh.GetVertices().ToList(); foreach (H3DSubMesh SubMesh in Mesh.SubMeshes) { string MaterialName; if (Mesh.MaterialIndex >= 0 && Mesh.MaterialIndex < Parent.Materials.Count) { MaterialName = Parent.Materials[Mesh.MaterialIndex].Name; } else { MaterialName = null; } SubMeshes.Add(new GFSubMesh(SubMesh, Mesh, Vertices, MaterialName)); SubMeshIdx++; } }
public DAE(H3D Scene, int MdlIndex, int AnimIndex = -1) { if (MdlIndex != -1) { library_visual_scenes = new List <DAEVisualScene>(); H3DModel Mdl = Scene.Models[MdlIndex]; DAEVisualScene VN = new DAEVisualScene(); VN.name = $"{Mdl.Name}_{MdlIndex.ToString("D2")}"; VN.id = $"{VN.name}_id"; //Materials if (Mdl.Materials.Count > 0) { library_materials = new List <DAEMaterial>(); library_effects = new List <DAEEffect>(); } foreach (H3DMaterial Mtl in Mdl.Materials) { string MtlName = $"{MdlIndex.ToString("D2")}_{Mtl.Name}"; DAEEffect Effect = new DAEEffect(); Effect.name = $"{Mtl.Name}_eff"; Effect.id = $"{Effect.name}_id"; DAEEffectParam ImgSurface = new DAEEffectParam(); DAEEffectParam ImgSampler = new DAEEffectParam(); ImgSurface.surface = new DAEEffectParamSurfaceElement(); ImgSampler.sampler2D = new DAEEffectParamSampler2DElement(); ImgSurface.sid = $"{Mtl.Name}_surf"; ImgSurface.surface.type = "2D"; ImgSurface.surface.init_from = Mtl.Texture0Name; ImgSurface.surface.format = "PNG"; ImgSampler.sid = $"{Mtl.Name}_samp"; ImgSampler.sampler2D.source = ImgSurface.sid; ImgSampler.sampler2D.wrap_s = Mtl.TextureMappers[0].WrapU.ToDAEWrap(); ImgSampler.sampler2D.wrap_t = Mtl.TextureMappers[0].WrapV.ToDAEWrap(); ImgSampler.sampler2D.minfilter = Mtl.TextureMappers[0].MinFilter.ToDAEFilter(); ImgSampler.sampler2D.magfilter = Mtl.TextureMappers[0].MagFilter.ToDAEFilter(); ImgSampler.sampler2D.mipfilter = DAEFilter.LINEAR; Effect.profile_COMMON.newparam.Add(ImgSurface); Effect.profile_COMMON.newparam.Add(ImgSampler); Effect.profile_COMMON.technique.sid = $"{Mtl.Name}_tech"; Effect.profile_COMMON.technique.phong.diffuse.texture.texture = ImgSampler.sid; library_effects.Add(Effect); DAEMaterial Material = new DAEMaterial(); Material.name = $"{Mtl.Name}_mat"; Material.id = $"{Material.name}_id"; Material.instance_effect.url = $"#{Effect.id}"; library_materials.Add(Material); } //Skeleton nodes string RootBoneId = string.Empty; if ((Mdl.Skeleton?.Count ?? 0) > 0) { Queue <Tuple <H3DBone, DAENode> > ChildBones = new Queue <Tuple <H3DBone, DAENode> >(); DAENode RootNode = new DAENode(); ChildBones.Enqueue(Tuple.Create(Mdl.Skeleton[0], RootNode)); RootBoneId = $"#{Mdl.Skeleton[0].Name}_bone_id"; while (ChildBones.Count > 0) { Tuple <H3DBone, DAENode> Bone_Node = ChildBones.Dequeue(); H3DBone Bone = Bone_Node.Item1; Bone_Node.Item2.id = $"{Bone.Name}_bone_id"; Bone_Node.Item2.name = Bone.Name; Bone_Node.Item2.sid = Bone.Name; Bone_Node.Item2.type = DAENodeType.JOINT; Bone_Node.Item2.SetBoneEuler(Bone.Translation, Bone.Rotation, Bone.Scale); foreach (H3DBone B in Mdl.Skeleton) { if (B.ParentIndex == -1) { continue; } H3DBone ParentBone = Mdl.Skeleton[B.ParentIndex]; if (ParentBone == Bone) { DAENode Node = new DAENode(); ChildBones.Enqueue(Tuple.Create(B, Node)); if (Bone_Node.Item2.Nodes == null) { Bone_Node.Item2.Nodes = new List <DAENode>(); } Bone_Node.Item2.Nodes.Add(Node); } } } VN.node.Add(RootNode); } //Mesh if (Mdl.Meshes.Count > 0) { library_geometries = new List <DAEGeometry>(); } for (int MeshIndex = 0; MeshIndex < Mdl.Meshes.Count; MeshIndex++) { if (Mdl.Meshes[MeshIndex].Type == H3DMeshType.Silhouette) { continue; } H3DMesh Mesh = Mdl.Meshes[MeshIndex]; PICAVertex[] Vertices = MeshTransform.GetWorldSpaceVertices(Mdl.Skeleton, Mesh); string MtlName = $"Mdl_{MdlIndex}_Mtl_{Mdl.Materials[Mesh.MaterialIndex].Name}"; string MtlTgt = library_materials[Mesh.MaterialIndex].id; for (int SMIndex = 0; SMIndex < Mesh.SubMeshes.Count; SMIndex++) { H3DSubMesh SM = Mesh.SubMeshes[SMIndex]; string ShortName = string.Empty; if (Mdl.MeshNodesTree != null && Mesh.NodeIndex < Mdl.MeshNodesTree.Count) { ShortName = Mdl.MeshNodesTree.Find(Mesh.NodeIndex); } string MeshName = $"{ShortName}_{MeshIndex}_{SMIndex}"; DAEGeometry Geometry = new DAEGeometry(); Geometry.name = MeshName; Geometry.id = $"{Geometry.name}_geo_id"; //Geometry string VertsId = $"{MeshName}_vtx_id"; Geometry.mesh.vertices.id = VertsId; Geometry.mesh.triangles.material = MtlName; Geometry.mesh.triangles.AddInput("VERTEX", $"#{VertsId}"); Geometry.mesh.triangles.Set_p(SM.Indices); foreach (PICAAttribute Attr in Mesh.Attributes) { if (Attr.Name >= PICAAttributeName.BoneIndex) { continue; } string[] Values = new string[Vertices.Length]; for (int Index = 0; Index < Vertices.Length; Index++) { PICAVertex v = Vertices[Index]; switch (Attr.Name) { case PICAAttributeName.Position: Values[Index] = DAEUtils.Vector3Str(v.Position); break; case PICAAttributeName.Normal: Values[Index] = DAEUtils.Vector3Str(v.Normal); break; case PICAAttributeName.Tangent: Values[Index] = DAEUtils.Vector3Str(v.Tangent); break; case PICAAttributeName.Color: Values[Index] = DAEUtils.Vector4Str(v.Color); break; case PICAAttributeName.TexCoord0: Values[Index] = DAEUtils.Vector2Str(v.TexCoord0); break; case PICAAttributeName.TexCoord1: Values[Index] = DAEUtils.Vector2Str(v.TexCoord1); break; case PICAAttributeName.TexCoord2: Values[Index] = DAEUtils.Vector2Str(v.TexCoord2); break; } } int Elements = 0; switch (Attr.Name) { case PICAAttributeName.Position: Elements = 3; break; case PICAAttributeName.Normal: Elements = 3; break; case PICAAttributeName.Tangent: Elements = 3; break; case PICAAttributeName.Color: Elements = 4; break; case PICAAttributeName.TexCoord0: Elements = 2; break; case PICAAttributeName.TexCoord1: Elements = 2; break; case PICAAttributeName.TexCoord2: Elements = 2; break; } DAESource Source = new DAESource(); Source.name = $"{MeshName}_{Attr.Name}"; Source.id = $"{Source.name}_id"; Source.float_array = new DAEArray() { id = $"{Source.name}_array_id", count = (uint)(Vertices.Length * Elements), data = string.Join(" ", Values) }; DAEAccessor Accessor = new DAEAccessor() { source = $"#{Source.float_array.id}", count = (uint)Vertices.Length, stride = (uint)Elements }; switch (Elements) { case 2: Accessor.AddParams("float", "S", "T"); break; case 3: Accessor.AddParams("float", "X", "Y", "Z"); break; case 4: Accessor.AddParams("float", "R", "G", "B", "A"); break; } Source.technique_common.accessor = Accessor; Geometry.mesh.source.Add(Source); if (Attr.Name < PICAAttributeName.Color) { string Semantic = string.Empty; switch (Attr.Name) { case PICAAttributeName.Position: Semantic = "POSITION"; break; case PICAAttributeName.Normal: Semantic = "NORMAL"; break; case PICAAttributeName.Tangent: Semantic = "TANGENT"; break; } Geometry.mesh.vertices.AddInput(Semantic, $"#{Source.id}"); } else if (Attr.Name == PICAAttributeName.Color) { Geometry.mesh.triangles.AddInput("COLOR", $"#{Source.id}", 0); } else { Geometry.mesh.triangles.AddInput("TEXCOORD", $"#{Source.id}", 0, (uint)Attr.Name - 4); } } //Attributes Loop library_geometries.Add(Geometry); //Controller bool HasController = SM.BoneIndicesCount > 0 && (Mdl.Skeleton?.Count ?? 0) > 0; DAEController Controller = new DAEController(); if (HasController) { if (library_controllers == null) { library_controllers = new List <DAEController>(); } Controller.name = $"{MeshName}_ctrl"; Controller.id = $"{Controller.name}_id"; Controller.skin.source = $"#{Geometry.id}"; Controller.skin.vertex_weights.count = (uint)Vertices.Length; string[] BoneNames = new string[Mdl.Skeleton.Count]; string[] BindPoses = new string[Mdl.Skeleton.Count]; for (int Index = 0; Index < Mdl.Skeleton.Count; Index++) { BoneNames[Index] = Mdl.Skeleton[Index].Name; BindPoses[Index] = DAEUtils.MatrixStr(Mdl.Skeleton[Index].InverseTransform); } //4 is the max number of bones per vertex int[] v = new int[Vertices.Length * 4 * 2]; int[] vcount = new int[Vertices.Length]; Dictionary <string, int> Weights = new Dictionary <string, int>(); int vi = 0, vci = 0; if (SM.Skinning == H3DSubMeshSkinning.Smooth) { foreach (PICAVertex Vertex in Vertices) { int Count = 0; for (int Index = 0; Index < 4; Index++) { int BIndex = Vertex.Indices[Index]; float Weight = Vertex.Weights[Index]; if (Weight == 0) { break; } if (BIndex < SM.BoneIndices.Length && BIndex > -1) { BIndex = SM.BoneIndices[BIndex]; } else { BIndex = 0; } string WStr = Weight.ToString(CultureInfo.InvariantCulture); v[vi++] = BIndex; if (Weights.ContainsKey(WStr)) { v[vi++] = Weights[WStr]; } else { v[vi++] = Weights.Count; Weights.Add(WStr, Weights.Count); } Count++; } vcount[vci++] = Count; } } else { foreach (PICAVertex Vertex in Vertices) { int BIndex = Vertex.Indices[0]; if (BIndex < SM.BoneIndices.Length && BIndex > -1) { BIndex = SM.BoneIndices[BIndex]; } else { BIndex = 0; } v[vi++] = BIndex; v[vi++] = 0; vcount[vci++] = 1; } Weights.Add("1", 0); } Array.Resize(ref v, vi); Controller.skin.src.Add(new DAESource($"{Controller.name}_names", 1, BoneNames, "JOINT", "Name")); Controller.skin.src.Add(new DAESource($"{Controller.name}_poses", 16, BindPoses, "TRANSFORM", "float4x4")); Controller.skin.src.Add(new DAESource($"{Controller.name}_weights", 1, Weights.Keys.ToArray(), "WEIGHT", "float")); Controller.skin.joints.AddInput("JOINT", $"#{Controller.skin.src[0].id}"); Controller.skin.joints.AddInput("INV_BIND_MATRIX", $"#{Controller.skin.src[1].id}"); Controller.skin.vertex_weights.AddInput("JOINT", $"#{Controller.skin.src[0].id}", 0); Controller.skin.vertex_weights.AddInput("WEIGHT", $"#{Controller.skin.src[2].id}", 1); Controller.skin.vertex_weights.vcount = string.Join(" ", vcount); Controller.skin.vertex_weights.v = string.Join(" ", v); library_controllers.Add(Controller); } //Mesh node DAENode Node = new DAENode(); Node.name = $"{MeshName}_node"; Node.id = $"{Node.name}_id"; Node.matrix = DAEMatrix.Identity; DAENodeInstance NodeInstance = new DAENodeInstance(); NodeInstance.url = $"#{(HasController ? Controller.id : Geometry.id)}"; NodeInstance.bind_material.technique_common.instance_material.symbol = MtlName; NodeInstance.bind_material.technique_common.instance_material.target = $"#{MtlTgt}"; if (HasController) { NodeInstance.skeleton = $"#{VN.node[0].id}"; Node.instance_controller = NodeInstance; } else { Node.instance_geometry = NodeInstance; } VN.node.Add(Node); } //SubMesh Loop } //Mesh Loop library_visual_scenes.Add(VN); if (library_visual_scenes.Count > 0) { scene.instance_visual_scene.url = $"#{library_visual_scenes[0].id}"; } library_images = new List <DAEImage>(); foreach (H3DTexture Tex in Scene.Textures) { //library_images.Add(new DAEImage() //{ // id = Tex.Name, // init_from = $"./{Tex.Name}.png" //}); } foreach (var mat in Scene.Models[MdlIndex].Materials) { if (mat.Texture0Name != null && !LibImgContainsThing(mat.Texture0Name)) { library_images.Add(new DAEImage() { id = mat.Texture0Name, init_from = $"./{mat.Texture0Name}.png" }); } if (mat.Texture1Name != null && !LibImgContainsThing(mat.Texture1Name)) { library_images.Add(new DAEImage() { id = mat.Texture0Name, init_from = $"./{mat.Texture0Name}.png" }); } if (mat.Texture2Name != null && !LibImgContainsThing(mat.Texture2Name)) { library_images.Add(new DAEImage() { id = mat.Texture0Name, init_from = $"./{mat.Texture0Name}.png" }); } } } //MdlIndex != -1 if (AnimIndex != -1) { library_animations = new List <DAEAnimation>(); string[] AnimElemNames = { "translate", "rotateX", "rotateY", "rotateZ", "scale" }; H3DAnimation SklAnim = Scene.SkeletalAnimations[AnimIndex]; H3DDict <H3DBone> Skeleton = Scene.Models[0].Skeleton; int FramesCount = (int)SklAnim.FramesCount + 1; foreach (H3DAnimationElement Elem in SklAnim.Elements) { if (Elem.PrimitiveType != H3DPrimitiveType.Transform && Elem.PrimitiveType != H3DPrimitiveType.QuatTransform) { continue; } H3DBone SklBone = Skeleton.FirstOrDefault(x => x.Name == Elem.Name); H3DBone Parent = null; if (SklBone != null && SklBone.ParentIndex != -1) { Parent = Skeleton[SklBone.ParentIndex]; } for (int i = 0; i < 5; i++) { string[] AnimTimes = new string[FramesCount]; string[] AnimPoses = new string[FramesCount]; string[] AnimLerps = new string[FramesCount]; bool IsRotation = i > 0 && i < 4; //1, 2, 3 bool Skip = Elem.PrimitiveType != H3DPrimitiveType.Transform && Elem.PrimitiveType != H3DPrimitiveType.QuatTransform; if (!Skip) { if (Elem.Content is H3DAnimTransform Transform) { switch (i) { case 0: Skip = !Transform.TranslationExists; break; case 1: Skip = !Transform.RotationX.Exists; break; case 2: Skip = !Transform.RotationY.Exists; break; case 3: Skip = !Transform.RotationZ.Exists; break; case 4: Skip = !Transform.ScaleExists; break; } } else if (Elem.Content is H3DAnimQuatTransform QuatTransform) { switch (i) { case 0: Skip = !QuatTransform.HasTranslation; break; case 1: Skip = !QuatTransform.HasRotation; break; case 2: Skip = !QuatTransform.HasRotation; break; case 3: Skip = !QuatTransform.HasRotation; break; case 4: Skip = !QuatTransform.HasScale; break; } } } if (Skip) { continue; } for (int Frame = 0; Frame < FramesCount; Frame++) { string StrTrans = string.Empty; H3DAnimationElement PElem = SklAnim.Elements.FirstOrDefault(x => x.Name == Parent?.Name); Vector3 InvScale = Vector3.One; if (Elem.Content is H3DAnimTransform Transform) { //Compensate parent bone scale (basically, don't inherit scales) if (Parent != null && (SklBone.Flags & H3DBoneFlags.IsSegmentScaleCompensate) != 0) { if (PElem != null) { H3DAnimTransform PTrans = (H3DAnimTransform)PElem.Content; InvScale /= new Vector3( PTrans.ScaleX.Exists ? PTrans.ScaleX.GetFrameValue(Frame) : Parent.Scale.X, PTrans.ScaleY.Exists ? PTrans.ScaleY.GetFrameValue(Frame) : Parent.Scale.Y, PTrans.ScaleZ.Exists ? PTrans.ScaleZ.GetFrameValue(Frame) : Parent.Scale.Z); } else { InvScale /= Parent.Scale; } } switch (i) { //Translation case 0: StrTrans = DAEUtils.VectorStr(new Vector3( Transform.TranslationX.Exists //X ? Transform.TranslationX.GetFrameValue(Frame) : SklBone.Translation.X, Transform.TranslationY.Exists //Y ? Transform.TranslationY.GetFrameValue(Frame) : SklBone.Translation.Y, Transform.TranslationZ.Exists //Z ? Transform.TranslationZ.GetFrameValue(Frame) : SklBone.Translation.Z)); break; //Scale case 4: StrTrans = DAEUtils.VectorStr(InvScale * new Vector3( Transform.ScaleX.Exists //X ? Transform.ScaleX.GetFrameValue(Frame) : SklBone.Scale.X, Transform.ScaleY.Exists //Y ? Transform.ScaleY.GetFrameValue(Frame) : SklBone.Scale.Y, Transform.ScaleZ.Exists //Z ? Transform.ScaleZ.GetFrameValue(Frame) : SklBone.Scale.Z)); break; //Rotation case 1: StrTrans = DAEUtils.RadToDegStr(Transform.RotationX.GetFrameValue(Frame)); break; case 2: StrTrans = DAEUtils.RadToDegStr(Transform.RotationY.GetFrameValue(Frame)); break; case 3: StrTrans = DAEUtils.RadToDegStr(Transform.RotationZ.GetFrameValue(Frame)); break; } } else if (Elem.Content is H3DAnimQuatTransform QuatTransform) { //Compensate parent bone scale (basically, don't inherit scales) if (Parent != null && (SklBone.Flags & H3DBoneFlags.IsSegmentScaleCompensate) != 0) { if (PElem != null) { InvScale /= ((H3DAnimQuatTransform)PElem.Content).GetScaleValue(Frame); } else { InvScale /= Parent.Scale; } } switch (i) { case 0: StrTrans = DAEUtils.VectorStr(QuatTransform.GetTranslationValue(Frame)); break; case 1: StrTrans = DAEUtils.RadToDegStr(QuatTransform.GetRotationValue(Frame).ToEuler().X); break; case 2: StrTrans = DAEUtils.RadToDegStr(QuatTransform.GetRotationValue(Frame).ToEuler().Y); break; case 3: StrTrans = DAEUtils.RadToDegStr(QuatTransform.GetRotationValue(Frame).ToEuler().Z); break; case 4: StrTrans = DAEUtils.VectorStr(InvScale * QuatTransform.GetScaleValue(Frame)); break; } } //This is the Time in seconds, so we divide by the target FPS AnimTimes[Frame] = (Frame / 30f).ToString(CultureInfo.InvariantCulture); AnimPoses[Frame] = StrTrans; AnimLerps[Frame] = "LINEAR"; } DAEAnimation Anim = new DAEAnimation(); Anim.name = $"{SklAnim.Name}_{Elem.Name}_{AnimElemNames[i]}"; Anim.id = $"{Anim.name}_id"; Anim.src.Add(new DAESource($"{Anim.name}_frame", 1, AnimTimes, "TIME", "float")); Anim.src.Add(new DAESource($"{Anim.name}_interp", 1, AnimLerps, "INTERPOLATION", "Name")); Anim.src.Add(IsRotation ? new DAESource($"{Anim.name}_pose", 1, AnimPoses, "ANGLE", "float") : new DAESource($"{Anim.name}_pose", 3, AnimPoses, "X", "float", "Y", "float", "Z", "float")); Anim.sampler.AddInput("INPUT", $"#{Anim.src[0].id}"); Anim.sampler.AddInput("INTERPOLATION", $"#{Anim.src[1].id}"); Anim.sampler.AddInput("OUTPUT", $"#{Anim.src[2].id}"); Anim.sampler.id = $"{Anim.name}_samp_id"; Anim.channel.source = $"#{Anim.sampler.id}"; Anim.channel.target = $"{Elem.Name}_bone_id/{AnimElemNames[i]}"; if (IsRotation) { Anim.channel.target += ".ANGLE"; } library_animations.Add(Anim); } //Axis 0-5 } //SklAnim.Elements } //AnimIndex != -1 }
public Mesh(Model Parent, H3DMesh BaseMesh) { this.Parent = Parent; this.BaseMesh = BaseMesh; Material = Parent.BaseModel.Materials[BaseMesh.MaterialIndex]; PosOffs = BaseMesh.PositionOffset.ToVector4(); int VtxCount = 1, FAOffset = 0; if (BaseMesh.VertexStride > 0) { VtxCount = BaseMesh.RawBuffer.Length / BaseMesh.VertexStride; FAOffset = BaseMesh.RawBuffer.Length; } byte[] Buffer; using (MemoryStream VertexStream = new MemoryStream()) { BinaryWriter Writer = new BinaryWriter(VertexStream); Writer.Write(BaseMesh.RawBuffer); VertexStream.Seek(0, SeekOrigin.End); foreach (PICAFixedAttribute Attrib in BaseMesh.FixedAttributes) { /* * OpenGL doesn't support constant attributes, so we need to write * them as a tight array (waste of space). */ for (int i = 0; i < VtxCount; i++) { Writer.Write(Attrib.Value.X); Writer.Write(Attrib.Value.Y); Writer.Write(Attrib.Value.Z); Writer.Write(Attrib.Value.W); } } Buffer = VertexStream.ToArray(); } IntPtr Length = new IntPtr(Buffer.Length); VBOHandle = GL.GenBuffer(); VAOHandle = GL.GenVertexArray(); GL.BindBuffer(BufferTarget.ArrayBuffer, VBOHandle); GL.BufferData(BufferTarget.ArrayBuffer, Length, Buffer, BufferUsageHint.StaticDraw); GL.BindBuffer(BufferTarget.ArrayBuffer, 0); GL.BindVertexArray(VAOHandle); int Offset = 0; int Stride = BaseMesh.VertexStride; for (int AttribIndex = 0; AttribIndex < 16; AttribIndex++) { GL.DisableVertexAttribArray(AttribIndex); } foreach (PICAAttribute Attrib in BaseMesh.Attributes) { int Size = Attrib.Elements; VertexAttribPointerType Type = VertexAttribPointerType.Byte; switch (Attrib.Format) { case PICAAttributeFormat.Byte: Type = VertexAttribPointerType.Byte; break; case PICAAttributeFormat.Ubyte: Type = VertexAttribPointerType.UnsignedByte; break; case PICAAttributeFormat.Short: Type = VertexAttribPointerType.Short; Size <<= 1; break; case PICAAttributeFormat.Float: Type = VertexAttribPointerType.Float; Size <<= 2; break; } int AttribIndex = (int)Attrib.Name; GL.EnableVertexAttribArray(AttribIndex); GL.BindBuffer(BufferTarget.ArrayBuffer, VBOHandle); //Short and Float types needs to be aligned into 2 bytes boundaries. if (Attrib.Format != PICAAttributeFormat.Byte && Attrib.Format != PICAAttributeFormat.Ubyte) { Offset += Offset & 1; } GL.VertexAttribPointer(AttribIndex, Attrib.Elements, Type, false, Stride, Offset); SetScale(Attrib.Name, Attrib.Scale); Offset += Size; } foreach (PICAFixedAttribute Attrib in BaseMesh.FixedAttributes) { int AttribIndex = (int)Attrib.Name; GL.EnableVertexAttribArray(AttribIndex); GL.BindBuffer(BufferTarget.ArrayBuffer, VBOHandle); GL.VertexAttribPointer(AttribIndex, 4, VertexAttribPointerType.Float, false, 0, FAOffset); /* * Pokémon Sun/Moon seems to have fixed attributes for all unused attributes, * with the vector set to zero (?). On the H3D shader this would normally * make the Tangent scale one, and this signals the shader to use the Tangent * to calculate the normal quaternion, and that would ruin the lighting * 'cause the tangent is actually zero, so we force it to use normals by * setting the Scale to zero here. Using the original Sun/Moon shaders * should avoid this issue entirely. */ SetScale(Attrib.Name, Attrib.Name != PICAAttributeName.Tangent ? 1 : 0); FAOffset += 0x10 * VtxCount; } GL.BindVertexArray(0); }
public H3DModel ToH3DModel() { H3DModel Output = new H3DModel() { Name = Name }; //Skeleton foreach (GFBone Bone in Skeleton) { Output.Skeleton.Add(new H3DBone() { ParentIndex = (short)Skeleton.FindIndex(x => x.Name == Bone.Parent), Name = Bone.Name, Scale = Bone.Scale, Rotation = Bone.Rotation, Translation = Bone.Translation }); } foreach (H3DBone Bone in Output.Skeleton) { Bone.CalculateTransform(Output.Skeleton); Bone.Flags |= H3DBoneFlags.IsSegmentScaleCompensate; } if (Output.Skeleton.Count > 0) { Output.Flags = H3DModelFlags.HasSkeleton; } //Materials foreach (GFMaterial Material in Materials) { H3DMaterial Mat = new H3DMaterial(); H3DMaterialParams Params = Mat.MaterialParams; Mat.Name = Material.MaterialName; Params.FragmentFlags = H3DFragmentFlags.IsLUTReflectionEnabled; Array.Copy(Material.TextureSources, Params.TextureSources, 4); for (int Unit = 0; Unit < Material.TextureCoords.Length; Unit++) { string TextureName = Material.TextureCoords[Unit].Name; Mat.EnabledTextures[Unit] = TextureName != null; switch (Unit) { case 0: Mat.Texture0Name = TextureName; break; case 1: Mat.Texture1Name = TextureName; break; case 2: Mat.Texture2Name = TextureName; break; } //Texture Coords GFTextureMappingType MappingType = Material.TextureCoords[Unit].MappingType; Params.TextureCoords[Unit].MappingType = (H3DTextureMappingType)MappingType; Params.TextureCoords[Unit].Scale = Material.TextureCoords[Unit].Scale; Params.TextureCoords[Unit].Rotation = Material.TextureCoords[Unit].Rotation; Params.TextureCoords[Unit].Translation = Material.TextureCoords[Unit].Translation; //Texture Mapper Mat.TextureMappers[Unit].WrapU = (PICATextureWrap)Material.TextureCoords[Unit].WrapU; Mat.TextureMappers[Unit].WrapV = (PICATextureWrap)Material.TextureCoords[Unit].WrapV; Mat.TextureMappers[Unit].MagFilter = (H3DTextureMagFilter)Material.TextureCoords[Unit].MagFilter; Mat.TextureMappers[Unit].MinFilter = (H3DTextureMinFilter)Material.TextureCoords[Unit].MinFilter; Mat.TextureMappers[Unit].MinLOD = (byte)Material.TextureCoords[Unit].MinLOD; Mat.TextureMappers[Unit].BorderColor = Material.BorderColor[Unit]; } Params.EmissionColor = Material.EmissionColor; Params.AmbientColor = Material.AmbientColor; Params.DiffuseColor = Material.DiffuseColor; Params.Specular0Color = Material.Specular0Color; Params.Specular1Color = Material.Specular1Color; Params.Constant0Color = Material.Constant0Color; Params.Constant1Color = Material.Constant1Color; Params.Constant2Color = Material.Constant2Color; Params.Constant3Color = Material.Constant3Color; Params.Constant4Color = Material.Constant4Color; Params.Constant5Color = Material.Constant5Color; Params.BlendColor = Material.BlendColor; //HACK: It's usually 0 on Sun/Moon, this causes issues on some //models being rendered transparent (Shader differences). Params.DiffuseColor.A = 0xff; Params.ColorScale = 1f; Params.LUTInputAbsolute = Material.LUTInputAbsolute; Params.LUTInputSelection = Material.LUTInputSelection; Params.LUTInputScale = Material.LUTInputScale; Params.ColorOperation = Material.ColorOperation; Params.BlendFunction = Material.BlendFunction; Params.LogicalOperation = Material.LogicalOperation; Params.AlphaTest = Material.AlphaTest; Params.StencilTest = Material.StencilTest; Params.StencilOperation = Material.StencilOperation; Params.DepthColorMask = Material.DepthColorMask; Params.FaceCulling = Material.FaceCulling; Params.ColorBufferRead = Material.ColorBufferRead; Params.ColorBufferWrite = Material.ColorBufferWrite; Params.StencilBufferRead = Material.StencilBufferRead; Params.StencilBufferWrite = Material.StencilBufferWrite; Params.DepthBufferRead = Material.DepthBufferRead; Params.DepthBufferWrite = Material.DepthBufferWrite; if (Material.LUT0HashId != 0) { Params.LUTReflecRTableName = DefaultLUTName; Params.LUTReflecRSamplerName = GetLUTName(Material.LUT0HashId); } if (Material.LUT1HashId != 0) { Params.LUTReflecGTableName = DefaultLUTName; Params.LUTReflecGSamplerName = GetLUTName(Material.LUT1HashId); } if (Material.LUT2HashId != 0) { Params.LUTReflecBTableName = DefaultLUTName; Params.LUTReflecBSamplerName = GetLUTName(Material.LUT2HashId); } if (Material.BumpTexture != -1) { Params.BumpTexture = (byte)Material.BumpTexture; Params.BumpMode = H3DBumpMode.AsBump; } Params.Constant0Assignment = Material.Constant0Assignment; Params.Constant1Assignment = Material.Constant1Assignment; Params.Constant2Assignment = Material.Constant2Assignment; Params.Constant3Assignment = Material.Constant3Assignment; Params.Constant4Assignment = Material.Constant4Assignment; Params.Constant5Assignment = Material.Constant5Assignment; string VtxShaderName = Material.VtxShaderName; //Make shader names match X/Y/OR/AS shader names. if (VtxShaderName == "Poke" || VtxShaderName == "PokeNormal") { VtxShaderName = "PokePack"; } Params.ShaderReference = $"0@{VtxShaderName}"; Params.ModelReference = $"{Mat.Name}@{Name}"; /* * Add those for compatibility with the older BCH models. * It's worth noting that ShaderParam0 is usually used as "UVScale" on model that uses * geometry shader to make billboarded point sprites. On the new shader it have a * multiplication of the Color by 3, while the older one doesn't have such multiplication, * so for compatibility with the older shader, the easiest thing to do is just multiply the * scale by 3 to give the same results on the old shader. */ Params.MetaData = new H3DMetaData(); Params.MetaData.Add(new H3DMetaDataValue("EdgeType", Material.EdgeType)); Params.MetaData.Add(new H3DMetaDataValue("IDEdgeEnable", Material.IDEdgeEnable)); Params.MetaData.Add(new H3DMetaDataValue("EdgeID", Material.EdgeID)); Params.MetaData.Add(new H3DMetaDataValue("ProjectionType", Material.ProjectionType)); Params.MetaData.Add(new H3DMetaDataValue("RimPow", Material.RimPower)); Params.MetaData.Add(new H3DMetaDataValue("RimScale", Material.RimScale)); Params.MetaData.Add(new H3DMetaDataValue("PhongPow", Material.PhongPower)); Params.MetaData.Add(new H3DMetaDataValue("PhongScale", Material.PhongScale)); Params.MetaData.Add(new H3DMetaDataValue("IDEdgeOffsetEnable", Material.IDEdgeOffsetEnable)); Params.MetaData.Add(new H3DMetaDataValue("EdgeMapAlphaMask", Material.EdgeMapAlphaMask)); Params.MetaData.Add(new H3DMetaDataValue("BakeTexture0", Material.BakeTexture0)); Params.MetaData.Add(new H3DMetaDataValue("BakeTexture1", Material.BakeTexture1)); Params.MetaData.Add(new H3DMetaDataValue("BakeTexture2", Material.BakeTexture2)); Params.MetaData.Add(new H3DMetaDataValue("BakeConstant0", Material.BakeConstant0)); Params.MetaData.Add(new H3DMetaDataValue("BakeConstant1", Material.BakeConstant1)); Params.MetaData.Add(new H3DMetaDataValue("BakeConstant2", Material.BakeConstant2)); Params.MetaData.Add(new H3DMetaDataValue("BakeConstant3", Material.BakeConstant3)); Params.MetaData.Add(new H3DMetaDataValue("BakeConstant4", Material.BakeConstant4)); Params.MetaData.Add(new H3DMetaDataValue("BakeConstant5", Material.BakeConstant5)); Params.MetaData.Add(new H3DMetaDataValue("VertexShaderType", Material.VertexShaderType)); Params.MetaData.Add(new H3DMetaDataValue("ShaderParam0", Material.ShaderParam0 * 3)); Params.MetaData.Add(new H3DMetaDataValue("ShaderParam1", Material.ShaderParam1)); Params.MetaData.Add(new H3DMetaDataValue("ShaderParam2", Material.ShaderParam2)); Params.MetaData.Add(new H3DMetaDataValue("ShaderParam3", Material.ShaderParam3)); Output.Materials.Add(Mat); } //Meshes Output.MeshNodesTree = new H3DPatriciaTree(); foreach (GFMesh Mesh in Meshes) { //Note: GFModel have one Vertex Buffer for each SubMesh, //while on H3D all SubMeshes shares the same Vertex Buffer. //For this reason we need to store SubMeshes as Meshes on H3D. foreach (GFSubMesh SubMesh in Mesh.SubMeshes) { int NodeIndex = Output.MeshNodesTree.Find(Mesh.Name); if (NodeIndex == -1) { Output.MeshNodesTree.Add(Mesh.Name); Output.MeshNodesVisibility.Add(true); NodeIndex = Output.MeshNodesCount++; } List <H3DSubMesh> SubMeshes = new List <H3DSubMesh>(); ushort[] BoneIndices = new ushort[SubMesh.BoneIndicesCount]; for (int Index = 0; Index < BoneIndices.Length; Index++) { BoneIndices[Index] = SubMesh.BoneIndices[Index]; } H3DSubMeshSkinning SMSk = Output.Skeleton.Count > 0 ? H3DSubMeshSkinning.Smooth : H3DSubMeshSkinning.None; SubMeshes.Add(new H3DSubMesh() { Skinning = SMSk, BoneIndicesCount = SubMesh.BoneIndicesCount, BoneIndices = BoneIndices, Indices = SubMesh.Indices }); H3DMesh M = new H3DMesh( SubMesh.RawBuffer, SubMesh.VertexStride, SubMesh.Attributes, SubMesh.FixedAttributes, SubMeshes); M.Skinning = H3DMeshSkinning.Smooth; int MatIndex = Materials.FindIndex(x => x.MaterialName == SubMesh.Name); GFMaterial Mat = Materials[MatIndex]; M.MaterialIndex = (ushort)MatIndex; M.NodeIndex = (ushort)NodeIndex; M.Layer = Mat.RenderLayer; M.Priority = Mat.RenderPriority; M.UpdateBoolUniforms(Output.Materials[MatIndex]); Output.AddMesh(M); } } return(Output); }
public H3D ToH3D(string TextureAndMtlSearchPath = null) { H3D Output = new H3D(); Dictionary <string, OBJMaterial> Materials = new Dictionary <string, OBJMaterial>(); if (TextureAndMtlSearchPath != null) { string MaterialFile = Path.Combine(TextureAndMtlSearchPath, MtlFile); if (File.Exists(MaterialFile)) { string MaterialName = null; OBJMaterial Material = default(OBJMaterial); TextReader Reader = new StreamReader(MaterialFile); for (string Line; (Line = Reader.ReadLine()) != null;) { string[] Params = Line.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); if (Params.Length == 0) { continue; } switch (Params[0]) { case "newmtl": if (Params.Length > 1) { if (MaterialName != null && Material.DiffuseTexture != null) { Materials.Add(MaterialName, Material); } Material = new OBJMaterial(); MaterialName = Line.Substring(Line.IndexOf(" ")).Trim(); } break; case "map_Kd": if (Params.Length > 1) { string Name = Line.Substring(Line.IndexOf(Params[1])); string TextureFile = Path.Combine(TextureAndMtlSearchPath, Name); string TextureName = Path.GetFileNameWithoutExtension(TextureFile); if (File.Exists(TextureFile) && !Output.Textures.Contains(TextureName)) { Output.Textures.Add(new H3DTexture(TextureFile)); } Material.DiffuseTexture = Path.GetFileNameWithoutExtension(TextureName); } break; case "Ka": case "Kd": case "Ks": if (Params.Length >= 4) { Vector4 Color = new Vector4( float.Parse(Params[1], CultureInfo.InvariantCulture), float.Parse(Params[2], CultureInfo.InvariantCulture), float.Parse(Params[3], CultureInfo.InvariantCulture), 1); switch (Params[0]) { case "Ka": Material.Ambient = Color; break; case "Kd": Material.Diffuse = Color; break; case "Ks": Material.Specular = Color; break; } } break; } } Reader.Dispose(); if (MaterialName != null && Material.DiffuseTexture != null) { Materials.Add(MaterialName, Material); } } } H3DModel Model = new H3DModel(); Model.Name = "Model"; ushort MaterialIndex = 0; Model.Flags = H3DModelFlags.HasSkeleton; Model.BoneScaling = H3DBoneScaling.Maya; Model.MeshNodesVisibility.Add(true); float Height = 0; foreach (OBJMesh Mesh in Meshes) { Vector3 MinVector = new Vector3(); Vector3 MaxVector = new Vector3(); Dictionary <PICAVertex, int> Vertices = new Dictionary <PICAVertex, int>(); List <H3DSubMesh> SubMeshes = new List <H3DSubMesh>(); Queue <PICAVertex> VerticesQueue = new Queue <PICAVertex>(); foreach (PICAVertex Vertex in Mesh.Vertices) { VerticesQueue.Enqueue(Vertex); } while (VerticesQueue.Count > 2) { List <ushort> Indices = new List <ushort>(); while (VerticesQueue.Count > 0) { for (int Tri = 0; Tri < 3; Tri++) { PICAVertex Vertex = VerticesQueue.Dequeue(); if (Vertices.ContainsKey(Vertex)) { Indices.Add((ushort)Vertices[Vertex]); } else { Indices.Add((ushort)Vertices.Count); if (Vertex.Position.X < MinVector.X) { MinVector.X = Vertex.Position.X; } if (Vertex.Position.Y < MinVector.Y) { MinVector.Y = Vertex.Position.Y; } if (Vertex.Position.Z < MinVector.Z) { MinVector.Z = Vertex.Position.Z; } if (Vertex.Position.X > MaxVector.X) { MaxVector.X = Vertex.Position.X; } if (Vertex.Position.Y > MaxVector.Y) { MaxVector.Y = Vertex.Position.Y; } if (Vertex.Position.Z > MaxVector.Z) { MaxVector.Z = Vertex.Position.Z; } Vertices.Add(Vertex, Vertices.Count); } } } H3DSubMesh SM = new H3DSubMesh(); SM.BoneIndices = new ushort[] { 0 }; SM.Skinning = H3DSubMeshSkinning.Smooth; SM.Indices = Indices.ToArray(); SubMeshes.Add(SM); } //Mesh List <PICAAttribute> Attributes = PICAAttribute.GetAttributes( PICAAttributeName.Position, PICAAttributeName.Normal, PICAAttributeName.TexCoord0, PICAAttributeName.Color, PICAAttributeName.BoneIndex, PICAAttributeName.BoneWeight); H3DMesh M = new H3DMesh(Vertices.Keys, Attributes, SubMeshes) { Skinning = H3DMeshSkinning.Smooth, MeshCenter = (MinVector + MaxVector) * 0.5f, MaterialIndex = MaterialIndex }; if (Height < MaxVector.Y) { Height = MaxVector.Y; } //Material string MatName = $"Mat{MaterialIndex++.ToString("D5")}_{Mesh.MaterialName}"; H3DMaterial Material = H3DMaterial.GetSimpleMaterial(Model.Name, MatName, null); if (Materials.ContainsKey(Mesh.MaterialName)) { Material.Texture0Name = Materials[Mesh.MaterialName].DiffuseTexture; } else { Material.Texture0Name = "NoTexture"; } Model.Materials.Add(Material); M.UpdateBoolUniforms(Material); Model.AddMesh(M); } /* * On Pokémon, the root bone (on the animaiton file) is used by the game to move * characters around, and all rigged bones are parented to this bone. * It's usually the Waist bone, that points upward and is half the character height. */ Model.Skeleton.Add(new H3DBone( new Vector3(0, Height * 0.5f, 0), new Vector3(0, 0, (float)(Math.PI * 0.5)), Vector3.One, "Waist", -1)); Model.Skeleton[0].CalculateTransform(Model.Skeleton); Output.Models.Add(Model); Output.CopyMaterials(); return(Output); }
private static PICAVertex[] GetWorldSpaceVertices(H3DDict <H3DBone> skeleton, H3DMesh mesh) { var vertices = mesh.GetVertices(); var transformedVertices = new bool[vertices.Length]; //Smooth meshes are already in World Space, so we don't need to do anything. if (mesh.Skinning != H3DMeshSkinning.Smooth) { foreach (var sm in mesh.SubMeshes) { foreach (var i in sm.Indices) { if (transformedVertices[i]) { continue; } transformedVertices[i] = true; var v = vertices[i]; if (skeleton != null && skeleton.Count > 0 && sm.Skinning != H3DSubMeshSkinning.Smooth) { int b = sm.BoneIndices[v.Indices[0]]; var transform = skeleton[b].GetWorldTransform(skeleton); v.Position = System.Numerics.Vector4.Transform(new System.Numerics.Vector3(v.Position.X, v.Position.Y, v.Position.Z), transform); v.Normal.W = 0; v.Normal = System.Numerics.Vector4.Transform(v.Normal, transform); v.Normal = System.Numerics.Vector4.Normalize(v.Normal); } vertices[i] = v; } } } return(vertices); }
public static PICAVertex[] GetVertices(H3DMesh Mesh) { if (Mesh.RawBuffer.Length == 0) { return(new PICAVertex[0]); } float[] Elems = new float[4]; PICAVertex[] Output = new PICAVertex[Mesh.RawBuffer.Length / Mesh.VertexStride]; using (MemoryStream MS = new MemoryStream(Mesh.RawBuffer)) { BinaryReader Reader = new BinaryReader(MS); for (int Index = 0; Index < Output.Length; Index++) { PICAVertex Out = new PICAVertex(); MS.Seek(Index * Mesh.VertexStride, SeekOrigin.Begin); int bi = 0; int wi = 0; foreach (PICAAttribute Attrib in Mesh.Attributes) { AlignStream(MS, Attrib.Format); for (int Elem = 0; Elem < Attrib.Elements; Elem++) { switch (Attrib.Format) { case PICAAttributeFormat.Byte: Elems[Elem] = Reader.ReadSByte(); break; case PICAAttributeFormat.Ubyte: Elems[Elem] = Reader.ReadByte(); break; case PICAAttributeFormat.Short: Elems[Elem] = Reader.ReadInt16(); break; case PICAAttributeFormat.Float: Elems[Elem] = Reader.ReadSingle(); break; } } Vector4 v = new Vector4(Elems[0], Elems[1], Elems[2], Elems[3]); v *= Attrib.Scale; if (Attrib.Name == PICAAttributeName.Position) { v += Mesh.PositionOffset; } switch (Attrib.Name) { case PICAAttributeName.Position: Out.Position = v; break; case PICAAttributeName.Normal: Out.Normal = v; break; case PICAAttributeName.Tangent: Out.Tangent = v; break; case PICAAttributeName.Color: Out.Color = v; break; case PICAAttributeName.TexCoord0: Out.TexCoord0 = v; break; case PICAAttributeName.TexCoord1: Out.TexCoord1 = v; break; case PICAAttributeName.TexCoord2: Out.TexCoord2 = v; break; case PICAAttributeName.BoneIndex: Out.Indices[bi++] = (int)v.X; if (Attrib.Elements == 1) { break; } Out.Indices[bi++] = (int)v.Y; if (Attrib.Elements == 2) { break; } Out.Indices[bi++] = (int)v.Z; if (Attrib.Elements == 3) { break; } Out.Indices[bi++] = (int)v.W; break; case PICAAttributeName.BoneWeight: Out.Weights[wi++] = v.X; if (Attrib.Elements == 1) { break; } Out.Weights[wi++] = v.Y; if (Attrib.Elements == 2) { break; } Out.Weights[wi++] = v.Z; if (Attrib.Elements == 3) { break; } Out.Weights[wi++] = v.W; break; } } if (Mesh.FixedAttributes != null) { bool HasFixedIndices = Mesh.FixedAttributes.Any(x => x.Name == PICAAttributeName.BoneIndex); bool HasFixedWeights = Mesh.FixedAttributes.Any(x => x.Name == PICAAttributeName.BoneWeight); if (HasFixedIndices || HasFixedWeights) { foreach (PICAFixedAttribute Attr in Mesh.FixedAttributes) { switch (Attr.Name) { case PICAAttributeName.BoneIndex: Out.Indices[0] = (int)Attr.Value.X; Out.Indices[1] = (int)Attr.Value.Y; Out.Indices[2] = (int)Attr.Value.Z; break; case PICAAttributeName.BoneWeight: Out.Weights[0] = Attr.Value.X; Out.Weights[1] = Attr.Value.Y; Out.Weights[2] = Attr.Value.Z; break; } } } } Output[Index] = Out; } } return(Output); }
public H3D ToH3D() { H3D Output = new H3D(); H3DModel Model = new H3DModel(); Model.MeshNodesTree = new H3DPatriciaTree(); Model.Flags = BoneIndicesGroups.Length > 0 ? H3DModelFlags.HasSkeleton : 0; Model.Name = "Model"; foreach (MTMaterial Mat in Materials) { H3DMaterial Mtl = H3DMaterial.GetSimpleMaterial( Model.Name, Mat.Name, Path.GetFileNameWithoutExtension(Mat.Texture0Name)); Mtl.MaterialParams.ColorOperation.BlendMode = Mat.AlphaBlend.BlendMode; Mtl.MaterialParams.BlendFunction = Mat.AlphaBlend.BlendFunction; Mtl.MaterialParams.DepthColorMask.RedWrite = Mat.AlphaBlend.RedWrite; Mtl.MaterialParams.DepthColorMask.GreenWrite = Mat.AlphaBlend.GreenWrite; Mtl.MaterialParams.DepthColorMask.BlueWrite = Mat.AlphaBlend.BlueWrite; Mtl.MaterialParams.DepthColorMask.AlphaWrite = Mat.AlphaBlend.AlphaWrite; Mtl.MaterialParams.DepthColorMask.Enabled = Mat.DepthStencil.DepthTest; Mtl.MaterialParams.DepthColorMask.DepthWrite = Mat.DepthStencil.DepthWrite; Mtl.MaterialParams.DepthColorMask.DepthFunc = Mat.DepthStencil.DepthFunc; Model.Materials.Add(Mtl); } ushort Index = 0; foreach (MTMesh Mesh in Meshes) { if (Mesh.RenderType != -1) { continue; } H3DMesh M = new H3DMesh( Mesh.RawBuffer, Mesh.VertexStride, Mesh.Attributes, null, null) { MaterialIndex = (ushort)Mesh.MaterialIndex, NodeIndex = Index, Priority = Mesh.RenderPriority }; byte[] BoneIndices = BoneIndicesGroups[Mesh.BoneIndicesIndex]; if ((Model.Flags & H3DModelFlags.HasSkeleton) != 0 && BoneIndices.Length > 0) { M.Skinning = H3DMeshSkinning.Smooth; PICAVertex[] Vertices = M.GetVertices(); for (int v = 0; v < Vertices.Length; v++) { Vector4 Position = Vector4.Zero; float WeightSum = 0; for (int i = 0; i < 4; i++) { if (Vertices[v].Weights[i] == 0) { break; } WeightSum += Vertices[v].Weights[i]; int bi = BoneIndicesGroups[Mesh.BoneIndicesIndex][Vertices[v].Indices[i]]; Vector4 Trans = Vector4.Zero; for (int b = bi; b != -1; b = Skeleton[b].ParentIndex) { Trans += new Vector4( Skeleton[b].LocalTransform.M41, Skeleton[b].LocalTransform.M42, Skeleton[b].LocalTransform.M43, 0); } Matrix4x4 WT = Skeleton[bi].WorldTransform; Vector3 P = new Vector3( Vertices[v].Position.X, Vertices[v].Position.Y, Vertices[v].Position.Z); Vector4 TP = Vector4.Transform(P, WT); Position += (TP + Trans) * Vertices[v].Weights[i]; } if (WeightSum < 1) { Position += Vertices[v].Position * (1 - WeightSum); } Vertices[v].Position = Position; } /* * Removes unused bone from bone indices list, also splits sub meshes on exceeding bones if * current Mesh uses more than 20 (BCH only supports up to 20). */ Queue <ushort> IndicesQueue = new Queue <ushort>(Mesh.Indices); while (IndicesQueue.Count > 0) { int Count = IndicesQueue.Count / 3; List <ushort> Indices = new List <ushort>(); List <int> Bones = new List <int>(); while (Count-- > 0) { ushort i0 = IndicesQueue.Dequeue(); ushort i1 = IndicesQueue.Dequeue(); ushort i2 = IndicesQueue.Dequeue(); List <int> TempBones = new List <int>(12); for (int j = 0; j < 4; j++) { int b0 = Vertices[i0].Indices[j]; int b1 = Vertices[i1].Indices[j]; int b2 = Vertices[i2].Indices[j]; if (!(Bones.Contains(b0) || TempBones.Contains(b0))) { TempBones.Add(b0); } if (!(Bones.Contains(b1) || TempBones.Contains(b1))) { TempBones.Add(b1); } if (!(Bones.Contains(b2) || TempBones.Contains(b2))) { TempBones.Add(b2); } } if (Bones.Count + TempBones.Count > 20) { IndicesQueue.Enqueue(i0); IndicesQueue.Enqueue(i1); IndicesQueue.Enqueue(i2); } else { Indices.Add(i0); Indices.Add(i1); Indices.Add(i2); Bones.AddRange(TempBones); } } H3DSubMesh SM = new H3DSubMesh(); SM.Skinning = H3DSubMeshSkinning.Smooth; SM.Indices = Indices.ToArray(); SM.BoneIndicesCount = (ushort)Bones.Count; for (int i = 0; i < Bones.Count; i++) { SM.BoneIndices[i] = BoneIndices[Bones[i]]; } bool[] Visited = new bool[Vertices.Length]; foreach (ushort i in Indices) { if (!Visited[i]) { Visited[i] = true; Vertices[i].Indices[0] = Bones.IndexOf(Vertices[i].Indices[0]); Vertices[i].Indices[1] = Bones.IndexOf(Vertices[i].Indices[1]); Vertices[i].Indices[2] = Bones.IndexOf(Vertices[i].Indices[2]); Vertices[i].Indices[3] = Bones.IndexOf(Vertices[i].Indices[3]); } } M.SubMeshes.Add(SM); } M.RawBuffer = VerticesConverter.GetBuffer(Vertices, M.Attributes); } else { M.SubMeshes.Add(new H3DSubMesh() { Indices = Mesh.Indices }); } Model.AddMesh(M); Model.MeshNodesTree.Add($"Mesh_{Index++}"); Model.MeshNodesVisibility.Add(true); } int BoneIndex = 0; foreach (MTBone Bone in Skeleton) { Model.Skeleton.Add(new H3DBone() { Name = $"Bone_{BoneIndex++}", ParentIndex = Bone.ParentIndex, Translation = Bone.Position, Scale = Vector3.One }); } foreach (H3DBone Bone in Model.Skeleton) { Bone.CalculateTransform(Model.Skeleton); } if (Model.Materials.Count == 0) { Model.Materials.Add(H3DMaterial.GetSimpleMaterial(Model.Name, "DummyMaterial", null)); } Output.Models.Add(Model); Output.CopyMaterials(); return(Output); }
public H3D ToH3D(string TextureSearchPath = null) { H3D Output = new H3D(); H3DModel Model = new H3DModel(); Model.Name = "Model"; ushort MaterialIndex = 0; if (Skeleton.Count > 0) { Model.Flags = H3DModelFlags.HasSkeleton; } Model.BoneScaling = H3DBoneScaling.Maya; Model.MeshNodesVisibility.Add(true); foreach (SMDMesh Mesh in Meshes) { Vector3 MinVector = new Vector3(); Vector3 MaxVector = new Vector3(); Dictionary <PICAVertex, int> Vertices = new Dictionary <PICAVertex, int>(); List <H3DSubMesh> SubMeshes = new List <H3DSubMesh>(); Queue <PICAVertex> VerticesQueue = new Queue <PICAVertex>(); foreach (PICAVertex Vertex in Mesh.Vertices) { VerticesQueue.Enqueue(Vertex); } while (VerticesQueue.Count > 2) { List <ushort> Indices = new List <ushort>(); List <ushort> BoneIndices = new List <ushort>(); int TriCount = VerticesQueue.Count / 3; while (TriCount-- > 0) { PICAVertex[] Triangle = new PICAVertex[3]; Triangle[0] = VerticesQueue.Dequeue(); Triangle[1] = VerticesQueue.Dequeue(); Triangle[2] = VerticesQueue.Dequeue(); List <ushort> TempIndices = new List <ushort>(); for (int Tri = 0; Tri < 3; Tri++) { PICAVertex Vertex = Triangle[Tri]; for (int i = 0; i < 4; i++) { ushort Index = (ushort)Vertex.Indices[i]; if (!(BoneIndices.Contains(Index) || TempIndices.Contains(Index))) { TempIndices.Add(Index); } } } if (BoneIndices.Count + TempIndices.Count > 20) { VerticesQueue.Enqueue(Triangle[0]); VerticesQueue.Enqueue(Triangle[1]); VerticesQueue.Enqueue(Triangle[2]); continue; } for (int Tri = 0; Tri < 3; Tri++) { PICAVertex Vertex = Triangle[Tri]; for (int Index = 0; Index < 4; Index++) { int BoneIndex = BoneIndices.IndexOf((ushort)Vertex.Indices[Index]); if (BoneIndex == -1) { BoneIndex = BoneIndices.Count; BoneIndices.Add((ushort)Vertex.Indices[Index]); } Vertex.Indices[Index] = BoneIndex; } if (Vertices.ContainsKey(Vertex)) { Indices.Add((ushort)Vertices[Vertex]); } else { Indices.Add((ushort)Vertices.Count); if (Vertex.Position.X < MinVector.X) { MinVector.X = Vertex.Position.X; } if (Vertex.Position.Y < MinVector.Y) { MinVector.Y = Vertex.Position.Y; } if (Vertex.Position.Z < MinVector.Z) { MinVector.Z = Vertex.Position.Z; } if (Vertex.Position.X > MaxVector.X) { MaxVector.X = Vertex.Position.X; } if (Vertex.Position.Y > MaxVector.Y) { MaxVector.Y = Vertex.Position.Y; } if (Vertex.Position.Z > MaxVector.Z) { MaxVector.Z = Vertex.Position.Z; } Vertices.Add(Vertex, Vertices.Count); } } } SubMeshes.Add(new H3DSubMesh() { Skinning = H3DSubMeshSkinning.Smooth, BoneIndicesCount = (ushort)BoneIndices.Count, BoneIndices = BoneIndices.ToArray(), Indices = Indices.ToArray() }); } List <PICAAttribute> Attributes = PICAAttribute.GetAttributes( PICAAttributeName.Position, PICAAttributeName.Normal, PICAAttributeName.Color, PICAAttributeName.TexCoord0, PICAAttributeName.BoneIndex, PICAAttributeName.BoneWeight); //Mesh H3DMesh M = new H3DMesh(Vertices.Keys, Attributes, SubMeshes) { Skinning = H3DMeshSkinning.Smooth, MeshCenter = (MinVector + MaxVector) * 0.5f, MaterialIndex = MaterialIndex }; //Material string TexName = Path.GetFileNameWithoutExtension(Mesh.MaterialName); string MatName = $"Mat{MaterialIndex++.ToString("D5")}_{TexName}"; H3DMaterial Material = H3DMaterial.GetSimpleMaterial(Model.Name, MatName, TexName); Model.Materials.Add(Material); if (TextureSearchPath != null && !Output.Textures.Contains(TexName)) { string TextureFile = Path.Combine(TextureSearchPath, Mesh.MaterialName); if (File.Exists(TextureFile)) { Output.Textures.Add(new H3DTexture(TextureFile)); } } M.UpdateBoolUniforms(Material); Model.AddMesh(M); } //Build Skeleton foreach (SMDBone Bone in Skeleton) { SMDNode Node = Nodes[Bone.NodeIndex]; Model.Skeleton.Add(new H3DBone() { Name = Node.Name, ParentIndex = (short)Node.ParentIndex, Translation = Bone.Translation, Rotation = Bone.Rotation, Scale = Vector3.One }); } //Calculate Absolute Inverse Transforms for all bones foreach (H3DBone Bone in Model.Skeleton) { Bone.CalculateTransform(Model.Skeleton); } Output.Models.Add(Model); Output.CopyMaterials(); return(Output); }
public H3D ToH3D() { H3D Output = new H3D(); foreach (GfxModel Model in Models) { H3DModel Mdl = new H3DModel(); Mdl.Name = Model.Name; Mdl.WorldTransform = Model.WorldTransform; foreach (GfxMaterial Material in Model.Materials) { H3DMaterial Mat = new H3DMaterial() { Name = Material.Name }; Mat.MaterialParams.ModelReference = $"{Mat.Name}@{Model.Name}"; Mat.MaterialParams.ShaderReference = "0@DefaultShader"; Mat.MaterialParams.Flags = (H3DMaterialFlags)Material.Flags; Mat.MaterialParams.TranslucencyKind = (H3DTranslucencyKind)Material.TranslucencyKind; Mat.MaterialParams.TexCoordConfig = (H3DTexCoordConfig)Material.TexCoordConfig; Mat.MaterialParams.EmissionColor = Material.Colors.Emission; Mat.MaterialParams.AmbientColor = Material.Colors.Ambient; Mat.MaterialParams.DiffuseColor = Material.Colors.Diffuse; Mat.MaterialParams.Specular0Color = Material.Colors.Specular0; Mat.MaterialParams.Specular1Color = Material.Colors.Specular1; Mat.MaterialParams.Constant0Color = Material.Colors.Constant0; Mat.MaterialParams.Constant1Color = Material.Colors.Constant1; Mat.MaterialParams.Constant2Color = Material.Colors.Constant2; Mat.MaterialParams.Constant3Color = Material.Colors.Constant3; Mat.MaterialParams.Constant4Color = Material.Colors.Constant4; Mat.MaterialParams.Constant5Color = Material.Colors.Constant5; Mat.MaterialParams.ColorScale = Material.Colors.Scale; if (Material.Rasterization.IsPolygonOffsetEnabled) { Mat.MaterialParams.Flags |= H3DMaterialFlags.IsPolygonOffsetEnabled; } Mat.MaterialParams.FaceCulling = Material.Rasterization.FaceCulling.ToPICAFaceCulling(); Mat.MaterialParams.PolygonOffsetUnit = Material.Rasterization.PolygonOffsetUnit; Mat.MaterialParams.DepthColorMask = Material.FragmentOperation.Depth.ColorMask; Mat.MaterialParams.DepthColorMask.RedWrite = true; Mat.MaterialParams.DepthColorMask.GreenWrite = true; Mat.MaterialParams.DepthColorMask.BlueWrite = true; Mat.MaterialParams.DepthColorMask.AlphaWrite = true; Mat.MaterialParams.DepthColorMask.DepthWrite = true; Mat.MaterialParams.ColorBufferRead = false; Mat.MaterialParams.ColorBufferWrite = true; Mat.MaterialParams.StencilBufferRead = false; Mat.MaterialParams.StencilBufferWrite = false; Mat.MaterialParams.DepthBufferRead = true; Mat.MaterialParams.DepthBufferWrite = true; Mat.MaterialParams.ColorOperation = Material.FragmentOperation.Blend.ColorOperation; Mat.MaterialParams.LogicalOperation = Material.FragmentOperation.Blend.LogicalOperation; Mat.MaterialParams.BlendFunction = Material.FragmentOperation.Blend.Function; Mat.MaterialParams.BlendColor = Material.FragmentOperation.Blend.Color; Mat.MaterialParams.StencilOperation = Material.FragmentOperation.Stencil.Operation; Mat.MaterialParams.StencilTest = Material.FragmentOperation.Stencil.Test; int TCIndex = 0; foreach (GfxTextureCoord TexCoord in Material.TextureCoords) { H3DTextureCoord TC = new H3DTextureCoord(); TC.MappingType = (H3DTextureMappingType)TexCoord.MappingType; TC.ReferenceCameraIndex = (sbyte)TexCoord.ReferenceCameraIndex; TC.TransformType = (H3DTextureTransformType)TexCoord.TransformType; TC.Scale = TexCoord.Scale; TC.Rotation = TexCoord.Rotation; TC.Translation = TexCoord.Translation; switch (TexCoord.MappingType) { case GfxTextureMappingType.UvCoordinateMap: Mat.MaterialParams.TextureSources[TCIndex] = TexCoord.SourceCoordIndex; break; case GfxTextureMappingType.CameraCubeEnvMap: Mat.MaterialParams.TextureSources[TCIndex] = 3; break; case GfxTextureMappingType.CameraSphereEnvMap: Mat.MaterialParams.TextureSources[TCIndex] = 4; break; } Mat.MaterialParams.TextureCoords[TCIndex++] = TC; if (TCIndex == Material.UsedTextureCoordsCount) { break; } } int TMIndex = 0; foreach (GfxTextureMapper TexMapper in Material.TextureMappers) { if (TexMapper == null) { break; } H3DTextureMapper TM = new H3DTextureMapper(); TM.WrapU = TexMapper.WrapU; TM.WrapV = TexMapper.WrapV; TM.MagFilter = (H3DTextureMagFilter)TexMapper.MinFilter; switch ((uint)TexMapper.MagFilter | ((uint)TexMapper.MipFilter << 1)) { case 0: TM.MinFilter = H3DTextureMinFilter.NearestMipmapNearest; break; case 1: TM.MinFilter = H3DTextureMinFilter.LinearMipmapNearest; break; case 2: TM.MinFilter = H3DTextureMinFilter.NearestMipmapLinear; break; case 3: TM.MinFilter = H3DTextureMinFilter.LinearMipmapLinear; break; } TM.LODBias = TexMapper.LODBias; TM.MinLOD = TexMapper.MinLOD; TM.BorderColor = TexMapper.BorderColor; Mat.TextureMappers[TMIndex++] = TM; } Mat.EnabledTextures[0] = Material.TextureMappers[0] != null; Mat.EnabledTextures[1] = Material.TextureMappers[1] != null; Mat.EnabledTextures[2] = Material.TextureMappers[2] != null; Mat.Texture0Name = Material.TextureMappers[0]?.Texture.Path; Mat.Texture1Name = Material.TextureMappers[1]?.Texture.Path; Mat.Texture2Name = Material.TextureMappers[2]?.Texture.Path; GfxFragmentFlags SrcFlags = Material.FragmentShader.Lighting.Flags; H3DFragmentFlags DstFlags = 0; if ((SrcFlags & GfxFragmentFlags.IsClampHighLightEnabled) != 0) { DstFlags |= H3DFragmentFlags.IsClampHighLightEnabled; } if ((SrcFlags & GfxFragmentFlags.IsLUTDist0Enabled) != 0) { DstFlags |= H3DFragmentFlags.IsLUTDist0Enabled; } if ((SrcFlags & GfxFragmentFlags.IsLUTDist1Enabled) != 0) { DstFlags |= H3DFragmentFlags.IsLUTDist1Enabled; } if ((SrcFlags & GfxFragmentFlags.IsLUTGeoFactor0Enabled) != 0) { DstFlags |= H3DFragmentFlags.IsLUTGeoFactor0Enabled; } if ((SrcFlags & GfxFragmentFlags.IsLUTGeoFactor1Enabled) != 0) { DstFlags |= H3DFragmentFlags.IsLUTGeoFactor1Enabled; } if ((SrcFlags & GfxFragmentFlags.IsLUTReflectionEnabled) != 0) { DstFlags |= H3DFragmentFlags.IsLUTReflectionEnabled; } if (Material.FragmentShader.Lighting.IsBumpRenormalize) { DstFlags |= H3DFragmentFlags.IsBumpRenormalizeEnabled; } Mat.MaterialParams.FragmentFlags = DstFlags; Mat.MaterialParams.FresnelSelector = (H3DFresnelSelector)Material.FragmentShader.Lighting.FresnelSelector; Mat.MaterialParams.BumpTexture = (byte)Material.FragmentShader.Lighting.BumpTexture; Mat.MaterialParams.BumpMode = (H3DBumpMode)Material.FragmentShader.Lighting.BumpMode; Mat.MaterialParams.LUTInputSelection.ReflecR = Material.FragmentShader.LUTs.ReflecR?.Input ?? 0; Mat.MaterialParams.LUTInputSelection.ReflecG = Material.FragmentShader.LUTs.ReflecG?.Input ?? 0; Mat.MaterialParams.LUTInputSelection.ReflecB = Material.FragmentShader.LUTs.ReflecB?.Input ?? 0; Mat.MaterialParams.LUTInputSelection.Dist0 = Material.FragmentShader.LUTs.Dist0?.Input ?? 0; Mat.MaterialParams.LUTInputSelection.Dist1 = Material.FragmentShader.LUTs.Dist1?.Input ?? 0; Mat.MaterialParams.LUTInputSelection.Fresnel = Material.FragmentShader.LUTs.Fresnel?.Input ?? 0; Mat.MaterialParams.LUTInputScale.ReflecR = Material.FragmentShader.LUTs.ReflecR?.Scale ?? 0; Mat.MaterialParams.LUTInputScale.ReflecG = Material.FragmentShader.LUTs.ReflecG?.Scale ?? 0; Mat.MaterialParams.LUTInputScale.ReflecB = Material.FragmentShader.LUTs.ReflecB?.Scale ?? 0; Mat.MaterialParams.LUTInputScale.Dist0 = Material.FragmentShader.LUTs.Dist0?.Scale ?? 0; Mat.MaterialParams.LUTInputScale.Dist1 = Material.FragmentShader.LUTs.Dist1?.Scale ?? 0; Mat.MaterialParams.LUTInputScale.Fresnel = Material.FragmentShader.LUTs.Fresnel?.Scale ?? 0; Mat.MaterialParams.LUTReflecRTableName = Material.FragmentShader.LUTs.ReflecR?.Sampler.TableName; Mat.MaterialParams.LUTReflecGTableName = Material.FragmentShader.LUTs.ReflecG?.Sampler.TableName; Mat.MaterialParams.LUTReflecBTableName = Material.FragmentShader.LUTs.ReflecB?.Sampler.TableName; Mat.MaterialParams.LUTDist0TableName = Material.FragmentShader.LUTs.Dist0?.Sampler.TableName; Mat.MaterialParams.LUTDist1TableName = Material.FragmentShader.LUTs.Dist1?.Sampler.TableName; Mat.MaterialParams.LUTFresnelTableName = Material.FragmentShader.LUTs.Fresnel?.Sampler.TableName; Mat.MaterialParams.LUTReflecRSamplerName = Material.FragmentShader.LUTs.ReflecR?.Sampler.SamplerName; Mat.MaterialParams.LUTReflecGSamplerName = Material.FragmentShader.LUTs.ReflecG?.Sampler.SamplerName; Mat.MaterialParams.LUTReflecBSamplerName = Material.FragmentShader.LUTs.ReflecB?.Sampler.SamplerName; Mat.MaterialParams.LUTDist0SamplerName = Material.FragmentShader.LUTs.Dist0?.Sampler.SamplerName; Mat.MaterialParams.LUTDist1SamplerName = Material.FragmentShader.LUTs.Dist1?.Sampler.SamplerName; Mat.MaterialParams.LUTFresnelSamplerName = Material.FragmentShader.LUTs.Fresnel?.Sampler.SamplerName; Mat.MaterialParams.TexEnvStages[0] = Material.FragmentShader.TextureEnvironments[0].Stage; Mat.MaterialParams.TexEnvStages[1] = Material.FragmentShader.TextureEnvironments[1].Stage; Mat.MaterialParams.TexEnvStages[2] = Material.FragmentShader.TextureEnvironments[2].Stage; Mat.MaterialParams.TexEnvStages[3] = Material.FragmentShader.TextureEnvironments[3].Stage; Mat.MaterialParams.TexEnvStages[4] = Material.FragmentShader.TextureEnvironments[4].Stage; Mat.MaterialParams.TexEnvStages[5] = Material.FragmentShader.TextureEnvironments[5].Stage; Mat.MaterialParams.AlphaTest = Material.FragmentShader.AlphaTest.Test; Mat.MaterialParams.TexEnvBufferColor = Material.FragmentShader.TexEnvBufferColor; Mdl.Materials.Add(Mat); } foreach (GfxMesh Mesh in Model.Meshes) { GfxShape Shape = Model.Shapes[Mesh.ShapeIndex]; H3DMesh M = new H3DMesh(); PICAVertex[] Vertices = null; foreach (GfxVertexBuffer VertexBuffer in Shape.VertexBuffers) { /* * CGfx supports 3 types of vertex buffer: * - Non-Interleaved: Each attribute is stored on it's on stream, like this: * P0 P1 P2 P3 P4 P5 ... N0 N1 N2 N3 N4 N5 * - Interleaved: All attributes are stored on the same stream, like this: * P0 N0 P1 N1 P2 N2 P3 N3 P4 N4 P5 N5 ... * - Fixed: The attribute have only a single fixed value, so instead of a stream, * it have a single vector. */ if (VertexBuffer is GfxAttribute) { //Non-Interleaved buffer GfxAttribute Attr = (GfxAttribute)VertexBuffer; M.Attributes.Add(Attr.ToPICAAttribute()); int Length = Attr.Elements; switch (Attr.Format) { case GfxGLDataType.GL_SHORT: Length <<= 1; break; case GfxGLDataType.GL_FLOAT: Length <<= 2; break; } M.VertexStride += Length; Vector4[] Vectors = Attr.GetVectors(); if (Vertices == null) { Vertices = new PICAVertex[Vectors.Length]; } for (int i = 0; i < Vectors.Length; i++) { switch (Attr.AttrName) { case PICAAttributeName.Position: Vertices[i].Position = Vectors[i]; break; case PICAAttributeName.Normal: Vertices[i].Normal = Vectors[i]; break; case PICAAttributeName.Tangent: Vertices[i].Tangent = Vectors[i]; break; case PICAAttributeName.TexCoord0: Vertices[i].TexCoord0 = Vectors[i]; break; case PICAAttributeName.TexCoord1: Vertices[i].TexCoord1 = Vectors[i]; break; case PICAAttributeName.TexCoord2: Vertices[i].TexCoord2 = Vectors[i]; break; case PICAAttributeName.Color: Vertices[i].Color = Vectors[i]; break; case PICAAttributeName.BoneIndex: Vertices[i].Indices[0] = (int)Vectors[i].X; Vertices[i].Indices[1] = (int)Vectors[i].Y; Vertices[i].Indices[2] = (int)Vectors[i].Z; Vertices[i].Indices[3] = (int)Vectors[i].W; break; case PICAAttributeName.BoneWeight: Vertices[i].Weights[0] = Vectors[i].X; Vertices[i].Weights[1] = Vectors[i].Y; Vertices[i].Weights[2] = Vectors[i].Z; Vertices[i].Weights[3] = Vectors[i].W; break; } } } else if (VertexBuffer is GfxVertexBufferFixed) { //Fixed vector float[] Vector = ((GfxVertexBufferFixed)VertexBuffer).Vector; M.FixedAttributes.Add(new PICAFixedAttribute() { Name = VertexBuffer.AttrName, Value = new PICAVectorFloat24( Vector.Length > 0 ? Vector[0] : 0, Vector.Length > 1 ? Vector[1] : 0, Vector.Length > 2 ? Vector[2] : 0, Vector.Length > 3 ? Vector[3] : 0) }); } else { //Interleaved buffer GfxVertexBufferInterleaved VtxBuff = (GfxVertexBufferInterleaved)VertexBuffer; foreach (GfxAttribute Attr in ((GfxVertexBufferInterleaved)VertexBuffer).Attributes) { M.Attributes.Add(Attr.ToPICAAttribute()); } M.RawBuffer = VtxBuff.RawBuffer; M.VertexStride = VtxBuff.VertexStride; } } if (Vertices != null) { M.RawBuffer = VerticesConverter.GetBuffer(Vertices, M.Attributes); } Vector4 PositionOffset = new Vector4(Shape.PositionOffset, 0); int Layer = (int)Model.Materials[Mesh.MaterialIndex].TranslucencyKind; M.MaterialIndex = (ushort)Mesh.MaterialIndex; M.NodeIndex = (ushort)Mesh.MeshNodeIndex; M.PositionOffset = PositionOffset; M.MeshCenter = Shape.BoundingBox.Center; M.Layer = Layer; M.Priority = Mesh.RenderPriority; H3DBoundingBox OBB = new H3DBoundingBox() { Center = Shape.BoundingBox.Center, Orientation = Shape.BoundingBox.Orientation, Size = Shape.BoundingBox.Size }; M.MetaData = new H3DMetaData(); M.MetaData.Add(new H3DMetaDataValue(OBB)); int SmoothCount = 0; foreach (GfxSubMesh SubMesh in Shape.SubMeshes) { foreach (GfxFace Face in SubMesh.Faces) { foreach (GfxFaceDescriptor Desc in Face.FaceDescriptors) { H3DSubMesh SM = new H3DSubMesh(); SM.BoneIndicesCount = (ushort)SubMesh.BoneIndices.Count; for (int i = 0; i < SubMesh.BoneIndices.Count; i++) { SM.BoneIndices[i] = (ushort)SubMesh.BoneIndices[i]; } switch (SubMesh.Skinning) { case GfxSubMeshSkinning.None: SM.Skinning = H3DSubMeshSkinning.None; break; case GfxSubMeshSkinning.Rigid: SM.Skinning = H3DSubMeshSkinning.Rigid; break; case GfxSubMeshSkinning.Smooth: SM.Skinning = H3DSubMeshSkinning.Smooth; break; } SM.Indices = Desc.Indices; SM.Indices = new ushort[Desc.Indices.Length]; Array.Copy(Desc.Indices, SM.Indices, SM.Indices.Length); M.SubMeshes.Add(SM); } } if (SubMesh.Skinning == GfxSubMeshSkinning.Smooth) { SmoothCount++; } } if (SmoothCount == Shape.SubMeshes.Count) { M.Skinning = H3DMeshSkinning.Smooth; } else if (SmoothCount > 0) { M.Skinning = H3DMeshSkinning.Mixed; } else { M.Skinning = H3DMeshSkinning.Rigid; } GfxMaterial Mat = Model.Materials[Mesh.MaterialIndex]; M.UpdateBoolUniforms(Mdl.Materials[Mesh.MaterialIndex]); Mdl.AddMesh(M); } //Workaround to fix blending problems until I can find a proper way. Mdl.MeshesLayer1.Reverse(); Mdl.MeshNodesTree = new H3DPatriciaTree(); foreach (GfxMeshNodeVisibility MeshNode in Model.MeshNodeVisibilities) { Mdl.MeshNodesTree.Add(MeshNode.Name); Mdl.MeshNodesVisibility.Add(MeshNode.IsVisible); } if (Model is GfxModelSkeletal) { foreach (GfxBone Bone in ((GfxModelSkeletal)Model).Skeleton.Bones) { H3DBone B = new H3DBone() { Name = Bone.Name, ParentIndex = (short)Bone.ParentIndex, Translation = Bone.Translation, Rotation = Bone.Rotation, Scale = Bone.Scale, InverseTransform = Bone.InvWorldTransform }; bool ScaleCompensate = (Bone.Flags & GfxBoneFlags.IsSegmentScaleCompensate) != 0; if (ScaleCompensate) { B.Flags |= H3DBoneFlags.IsSegmentScaleCompensate; } Mdl.Skeleton.Add(B); } Mdl.Flags |= H3DModelFlags.HasSkeleton; Mdl.BoneScaling = (H3DBoneScaling)((GfxModelSkeletal)Model).Skeleton.ScalingRule; } Output.Models.Add(Mdl); } foreach (GfxTexture Texture in Textures) { H3DTexture Tex = new H3DTexture() { Name = Texture.Name, Width = Texture.Width, Height = Texture.Height, Format = Texture.HwFormat, MipmapSize = (byte)Texture.MipmapSize }; if (Texture is GfxTextureCube) { Tex.RawBufferXPos = ((GfxTextureCube)Texture).ImageXPos.RawBuffer; Tex.RawBufferXNeg = ((GfxTextureCube)Texture).ImageXNeg.RawBuffer; Tex.RawBufferYPos = ((GfxTextureCube)Texture).ImageYPos.RawBuffer; Tex.RawBufferYNeg = ((GfxTextureCube)Texture).ImageYNeg.RawBuffer; Tex.RawBufferZPos = ((GfxTextureCube)Texture).ImageZPos.RawBuffer; Tex.RawBufferZNeg = ((GfxTextureCube)Texture).ImageZNeg.RawBuffer; } else { Tex.RawBuffer = ((GfxTextureImage)Texture).Image.RawBuffer; } Output.Textures.Add(Tex); } foreach (GfxLUT LUT in LUTs) { H3DLUT L = new H3DLUT() { Name = LUT.Name }; foreach (GfxLUTSampler Sampler in LUT.Samplers) { L.Samplers.Add(new H3DLUTSampler() { Flags = Sampler.IsAbsolute ? H3DLUTFlags.IsAbsolute : 0, Name = Sampler.Name, Table = Sampler.Table }); } Output.LUTs.Add(L); } foreach (GfxCamera Camera in Cameras) { Output.Cameras.Add(Camera.ToH3DCamera()); } foreach (GfxLight Light in Lights) { Output.Lights.Add(Light.ToH3DLight()); } foreach (GfxAnimation SklAnim in SkeletalAnimations) { Output.SkeletalAnimations.Add(SklAnim.ToH3DAnimation()); } foreach (GfxAnimation MatAnim in MaterialAnimations) { Output.MaterialAnimations.Add(new H3DMaterialAnim(MatAnim.ToH3DAnimation())); } foreach (GfxAnimation VisAnim in VisibilityAnimations) { Output.VisibilityAnimations.Add(VisAnim.ToH3DAnimation()); } foreach (GfxAnimation CamAnim in CameraAnimations) { Output.CameraAnimations.Add(CamAnim.ToH3DAnimation()); } Output.CopyMaterials(); return(Output); }
public H3DMeshWrapper(BCH bch, H3DModelWrapper parentModel, H3DMesh mesh) : base() { ParentBCH = bch; ParentModel = parentModel; Mesh = mesh; ImageKey = "mesh"; SelectedImageKey = "mesh"; MaterialIndex = Mesh.MaterialIndex; foreach (var subMesh in mesh.SubMeshes) { STGenericPolygonGroup group = new STGenericPolygonGroup(); for (int i = 0; i < subMesh.Indices.Length; i++) { group.faces.Add(subMesh.Indices[i]); } group.PrimativeType = STPrimitiveType.Triangles; /* switch (subMesh.PrimitiveMode) * { * case SPICA.PICA.Commands.PICAPrimitiveMode.Triangles: * group.PrimativeType = STPrimitiveType.Triangles; * break; * case SPICA.PICA.Commands.PICAPrimitiveMode.TriangleStrip: * group.PrimativeType = STPrimitiveType.TrangleStrips; * break; * }*/ PolygonGroups.Add(group); } var vertices = mesh.GetVertices(); List <ushort> boneIndices = new List <ushort>(); foreach (var subMesh in mesh.SubMeshes) { if (subMesh.BoneIndicesCount > 0) { boneIndices.AddRange(subMesh.BoneIndices.ToArray()); } } for (int v = 0; v < vertices.Length; v++) { Vertex vertex = new Vertex(); vertex.pos = ConvertVector3(vertices[v].Position); vertex.nrm = ConvertVector3(vertices[v].Normal); vertex.tan = ConvertVector4(vertices[v].Tangent); vertex.uv0 = ConvertVector2(vertices[v].TexCoord0); vertex.uv1 = ConvertVector2(vertices[v].TexCoord1); vertex.uv2 = ConvertVector2(vertices[v].TexCoord2); vertex.col = ConvertVector4(vertices[v].Color); //Flip UVs vertex.uv0 = new Vector2(vertex.uv0.X, 1 - vertex.uv0.Y); if (boneIndices.Count > 0) { /* if (vertices[v].Indices.b0 != -1) vertex.boneIds.Add(boneIndices[vertices[v].Indices.b0]); * if (vertices[v].Indices.b1 != -1) vertex.boneIds.Add(boneIndices[vertices[v].Indices.b1]); * if (vertices[v].Indices.b2 != -1) vertex.boneIds.Add(boneIndices[vertices[v].Indices.b2]); * if (vertices[v].Indices.b3 != -1) vertex.boneIds.Add(boneIndices[vertices[v].Indices.b3]);*/ if (mesh.Skinning == H3DMeshSkinning.Rigid) { int index = boneIndices[vertices[v].Indices.b0]; vertex.pos = Vector3.TransformPosition(vertex.pos, parentModel.Skeleton.Renderable.bones[index].Transform); // vertex.nrm = Vector3.TransformNormal(vertex.nrm, parentModel.Skeleton.Renderable.bones[index].Transform); } /* vertex.boneWeights.Add(vertices[v].Weights.w0); * vertex.boneWeights.Add(vertices[v].Weights.w1); * vertex.boneWeights.Add(vertices[v].Weights.w2); * vertex.boneWeights.Add(vertices[v].Weights.w3);*/ } this.vertices.Add(vertex); } }
public H3D ToH3D(string TextureAndMtlSearchPath = null, bool noTextures = false) { H3D Output = new H3D(); Dictionary <string, OBJMaterial> Materials = new Dictionary <string, OBJMaterial>(); if (TextureAndMtlSearchPath != null) { TextReader Reader = null; if (textureOnly) { Reader = new StreamReader(textureOnlyFile); } else { string MaterialFile = Path.Combine(TextureAndMtlSearchPath, MtlFile); if (File.Exists(MaterialFile)) { Reader = new StreamReader(MaterialFile); } } if (Reader != null) { string MaterialName = null; OBJMaterial Material = default(OBJMaterial); for (string Line; (Line = Reader.ReadLine()) != null;) { string[] Params = Line.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); if (Params.Length == 0) { continue; } switch (Params[0]) { case "newmtl": if (Params.Length > 1) { if (MaterialName != null && Material.DiffuseTexture != null) { Materials.Add(MaterialName, Material); } Material = new OBJMaterial(); MaterialName = Line.Substring(Line.IndexOf(" ")).Trim(); } break; case "map_Kd": if (Params.Length > 1) { string Name = Line.Substring(Line.IndexOf(Params[1])); string TextureFile = Path.Combine(TextureAndMtlSearchPath, Name); string TextureName = Path.GetFileName(TextureFile); if (File.Exists(TextureFile) && !noTextures) { if (Output.Textures.Contains(TextureName)) { Output.Textures.Remove(Output.Textures[Output.Textures.Find(TextureName)]); } Output.Textures.Add(new H3DTexture(TextureFile)); } Material.DiffuseTexture = TextureName; } break; case "Ka": case "Kd": case "Ks": if (Params.Length >= 4) { Vector4 Color = new Vector4( float.Parse(Params[1], CultureInfo.InvariantCulture), float.Parse(Params[2], CultureInfo.InvariantCulture), float.Parse(Params[3], CultureInfo.InvariantCulture), 1); switch (Params[0]) { case "Ka": Material.Ambient = Color; break; case "Kd": Material.Diffuse = Color; break; case "Ks": Material.Specular = Color; break; } } break; } } Reader.Dispose(); if (MaterialName != null && !textureOnly) { Materials.Add(MaterialName, Material); } } } if (!textureOnly) { H3DModel Model = new H3DModel(); string newName = Microsoft.VisualBasic.Interaction.InputBox("Enter model name: ", "Name", Model.Name); if (newName != "") { Model.Name = newName; } ushort MaterialIndex = 0; Model.Flags = 0; Model.BoneScaling = H3DBoneScaling.Standard; Model.MeshNodesVisibility.Clear(); Model.Skeleton.Clear(); Model.MeshNodesVisibility.Add(true); float Height = 0; Meshes.Sort((x, y) => string.Compare(x.Name, y.Name)); foreach (OBJMesh Mesh in Meshes) { Vector3 MinVector = new Vector3(); Vector3 MaxVector = new Vector3(); Dictionary <PICAVertex, int> Vertices = new Dictionary <PICAVertex, int>(); List <H3DSubMesh> SubMeshes = new List <H3DSubMesh>(); Queue <PICAVertex> VerticesQueue = new Queue <PICAVertex>(); foreach (PICAVertex Vertex in Mesh.Vertices) { VerticesQueue.Enqueue(Vertex); } while (VerticesQueue.Count > 2) { List <ushort> Indices = new List <ushort>(); while (VerticesQueue.Count > 0) { for (int Tri = 0; Tri < 3; Tri++) { PICAVertex Vertex = VerticesQueue.Dequeue(); if (Mesh.Name.Contains("uncolor")) { Vertex.Color = Vector4.One; } if (Vertices.ContainsKey(Vertex)) { Indices.Add((ushort)Vertices[Vertex]); } else { Indices.Add((ushort)Vertices.Count); if (Vertex.Position.X < MinVector.X) { MinVector.X = Vertex.Position.X; } if (Vertex.Position.Y < MinVector.Y) { MinVector.Y = Vertex.Position.Y; } if (Vertex.Position.Z < MinVector.Z) { MinVector.Z = Vertex.Position.Z; } if (Vertex.Position.X > MaxVector.X) { MaxVector.X = Vertex.Position.X; } if (Vertex.Position.Y > MaxVector.Y) { MaxVector.Y = Vertex.Position.Y; } if (Vertex.Position.Z > MaxVector.Z) { MaxVector.Z = Vertex.Position.Z; } Vertices.Add(Vertex, Vertices.Count); } } } H3DSubMesh SM = new H3DSubMesh(); SM.BoneIndices = new ushort[] { }; SM.Skinning = H3DSubMeshSkinning.None; SM.Indices = Indices.ToArray(); SubMeshes.Add(SM); } //Mesh List <PICAAttribute> Attributes = PICAAttribute.GetAttributes( PICAAttributeName.Position, PICAAttributeName.Normal, PICAAttributeName.TexCoord0, PICAAttributeName.Color ); H3DMesh M = new H3DMesh(Vertices.Keys, Attributes, SubMeshes) { Skinning = H3DMeshSkinning.Rigid, MeshCenter = (MinVector + MaxVector) * 0.5f, MaterialIndex = MaterialIndex, }; if (Height < MaxVector.Y) { Height = MaxVector.Y; } //Material string MatName = $"Mat{MaterialIndex++.ToString("D5")}_{Mesh.MaterialName}"; H3DMaterial Material = H3DMaterial.GetSimpleMaterial(Model.Name, Mesh.MaterialName, Materials[Mesh.MaterialName].DiffuseTexture); Material.Texture0Name = Materials[Mesh.MaterialName].DiffuseTexture; Material.MaterialParams.FaceCulling = PICAFaceCulling.BackFace; Material.MaterialParams.Flags = H3DMaterialFlags.IsFragmentLightingEnabled | H3DMaterialFlags.IsVertexLightingEnabled | H3DMaterialFlags.IsFragmentLightingPolygonOffsetDirty; Material.MaterialParams.FragmentFlags = 0; Material.MaterialParams.LightSetIndex = 0; Material.MaterialParams.FogIndex = 0; Material.MaterialParams.LogicalOperation = PICALogicalOp.Noop; Material.MaterialParams.AmbientColor = RGBA.White; Material.MaterialParams.DiffuseColor = RGBA.White; Material.MaterialParams.EmissionColor = RGBA.Black; Material.MaterialParams.Specular0Color = RGBA.Black; Material.MaterialParams.Specular1Color = RGBA.Black; Material.MaterialParams.Constant0Color = RGBA.White; Material.MaterialParams.Constant1Color = RGBA.White; Material.MaterialParams.Constant2Color = RGBA.White; Material.MaterialParams.Constant3Color = RGBA.White; Material.MaterialParams.Constant4Color = RGBA.White; Material.MaterialParams.Constant5Color = RGBA.White; Material.MaterialParams.BlendColor = RGBA.Black; Material.MaterialParams.Constant2Assignment = 2; Material.MaterialParams.ColorScale = 1; Material.MaterialParams.FresnelSelector = H3DFresnelSelector.No; Material.MaterialParams.BumpMode = H3DBumpMode.NotUsed; Material.MaterialParams.BumpTexture = 0; Material.MaterialParams.PolygonOffsetUnit = 0; Material.MaterialParams.TexEnvBufferColor = RGBA.White; Material.MaterialParams.ColorOperation.FragOpMode = PICAFragOpMode.Default; Material.MaterialParams.ColorOperation.BlendMode = PICABlendMode.Blend; Material.MaterialParams.ColorBufferRead = true; Material.MaterialParams.ColorBufferWrite = true; Material.MaterialParams.StencilBufferRead = true; Material.MaterialParams.StencilBufferWrite = true; Material.MaterialParams.DepthBufferRead = true; Material.MaterialParams.DepthBufferWrite = false; Material.MaterialParams.TexEnvStages[0].Source.Color = new PICATextureCombinerSource[] { PICATextureCombinerSource.Texture0, PICATextureCombinerSource.PrimaryColor, PICATextureCombinerSource.Texture0 }; Material.MaterialParams.TexEnvStages[0].Source.Alpha = new PICATextureCombinerSource[] { PICATextureCombinerSource.Texture0, PICATextureCombinerSource.Texture0, PICATextureCombinerSource.Texture0 }; Material.MaterialParams.TexEnvStages[0].Operand.Color = new PICATextureCombinerColorOp[] { PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color }; Material.MaterialParams.TexEnvStages[0].Operand.Alpha = new PICATextureCombinerAlphaOp[] { PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha }; Material.MaterialParams.TexEnvStages[0].Combiner.Color = PICATextureCombinerMode.Modulate; Material.MaterialParams.TexEnvStages[0].Combiner.Alpha = PICATextureCombinerMode.Replace; Material.MaterialParams.TexEnvStages[0].Color = RGBA.White; Material.MaterialParams.TexEnvStages[0].Scale.Color = PICATextureCombinerScale.One; Material.MaterialParams.TexEnvStages[0].Scale.Alpha = PICATextureCombinerScale.One; Material.MaterialParams.TexEnvStages[0].UpdateColorBuffer = false; Material.MaterialParams.TexEnvStages[0].UpdateAlphaBuffer = false; Material.MaterialParams.TexEnvStages[1].Source.Color = new PICATextureCombinerSource[] { PICATextureCombinerSource.Previous, PICATextureCombinerSource.FragmentPrimaryColor, PICATextureCombinerSource.Previous }; Material.MaterialParams.TexEnvStages[1].Source.Alpha = new PICATextureCombinerSource[] { PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous }; Material.MaterialParams.TexEnvStages[1].Operand.Color = new PICATextureCombinerColorOp[] { PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color }; Material.MaterialParams.TexEnvStages[1].Operand.Alpha = new PICATextureCombinerAlphaOp[] { PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha }; Material.MaterialParams.TexEnvStages[1].Combiner.Color = PICATextureCombinerMode.Modulate; Material.MaterialParams.TexEnvStages[1].Combiner.Alpha = PICATextureCombinerMode.Replace; Material.MaterialParams.TexEnvStages[1].Color = RGBA.Black; Material.MaterialParams.TexEnvStages[1].Scale.Color = PICATextureCombinerScale.One; Material.MaterialParams.TexEnvStages[1].Scale.Alpha = PICATextureCombinerScale.One; Material.MaterialParams.TexEnvStages[1].UpdateColorBuffer = false; Material.MaterialParams.TexEnvStages[1].UpdateAlphaBuffer = false; Material.MaterialParams.TexEnvStages[2].Source.Color = new PICATextureCombinerSource[] { PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous }; Material.MaterialParams.TexEnvStages[2].Source.Alpha = new PICATextureCombinerSource[] { PICATextureCombinerSource.Previous, PICATextureCombinerSource.PrimaryColor, PICATextureCombinerSource.Previous }; Material.MaterialParams.TexEnvStages[2].Operand.Color = new PICATextureCombinerColorOp[] { PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color }; Material.MaterialParams.TexEnvStages[2].Operand.Alpha = new PICATextureCombinerAlphaOp[] { PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha }; Material.MaterialParams.TexEnvStages[2].Combiner.Color = PICATextureCombinerMode.Replace; Material.MaterialParams.TexEnvStages[2].Combiner.Alpha = PICATextureCombinerMode.Modulate; Material.MaterialParams.TexEnvStages[2].Color = RGBA.White; Material.MaterialParams.TexEnvStages[2].Scale.Color = PICATextureCombinerScale.One; Material.MaterialParams.TexEnvStages[2].Scale.Alpha = PICATextureCombinerScale.One; Material.MaterialParams.TexEnvStages[2].UpdateColorBuffer = false; Material.MaterialParams.TexEnvStages[2].UpdateAlphaBuffer = false; Material.MaterialParams.TexEnvStages[3].Source.Color = new PICATextureCombinerSource[] { PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous }; Material.MaterialParams.TexEnvStages[3].Source.Alpha = new PICATextureCombinerSource[] { PICATextureCombinerSource.Previous, PICATextureCombinerSource.Constant, PICATextureCombinerSource.Previous }; Material.MaterialParams.TexEnvStages[3].Operand.Color = new PICATextureCombinerColorOp[] { PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color }; Material.MaterialParams.TexEnvStages[3].Operand.Alpha = new PICATextureCombinerAlphaOp[] { PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha }; Material.MaterialParams.TexEnvStages[3].Combiner.Color = PICATextureCombinerMode.Replace; Material.MaterialParams.TexEnvStages[3].Combiner.Alpha = PICATextureCombinerMode.Modulate; Material.MaterialParams.TexEnvStages[3].Color = RGBA.White; Material.MaterialParams.TexEnvStages[3].Scale.Color = PICATextureCombinerScale.One; Material.MaterialParams.TexEnvStages[3].Scale.Alpha = PICATextureCombinerScale.One; Material.MaterialParams.TexEnvStages[3].UpdateColorBuffer = false; Material.MaterialParams.TexEnvStages[3].UpdateAlphaBuffer = false; Material.MaterialParams.TexEnvStages[4].Source.Color = new PICATextureCombinerSource[] { PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous }; Material.MaterialParams.TexEnvStages[4].Source.Alpha = new PICATextureCombinerSource[] { PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous }; Material.MaterialParams.TexEnvStages[4].Operand.Color = new PICATextureCombinerColorOp[] { PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color }; Material.MaterialParams.TexEnvStages[4].Operand.Alpha = new PICATextureCombinerAlphaOp[] { PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha }; Material.MaterialParams.TexEnvStages[4].Combiner.Color = PICATextureCombinerMode.Replace; Material.MaterialParams.TexEnvStages[4].Combiner.Alpha = PICATextureCombinerMode.Replace; Material.MaterialParams.TexEnvStages[4].Color = RGBA.Black; Material.MaterialParams.TexEnvStages[4].Scale.Color = PICATextureCombinerScale.One; Material.MaterialParams.TexEnvStages[4].Scale.Alpha = PICATextureCombinerScale.One; Material.MaterialParams.TexEnvStages[4].UpdateColorBuffer = true; Material.MaterialParams.TexEnvStages[4].UpdateAlphaBuffer = false; Material.MaterialParams.TexEnvStages[5].Source.Color = new PICATextureCombinerSource[] { PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous }; Material.MaterialParams.TexEnvStages[5].Source.Alpha = new PICATextureCombinerSource[] { PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous }; Material.MaterialParams.TexEnvStages[5].Operand.Color = new PICATextureCombinerColorOp[] { PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color }; Material.MaterialParams.TexEnvStages[5].Operand.Alpha = new PICATextureCombinerAlphaOp[] { PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha }; Material.MaterialParams.TexEnvStages[5].Combiner.Color = PICATextureCombinerMode.Replace; Material.MaterialParams.TexEnvStages[5].Combiner.Alpha = PICATextureCombinerMode.Replace; Material.MaterialParams.TexEnvStages[5].Color = RGBA.Black; Material.MaterialParams.TexEnvStages[5].Scale.Color = PICATextureCombinerScale.One; Material.MaterialParams.TexEnvStages[5].Scale.Alpha = PICATextureCombinerScale.One; Material.MaterialParams.TexEnvStages[5].UpdateColorBuffer = false; Material.MaterialParams.TexEnvStages[5].UpdateAlphaBuffer = false; if (Mesh.Name.Contains("alpha")) { if (Mesh.Name.Contains("alphablend")) { M.Layer = 1; Material.MaterialParams.ColorOperation.BlendMode = PICABlendMode.Blend; Material.MaterialParams.BlendFunction.ColorDstFunc = PICABlendFunc.OneMinusSourceAlpha; Material.MaterialParams.BlendFunction.ColorEquation = PICABlendEquation.FuncAdd; Material.MaterialParams.BlendFunction.ColorSrcFunc = PICABlendFunc.SourceAlpha; Material.MaterialParams.BlendFunction.AlphaDstFunc = PICABlendFunc.OneMinusSourceAlpha; Material.MaterialParams.BlendFunction.AlphaEquation = PICABlendEquation.FuncAdd; Material.MaterialParams.BlendFunction.AlphaSrcFunc = PICABlendFunc.SourceAlpha; if (Mesh.Name.Contains("rl")) { int digit = Mesh.Name[Mesh.Name.IndexOf("rl") + 2] - '0'; if (digit >= 0 && digit <= 3) { //set renderlayer M.Priority = digit; } } } Material.MaterialParams.AlphaTest.Enabled = true; Material.MaterialParams.AlphaTest.Function = PICATestFunc.Greater; Material.MaterialParams.AlphaTest.Reference = 0; } if (Mesh.Name.Contains("unculled")) { Material.MaterialParams.FaceCulling = PICAFaceCulling.Never; } if (Material.Name.Contains("mado") || Material.Name.Contains("window")) { Material.MaterialParams.LightSetIndex = 1; } Material.TextureMappers[0].MagFilter = H3DTextureMagFilter.Linear; if (Model.Materials.Find(Material.Name) != -1) { M.MaterialIndex = (ushort)Model.Materials.Find(Material.Name); MaterialIndex--; M.UpdateBoolUniforms(Model.Materials[M.MaterialIndex]); } else { Model.Materials.Add(Material); M.UpdateBoolUniforms(Material); } Model.AddMesh(M); } /* * On Pokémon, the root bone (on the animaiton file) is used by the game to move * characters around, and all rigged bones are parented to this bone. * It's usually the Waist bone, that points upward and is half the character height. */ /*Model.Skeleton.Add(new H3DBone( * new Vector3(0, Height * 0.5f, 0), * new Vector3(0, 0, (float)(Math.PI * 0.5)), * Vector3.One, * "Waist", * -1));*/ //Model.Skeleton[0].CalculateTransform(Model.Skeleton); Output.Models.Add(Model); Output.CopyMaterials(); } return(Output); }