private bool GetBoneRT( H3DAnimation Anim, H3DDict <H3DBone> Skeleton, string Name, int Frame, out Vector3 Rotation, out Vector3 Translation) { if (!Skeleton.Contains(Name)) { Rotation = Vector3.Zero; Translation = Vector3.Zero; return(false); } H3DBone PoseBone = Skeleton[Name]; Rotation = PoseBone.Rotation; Translation = PoseBone.Translation; H3DAnimationElement Bone = Anim.Elements.Find(x => x.Name == Name); if (Bone != null) { H3DAnimTransform Transform = (H3DAnimTransform)Bone.Content; if (Transform.RotationX.Exists) { Rotation.X = Transform.RotationX.GetFrameValue(Frame); } if (Transform.RotationY.Exists) { Rotation.Y = Transform.RotationY.GetFrameValue(Frame); } if (Transform.RotationZ.Exists) { Rotation.Z = Transform.RotationZ.GetFrameValue(Frame); } if (Transform.TranslationX.Exists) { Translation.X = Transform.TranslationX.GetFrameValue(Frame); } if (Transform.TranslationY.Exists) { Translation.Y = Transform.TranslationY.GetFrameValue(Frame); } if (Transform.TranslationZ.Exists) { Translation.Z = Transform.TranslationZ.GetFrameValue(Frame); } } return(true); }
private string GetBonePath(H3DBone bone, H3DDict <H3DBone> skeleton, string currentPath = "") { currentPath = bone.Name + currentPath; if (bone.ParentIndex < 0) { return(currentPath); } else { return(GetBonePath(skeleton[bone.ParentIndex], skeleton, "/" + currentPath)); } }
public GFBone(H3DBone Bone, H3DDict <H3DBone> Skeleton) { Flags = (byte)(Bone.ParentIndex == -1 ? 2 : 1); Name = Bone.Name; Rotation = Bone.Rotation; Translation = Bone.Translation; Scale = Bone.Scale; if (Bone.ParentIndex != -1) { Parent = Skeleton[Bone.ParentIndex].Name; } else { Parent = "Origin"; } }
public void Load(H3DBone bone, BCH bch) { BchParent = bch; Checked = true; Bone = bone; Text = bone.Name; parentIndex = bone.ParentIndex; RotationType = BoneRotationType.Euler; Position = new OpenTK.Vector3( bone.Translation.X, bone.Translation.Y, bone.Translation.Z); EulerRotation = new OpenTK.Vector3( bone.Rotation.X, bone.Rotation.Y, bone.Rotation.Z); Scale = new OpenTK.Vector3( bone.Scale.X, bone.Scale.Y, bone.Scale.Z); }
public H3DAnimation ToH3DSkeletalAnimation(H3DDict <H3DBone> Skeleton) { H3DAnimation Output = new H3DAnimation() { Name = "GFMotion", FramesCount = FramesCount, AnimationType = H3DAnimationType.Skeletal }; foreach (GF1MotBoneTransform Bone in Bones) { H3DAnimTransform Transform = new H3DAnimTransform(); SetKeyFrameGroup(Bone.TranslationX, Transform.TranslationX, 0); SetKeyFrameGroup(Bone.TranslationY, Transform.TranslationY, 1); SetKeyFrameGroup(Bone.TranslationZ, Transform.TranslationZ, 2); SetKeyFrameGroup(Bone.RotationX, Transform.RotationX, 3); SetKeyFrameGroup(Bone.RotationY, Transform.RotationY, 4); SetKeyFrameGroup(Bone.RotationZ, Transform.RotationZ, 5); SetKeyFrameGroup(Bone.ScaleX, Transform.ScaleX, 6); SetKeyFrameGroup(Bone.ScaleY, Transform.ScaleY, 7); SetKeyFrameGroup(Bone.ScaleZ, Transform.ScaleZ, 8); Output.Elements.Add(new H3DAnimationElement() { Name = Bone.Name, Content = Transform, TargetType = H3DTargetType.Bone, PrimitiveType = H3DPrimitiveType.Transform }); } //If we don't have a Skeleton then can't convert anything, just return with //what we have. if (Skeleton == null) { return(Output); } /* * Transform World Space bones to Local Space. * Not all animations have those. * This can be improved, for example, by supporting Scales aswell, * and checking for the special case where the World Space bone have no parent. * Those cases doesn't actually happen in any of the observed animations, * but it's always good pratice to check all fail paths. */ int AnimIdx = 0; foreach (GF1MotBoneTransform Bone in Bones) { if (Bone.IsWorldSpace) { if (!Skeleton.Contains(Bone.Name)) { break; } H3DBone PoseBone = Skeleton[Bone.Name]; Vector3[] LocalTrans = new Vector3[FramesCount + 1]; Vector3[] ParentRot = new Vector3[FramesCount + 1]; int BoneIndex = Skeleton.Find(Bone.Name); int ParentIndex = Skeleton[BoneIndex].ParentIndex; string ParentName = Skeleton[ParentIndex].Name; for (int Frame = 0; Frame < FramesCount + 1; Frame++) { Matrix4x4 Transform = Matrix4x4.Identity; int b = BoneIndex; while ((b = Skeleton[b].ParentIndex) != -1) { GetBoneRT( Output, Skeleton, Skeleton[b].Name, Frame, out Vector3 R, out Vector3 T); Transform *= Matrix4x4.CreateRotationX(R.X); Transform *= Matrix4x4.CreateRotationY(R.Y); Transform *= Matrix4x4.CreateRotationZ(R.Z); Transform *= Matrix4x4.CreateTranslation(T); } GetBoneRT( Output, Skeleton, ParentName, Frame, out Vector3 PR, out Vector3 PT); GetBoneRT( Output, Skeleton, Bone.Name, Frame, out Vector3 BR, out Vector3 BT); Matrix4x4.Invert(Transform, out Matrix4x4 ITransform); BT = Vector3.Transform(BT, ITransform); Quaternion Rotation = VectorExtensions.CreateRotationBetweenVectors(PT, BT); LocalTrans[Frame] = Vector3.Transform(BT, Quaternion.Inverse(Rotation)); ParentRot[Frame] = Rotation.ToEuler(); } H3DAnimationElement B_Anim = Output.Elements[AnimIdx]; H3DAnimationElement P_Anim = Output.Elements.Find(x => x.Name == ParentName); if (P_Anim == null) { P_Anim = new H3DAnimationElement() { Name = ParentName, Content = new H3DAnimTransform(), TargetType = H3DTargetType.Bone, PrimitiveType = H3DPrimitiveType.Transform }; Output.Elements.Add(P_Anim); } H3DAnimTransform B_AT = (H3DAnimTransform)B_Anim.Content; H3DAnimTransform P_AT = (H3DAnimTransform)P_Anim.Content; AddVectors(LocalTrans, B_AT.TranslationX, B_AT.TranslationY, B_AT.TranslationZ); if (!P_AT.RotationExists) { AddVectors(ParentRot, P_AT.RotationX, P_AT.RotationY, P_AT.RotationZ); } } AnimIdx++; } return(Output); }
private void BuildAnimations(H3DAnimation anim, H3DModel model) { // Note: Because bones and armatures in Blender are an immense calvary, the animations are exported as a separate XML file, that we can re-import in the final engine (Unity for instance) as a readable format. animationXml = new XmlDocument(); var xmlRoot = animationXml.CreateElement("animation"); var rootName = animationXml.CreateAttribute("name"); rootName.Value = anim.Name; var rootLength = animationXml.CreateAttribute("framesCount"); rootLength.Value = (anim.FramesCount + 1).ToString(); xmlRoot.Attributes.Append(rootName); xmlRoot.Attributes.Append(rootLength); animationXml.AppendChild(xmlRoot); for (int frame = 0; frame <= anim.FramesCount; ++frame) { var xmlFrame = animationXml.CreateElement("frame"); var frameNumber = animationXml.CreateAttribute("number"); frameNumber.Value = frame.ToString(); xmlFrame.Attributes.Append(frameNumber); xmlRoot.AppendChild(xmlFrame); } pythonScript.AppendLine($"act1 = bpy.data.actions.new('{anim.Name}')"); pythonScript.AppendLine($"root.animation_data_create()"); pythonScript.AppendLine($"root.animation_data.action = act1"); foreach (var element in anim.Elements) { var fc = new BLENDFCurve(element.Content); if (fc.IsNull || fc.NothingExists()) { continue; } var bone = model.Skeleton.FirstOrDefault(x => x.Name == element.Name); Matrix4x4.Decompose(bone.Transform, out var _, out var lr, out var ll); Matrix4x4.Decompose(bone.GetWorldTransform(model.Skeleton), out var _, out var wr, out var wl); H3DBone parentbone = null; if (bone.ParentIndex != -1) { parentbone = model.Skeleton[bone.ParentIndex]; } var bData = $"pose.bones[\"{element.Name}\"]"; pythonScript.AppendLine($"flx = act1.fcurves.new(data_path='{bData}.location', index=0)"); pythonScript.AppendLine($"fly = act1.fcurves.new(data_path='{bData}.location', index=1)"); pythonScript.AppendLine($"flz = act1.fcurves.new(data_path='{bData}.location', index=2)"); if (fc.IsQuaternion) { pythonScript.AppendLine($"root.pose.bones['{element.Name}'].rotation_mode = 'QUATERNION'"); pythonScript.AppendLine($"frw = act1.fcurves.new(data_path='{bData}.rotation_quaternion', index=0)"); pythonScript.AppendLine($"frx = act1.fcurves.new(data_path='{bData}.rotation_quaternion', index=1)"); pythonScript.AppendLine($"fry = act1.fcurves.new(data_path='{bData}.rotation_quaternion', index=2)"); pythonScript.AppendLine($"frz = act1.fcurves.new(data_path='{bData}.rotation_quaternion', index=3)"); } else { pythonScript.AppendLine($"root.pose.bones['{element.Name}'].rotation_mode = 'XYZ'"); pythonScript.AppendLine($"frx = act1.fcurves.new(data_path='{bData}.rotation_euler', index=0)"); pythonScript.AppendLine($"fry = act1.fcurves.new(data_path='{bData}.rotation_euler', index=1)"); pythonScript.AppendLine($"frz = act1.fcurves.new(data_path='{bData}.rotation_euler', index=2)"); } pythonScript.AppendLine($"fsx = act1.fcurves.new(data_path='{bData}.scale', index=0)"); pythonScript.AppendLine($"fsy = act1.fcurves.new(data_path='{bData}.scale', index=1)"); pythonScript.AppendLine($"fsz = act1.fcurves.new(data_path='{bData}.scale', index=2)"); for (int frame = 0; frame <= anim.FramesCount; ++frame) { var xmlElement = animationXml.CreateElement("element"); var elemName = animationXml.CreateAttribute("name"); elemName.Value = element.Name; var elemPath = animationXml.CreateAttribute("path"); elemPath.Value = GetBonePath(bone, model.Skeleton); xmlElement.Attributes.Append(elemName); xmlElement.Attributes.Append(elemPath); var l = ll * SCALE - fc.GetLocationAtFrame(frame) * SCALE; pythonScript.AppendLine($"flx.keyframe_points.insert({frame + 1}, {l.Z})"); pythonScript.AppendLine($"fly.keyframe_points.insert({frame + 1}, {-l.Y})"); pythonScript.AppendLine($"flz.keyframe_points.insert({frame + 1}, {-l.X})"); var locAttr = animationXml.CreateAttribute("location"); locAttr.Value = $"{l.X},{l.Y},{l.Z}"; xmlElement.Attributes.Append(locAttr); var r = fc.GetRotationAtFrame(frame); if (r is Vector3 rv) { //pythonScript.AppendLine($"frx.keyframe_points.insert({frame + 1}, {rv.Z})"); //pythonScript.AppendLine($"fry.keyframe_points.insert({frame + 1}, {-rv.Y})"); //pythonScript.AppendLine($"frz.keyframe_points.insert({frame + 1}, {-rv.X})"); var rotAttr = animationXml.CreateAttribute("rotation"); rotAttr.Value = $"{rv.X},{rv.Y},{rv.Z}"; xmlElement.Attributes.Append(rotAttr); } else if (r is Quaternion rq) { //rq = Quaternion.Multiply(lr, Quaternion.Inverse(rq)); //pythonScript.AppendLine($"frw.keyframe_points.insert({frame + 1}, {rq.W})"); //pythonScript.AppendLine($"frx.keyframe_points.insert({frame + 1}, {rq.X})"); //pythonScript.AppendLine($"fry.keyframe_points.insert({frame + 1}, {rq.Y})"); //pythonScript.AppendLine($"frz.keyframe_points.insert({frame + 1}, {rq.Z})"); var rotAttr = animationXml.CreateAttribute("rotation"); rotAttr.Value = $"{rq.X},{rq.Y},{rq.Z},{rq.W}"; xmlElement.Attributes.Append(rotAttr); } var s = fc.GetScaleAtFrame(frame); pythonScript.AppendLine($"fsx.keyframe_points.insert({frame + 1}, {s.X})"); pythonScript.AppendLine($"fsy.keyframe_points.insert({frame + 1}, {s.Y})"); pythonScript.AppendLine($"fsz.keyframe_points.insert({frame + 1}, {s.Z})"); var scaleAttr = animationXml.CreateAttribute("scale"); scaleAttr.Value = $"{s.X},{s.Y},{s.Z}"; xmlElement.Attributes.Append(scaleAttr); xmlRoot.SelectSingleNode($"frame[@number={frame}]").AppendChild(xmlElement); } } }
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 void Render() { Shader Shader = Parent.Shaders[BaseMesh.MaterialIndex]; H3DMaterialParams Params = Material.MaterialParams; Params.BlendFunction.SetGL(); Params.StencilTest.SetGL(); Params.StencilOperation.SetGL(); Params.DepthColorMask.SetGL(); Params.AlphaTest.SetGL(); GL.BlendColor(Params.BlendColor.ToColor4()); GL.CullFace(Params.FaceCulling.ToCullFaceMode()); GL.PolygonOffset(0, Params.PolygonOffsetUnit); SetState(EnableCap.Blend, Params.ColorOperation.BlendMode == PICABlendMode.Blend); SetState(EnableCap.StencilTest, Params.StencilTest.Enabled); SetState(EnableCap.DepthTest, Params.DepthColorMask.Enabled); SetState(EnableCap.CullFace, Params.FaceCulling != PICAFaceCulling.Never); Parent.Renderer.TryBindLUT(4, Params.LUTDist0TableName, Params.LUTDist0SamplerName); Parent.Renderer.TryBindLUT(5, Params.LUTDist1TableName, Params.LUTDist1SamplerName); Parent.Renderer.TryBindLUT(6, Params.LUTFresnelTableName, Params.LUTFresnelSamplerName); Parent.Renderer.TryBindLUT(7, Params.LUTReflecRTableName, Params.LUTReflecRSamplerName); Parent.Renderer.TryBindLUT(8, Params.LUTReflecGTableName ?? Params.LUTReflecRTableName, Params.LUTReflecGSamplerName ?? Params.LUTReflecRSamplerName); Parent.Renderer.TryBindLUT(9, Params.LUTReflecBTableName ?? Params.LUTReflecRTableName, Params.LUTReflecBSamplerName ?? Params.LUTReflecRSamplerName); //Setup texture units if (Texture0Name != null) { //Only the texture unit 0 can have a Cube Map texture if (Params.TextureCoords[0].MappingType == H3DTextureMappingType.CameraCubeEnvMap) { Parent.Renderer.TryBindTexture(3, Texture0Name); SetWrapAndFilter(TextureTarget.TextureCubeMap, 0); } else { Parent.Renderer.TryBindTexture(0, Texture0Name); SetWrapAndFilter(TextureTarget.Texture2D, 0); } } if (Texture1Name != null) { Parent.Renderer.TryBindTexture(1, Texture1Name); SetWrapAndFilter(TextureTarget.Texture2D, 1); } if (Texture2Name != null) { Parent.Renderer.TryBindTexture(2, Texture2Name); SetWrapAndFilter(TextureTarget.Texture2D, 2); } Shader.SetVtxVector4(DefaultShaderIds.PosOffs, PosOffs); Shader.SetVtxVector4(DefaultShaderIds.IrScale + 0, Scales0); Shader.SetVtxVector4(DefaultShaderIds.IrScale + 1, Scales1); //Render all SubMeshes GL.BindVertexArray(VAOHandle); foreach (H3DSubMesh SM in BaseMesh.SubMeshes) { bool SmoothSkin = SM.Skinning == H3DSubMeshSkinning.Smooth; Matrix4[] Transforms = new Matrix4[20]; for (int Index = 0; Index < Transforms.Length; Index++) { Matrix4 Transform = Matrix4.Identity; if (Index < SM.BoneIndicesCount && SM.BoneIndices[Index] < Parent.SkeletonTransforms.Length) { int BoneIndex = SM.BoneIndices[Index]; Transform = Parent.SkeletonTransforms[BoneIndex]; if (SmoothSkin) { Transform = Parent.InverseTransforms[BoneIndex] * Transform; } //Build billboard matrix if needed (used to make the bones follow the camera view) H3DBone Bone = Parent.BaseModel.Skeleton[BoneIndex]; if (Bone.BillboardMode != H3DBillboardMode.Off) { Matrix4 BillMtx = Matrix4.Identity; Matrix4 WrldMtx = Parent.Transform * Parent.Renderer.Camera.ViewMatrix; Matrix4 BoneMtx = Matrix4.CreateRotationX(Bone.Rotation.X) * Matrix4.CreateRotationY(Bone.Rotation.Y) * Matrix4.CreateRotationZ(Bone.Rotation.Z); Vector3 X, Y, Z; X = Y = Z = Vector3.Zero; switch (Bone.BillboardMode) { case H3DBillboardMode.World: Y = Vector3.Normalize(WrldMtx.Row1.Xyz); Z = Vector3.UnitZ; break; case H3DBillboardMode.WorldViewpoint: Y = Vector3.Normalize(WrldMtx.Row1.Xyz); Z = Vector3.Normalize(-WrldMtx.Row3.Xyz); break; case H3DBillboardMode.Screen: Y = Vector3.Normalize(BoneMtx.Row1.Xyz); Z = Vector3.UnitZ; break; case H3DBillboardMode.ScreenViewpoint: Y = Vector3.Normalize(BoneMtx.Row1.Xyz); Z = Vector3.Normalize(-WrldMtx.Row3.Xyz); break; case H3DBillboardMode.YAxial: Y = Vector3.Normalize(WrldMtx.Row1.Xyz); Z = Vector3.UnitZ; break; case H3DBillboardMode.YAxialViewpoint: Y = Vector3.Normalize(WrldMtx.Row1.Xyz); Z = Vector3.Normalize(-WrldMtx.Row3.Xyz); break; } X = Vector3.Normalize(Vector3.Cross(Y, Z)); Y = Vector3.Normalize(Vector3.Cross(Z, X)); BillMtx.Row0 = new Vector4(X.X, Y.X, Z.X, 0); BillMtx.Row1 = new Vector4(X.Y, Y.Y, Z.Y, 0); BillMtx.Row2 = new Vector4(X.Z, Y.Z, Z.Z, 0); BillMtx.Row3 = (Transform * WrldMtx).Row3; WrldMtx = WrldMtx.ClearScale(); WrldMtx.Invert(); Transform = Matrix4.CreateScale(Transform.ExtractScale()) * BillMtx * WrldMtx; } } Shader.SetVtx3x4Array(DefaultShaderIds.UnivReg + Index * 3, Transform); } int BoolsLocation = GL.GetUniformLocation(Shader.Handle, ShaderGenerator.BoolsName); GL.Uniform1(BoolsLocation, SM.BoolUniforms); GL.DrawElements(PrimitiveType.Triangles, SM.Indices.Length, DrawElementsType.UnsignedShort, SM.Indices); } GL.BindVertexArray(0); GL.BindTexture(TextureTarget.Texture2D, 0); GL.BindTexture(TextureTarget.TextureCubeMap, 0); }
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 H3DBoneWrapper(STSkeleton skeleton, H3DBone bone, BCH bch) : base(skeleton) { BchParent = bch; Load(bone, bch); }