示例#1
0
 public GLModelViewer(VrfGuiContext guiContext, PhysAggregateData phys)
     : base(guiContext, Frustum.CreateEmpty())
 {
     this.phys = phys;
 }
示例#2
0
        protected override void LoadScene()
        {
            if (model != null)
            {
                modelSceneNode = new ModelSceneNode(Scene, model);
                SetAvailableAnimations(modelSceneNode.GetSupportedAnimationNames());
                Scene.Add(modelSceneNode, false);

                phys = model.GetEmbeddedPhys();
                if (phys == null)
                {
                    var refPhysicsPaths = model.GetReferencedPhysNames();
                    if (refPhysicsPaths.Any())
                    {
                        //TODO are there any models with more than one vphys?
                        if (refPhysicsPaths.Count() != 1)
                        {
                            Console.WriteLine($"Model has more than 1 vphys ({refPhysicsPaths.Count()})." +
                                              " Please report this on https://github.com/SteamDatabase/ValveResourceFormat and provide the file that caused this.");
                        }

                        var newResource = Scene.GuiContext.LoadFileByAnyMeansNecessary(refPhysicsPaths.First() + "_c");
                        if (newResource != null)
                        {
                            phys = (PhysAggregateData)newResource.DataBlock;
                        }
                    }
                }

                var meshGroups = modelSceneNode.GetMeshGroups();

                if (meshGroups.Count() > 1)
                {
                    meshGroupListBox = ViewerControl.AddMultiSelection("Mesh Group", selectedGroups =>
                    {
                        modelSceneNode.SetActiveMeshGroups(selectedGroups);
                    });

                    meshGroupListBox.Items.AddRange(modelSceneNode.GetMeshGroups().ToArray <object>());
                    foreach (var group in modelSceneNode.GetActiveMeshGroups())
                    {
                        meshGroupListBox.SetItemChecked(meshGroupListBox.FindStringExact(group), true);
                    }
                }

                var materialGroups = model.GetMaterialGroups();

                if (materialGroups.Count() > 1)
                {
                    materialGroupListBox = ViewerControl.AddSelection("Material Group", (selectedGroup, _) =>
                    {
                        modelSceneNode?.SetSkin(selectedGroup);
                    });

                    materialGroupListBox.Items.AddRange(materialGroups.ToArray <object>());
                    materialGroupListBox.SelectedIndex = 0;
                }

                modelSceneNode.AnimationController.RegisterUpdateHandler((animation, frame) =>
                {
                    if (animationTrackBar.TrackBar.Value != frame)
                    {
                        animationTrackBar.UpdateValueSilently(frame);
                    }
                    var maximum = animation == null ? 1 : animation.FrameCount - 1;
                    if (animationTrackBar.TrackBar.Maximum != maximum)
                    {
                        animationTrackBar.TrackBar.Maximum = maximum;
                    }
                    animationTrackBar.Enabled  = animation != null;
                    animationPlayPause.Enabled = animation != null;
                });
            }
            else
            {
                SetAvailableAnimations(Enumerable.Empty <string>());
            }

            if (mesh != null)
            {
                meshSceneNode = new MeshSceneNode(Scene, mesh);
                Scene.Add(meshSceneNode, false);
            }

            if (phys != null)
            {
                physSceneNode = new PhysSceneNode(Scene, phys);
                Scene.Add(physSceneNode, false);

                //disabled by default. Enable if viewing only phys or model without meshes
                physSceneNode.Enabled = (modelSceneNode == null || !modelSceneNode.RenderableMeshes.Any());

                ViewerControl.AddCheckBox("Show Physics", physSceneNode.Enabled, (v) => { physSceneNode.Enabled = v; });
            }
        }
        public PhysSceneNode(Scene scene, PhysAggregateData phys)
            : base(scene)
        {
            this.phys = phys;

            var verts = new List <float>();
            var inds  = new List <int>();

            var bindPose = phys.Data.GetArray("m_bindPose")
                           .Select(v => Matrix4x4FromArray(v
                                                           .Select(m => Convert.ToSingle(m.Value))
                                                           .ToArray()))
                           .ToArray();

            if (bindPose.Length == 0)
            {
                bindPose = new Matrix4x4[] { Matrix4x4.Identity };
            }
            //m_boneParents

            bool firstBbox = true;

            var parts = phys.Data.GetArray("m_parts");

            for (int p = 0; p < parts.Length; p++)
            {
                var shape = parts[p].GetSubCollection("m_rnShape");

                var spheres = shape.GetArray("m_spheres");
                foreach (var s in spheres)
                {
                    var sphere = s.GetSubCollection("m_Sphere");
                    var center = sphere.GetSubCollection("m_vCenter").ToVector3();
                    var radius = sphere.GetFloatProperty("m_flRadius");

                    if (bindPose.Any())
                    {
                        center = Vector3.Transform(center, bindPose[p]);
                    }

                    AddSphere(verts, inds, center, radius);

                    AABB bbox = new AABB(center + new Vector3(radius),
                                         center - new Vector3(radius));
                    LocalBoundingBox = firstBbox ? bbox : LocalBoundingBox.Union(bbox);
                    firstBbox        = false;
                }

                var capsules = shape.GetArray("m_capsules");
                foreach (var c in capsules)
                {
                    var capsule = c.GetSubCollection("m_Capsule");
                    var center  = capsule.GetArray("m_vCenter").Select(v => v.ToVector3()).ToArray();
                    var radius  = capsule.GetFloatProperty("m_flRadius");

                    center[0] = Vector3.Transform(center[0], bindPose[p]);
                    center[1] = Vector3.Transform(center[1], bindPose[p]);

                    AddCapsule(verts, inds, center[0], center[1], radius);
                    foreach (var cn in center)
                    {
                        AABB bbox = new AABB(cn + new Vector3(radius),
                                             cn - new Vector3(radius));
                        LocalBoundingBox = firstBbox ? bbox : LocalBoundingBox.Union(bbox);
                        firstBbox        = false;
                    }
                }
                var hulls = shape.GetArray("m_hulls");
                foreach (var h in hulls)
                {
                    var hull = h.GetSubCollection("m_Hull");
                    //m_vCentroid
                    //m_flMaxAngularRadius
                    //m_Vertices
                    var vertices   = hull.GetArray("m_Vertices");
                    var vertOffset = verts.Count / 7;
                    foreach (var v in vertices)
                    {
                        var vec = v.ToVector3();
                        if (bindPose.Any())
                        {
                            vec = Vector3.Transform(vec, bindPose[p]);
                        }
                        verts.Add(vec.X);
                        verts.Add(vec.Y);
                        verts.Add(vec.Z);
                        //color red
                        verts.Add(1);
                        verts.Add(0);
                        verts.Add(0);
                        verts.Add(1);
                    }
                    //m_Planes
                    var edges = hull.GetArray("m_Edges");
                    foreach (var e in edges)
                    {
                        inds.Add((int)(vertOffset + e.GetIntegerProperty("m_nOrigin")));
                        var next = edges[e.GetIntegerProperty("m_nNext")];
                        inds.Add((int)(vertOffset + next.GetIntegerProperty("m_nOrigin")));
                    }
                    //m_Faces
                    var  bounds = hull.GetSubCollection("m_Bounds");
                    AABB bbox   = new AABB(bounds.GetSubCollection("m_vMinBounds").ToVector3(),
                                           bounds.GetSubCollection("m_vMaxBounds").ToVector3());

                    LocalBoundingBox = firstBbox ? bbox : LocalBoundingBox.Union(bbox);
                    firstBbox        = false;
                }
                var meshes = shape.GetArray("m_meshes");
                foreach (var m in meshes)
                {
                    var mesh = m.GetSubCollection("m_Mesh");
                    //m_Nodes

                    var       vertOffset = verts.Count / 7;
                    Vector3[] vertices   = null;
                    if (mesh is NTROStruct)
                    {
                        //NTRO has vertices as array of structs
                        var verticesArr = mesh.GetArray("m_Vertices");
                        vertices = verticesArr.Select(v => v.ToVector3()).ToArray();
                    }
                    else
                    {
                        //KV3 has vertices as blob
                        var verticesBlob = mesh.GetArray <byte>("m_Vertices");
                        vertices = Enumerable.Range(0, verticesBlob.Length / 12)
                                   .Select(i => new Vector3(BitConverter.ToSingle(verticesBlob, i * 12),
                                                            BitConverter.ToSingle(verticesBlob, (i * 12) + 4),
                                                            BitConverter.ToSingle(verticesBlob, (i * 12) + 8)))
                                   .ToArray();
                    }

                    foreach (var vec in vertices)
                    {
                        var v = vec;
                        if (bindPose.Any())
                        {
                            v = Vector3.Transform(vec, bindPose[p]);
                        }
                        verts.Add(v.X);
                        verts.Add(v.Y);
                        verts.Add(v.Z);
                        //color green
                        verts.Add(0);
                        verts.Add(1);
                        verts.Add(0);
                        verts.Add(1);
                    }

                    int[] triangles = null;
                    if (mesh is NTROStruct)
                    {
                        //NTRO and SOME KV3 has triangles as array of structs
                        var trianglesArr = mesh.GetArray("m_Triangles");
                        triangles = trianglesArr.SelectMany(t => t.GetArray <object>("m_nIndex").
                                                            Select(Convert.ToInt32)).ToArray();
                    }
                    else
                    {
                        //some KV3 has triangles as blob
                        var trianglesBlob = mesh.GetArray <byte>("m_Triangles");
                        triangles = new int[trianglesBlob.Length / 4];
                        System.Buffer.BlockCopy(trianglesBlob, 0, triangles, 0, trianglesBlob.Length);
                    }

                    for (int i = 0; i < triangles.Length; i += 3)
                    {
                        inds.Add(vertOffset + triangles[i]);
                        inds.Add(vertOffset + triangles[i + 1]);
                        inds.Add(vertOffset + triangles[i + 1]);
                        inds.Add(vertOffset + triangles[i + 2]);
                        inds.Add(vertOffset + triangles[i + 2]);
                        inds.Add(vertOffset + triangles[i]);
                    }

                    AABB bbox = new AABB(mesh.GetSubCollection("m_vMin").ToVector3(),
                                         mesh.GetSubCollection("m_vMax").ToVector3());
                    LocalBoundingBox = firstBbox ? bbox : LocalBoundingBox.Union(bbox);
                    firstBbox        = false;
                }
                //m_CollisionAttributeIndices

                //Console.WriteLine($"Phys mesh verts {verts.Count} inds {inds.Count}");
            }

            shader = Scene.GuiContext.ShaderLoader.LoadShader("vrf.grid", new Dictionary <string, bool>());
            GL.UseProgram(shader.Program);

            vaoHandle = GL.GenVertexArray();
            GL.BindVertexArray(vaoHandle);

            vboHandle = GL.GenBuffer();
            GL.BindBuffer(BufferTarget.ArrayBuffer, vboHandle);
            GL.BufferData(BufferTarget.ArrayBuffer, verts.Count * sizeof(float), verts.ToArray(), BufferUsageHint.StaticDraw);

            iboHandle  = GL.GenBuffer();
            indexCount = inds.Count;
            GL.BindBuffer(BufferTarget.ElementArrayBuffer, iboHandle);
            GL.BufferData(BufferTarget.ElementArrayBuffer, inds.Count * sizeof(int), inds.ToArray(), BufferUsageHint.StaticDraw);

            const int stride = sizeof(float) * 7;
            var       positionAttributeLocation = GL.GetAttribLocation(shader.Program, "aVertexPosition");

            GL.EnableVertexAttribArray(positionAttributeLocation);
            GL.VertexAttribPointer(positionAttributeLocation, 3, VertexAttribPointerType.Float, false, stride, 0);

            var colorAttributeLocation = GL.GetAttribLocation(shader.Program, "aVertexColor");

            GL.EnableVertexAttribArray(colorAttributeLocation);
            GL.VertexAttribPointer(colorAttributeLocation, 4, VertexAttribPointerType.Float, false, stride, sizeof(float) * 3);

            GL.BindVertexArray(0);
        }