Ejemplo n.º 1
0
    /// <summary>
    /// Calculates the resulting force on this skin vertex based on
    /// the gravity and the spring forces of all edges starting in this skin vertex.
    /// This value will be cached and used in the associated 'ApplyAcceleration()' method.
    /// </summary>
    public void CalculateResultingForce()
    {
        _resultingForce = Mathf.Atan(currentPosition.y) * Physics.gravity * 0.05f * _skinMesh.gravityMultiplier + addedForces;

        Vector3 skinEdgesResultingForce = Vector3.zero;

        foreach (SkinEdge skinEdge in edges)
        {
            skinEdge.ShuffleVertexIndices(vertexIndex);
            SkinVertex otherSkinVertex = _skinMesh.GetSkinVertex(skinEdge.vertex1Index);
            skinEdgesResultingForce += skinEdge.cachedSpringForce * (otherSkinVertex.currentPosition - currentPosition).normalized;
        }

        if (threads.Count == 0)
        {
            _resultingForce += skinEdgesResultingForce;
        }
        else
        {
            Vector3 threadsResultingForce = Vector3.zero;
            foreach (Thread thread in threads)
            {
                thread.ShuffleVertexIndices(vertexIndex);
                SkinVertex otherSkinVertex = _skinMesh.GetSkinVertex(thread.vertex1Index);
                threadsResultingForce += thread.cachedSpringForce * (otherSkinVertex.currentPosition - currentPosition).normalized;
            }

            _resultingForce += skinEdgesResultingForce + threadsResultingForce;
        }
    }
Ejemplo n.º 2
0
    /// <summary>
    /// Update is called every frame, if the MonoBehaviour is enabled.
    /// </summary>
    public void Update()
    {
        if (!Input.GetKey(KeyCode.LeftControl) && !Input.GetKey(KeyCode.RightControl))
        {
            threadStart = null;
        }
        if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
        {
            //we are using the scalpel
            return;
        }

        if (Input.GetMouseButtonDown(0) && (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl)))
        {
            if (threadStart == null)
            {
                Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
                threadStart = _skinMesh.GetClosestSkinVertexToLineSgement(ray.origin, ray.GetPoint(10f), _skin.snapDistance);
            }
            else
            {
                Ray        ray        = Camera.main.ScreenPointToRay(Input.mousePosition);
                SkinVertex skinVertex = _skinMesh.GetClosestSkinVertexToLineSgement(ray.origin, ray.GetPoint(10f), _skin.snapDistance);
                if (skinVertex != null)
                {
                    _skinMesh.AddThread(threadStart.vertexIndex, skinVertex.vertexIndex);
                    threadStart = skinVertex;
                }
            }
        }
    }
Ejemplo n.º 3
0
    /// <summary>
    /// Update is called every frame, if the MonoBehaviour is enabled.
    /// </summary>
    public void Update()
    {
        if (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl))
        {
            //we are using the needle
            return;
        }

        if (Input.GetMouseButton(0) && (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)))
        {
            if (cutStart == null)
            {
                Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
                cutStart = _skinMesh.GetClosestSkinVertexToLineSgement(ray.origin, ray.GetPoint(10f), _skin.snapDistance);
            }
            else
            {
                Ray        ray    = Camera.main.ScreenPointToRay(Input.mousePosition);
                SkinVertex cutEnd = _skinMesh.GetClosestSkinVertexToLineSgement(ray.origin, ray.GetPoint(10f), _skin.snapDistance);
                _skinMesh.Cut(cutStart, cutEnd, _skin.snapDistance, cutDepth);
                cutStart = cutEnd;
            }
        }
        else
        {
            _cutStart = null;
        }
    }
Ejemplo n.º 4
0
    /// <summary>
    /// Update is called every frame, if the MonoBehaviour is enabled.
    /// </summary>
    public void Update()
    {
        if (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl))
        {
            //we are using the needle
            return;
        }
        if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
        {
            //we are using the scalpel
            return;
        }
        if (Input.GetMouseButton(0))
        {
            if (dragSkinVertex == null)
            {
                Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
                dragSkinVertex = _skinMesh.GetClosestSkinVertexToLineSgement(ray.origin, ray.GetPoint(10f), _skin.snapDistance);
                if (dragSkinVertex != null)
                {
                    originalVertexHeight = dragSkinVertex.currentPosition.y;
                }
                _draggingHeight = 0f;
            }
            else
            {
                if (_draggingHeight < maxHeight)
                {
                    _draggingHeight = Mathf.Min(maxHeight, _draggingHeight + Time.deltaTime * maxHeight); //1 second to get to the max height
                }
                Vector3 newPosition = Camera.main.ScreenToWorldPoint(
                    new Vector3(Input.mousePosition.x, Input.mousePosition.y, Camera.main.transform.position.y - (originalVertexHeight + _draggingHeight)));

                Vector3 skinVertexForce           = dragSkinVertex.resultingForce;
                Vector3 skinVertexForceNormalized = skinVertexForce.normalized;
                Vector3 newForce = newPosition - dragSkinVertex.currentPosition;

                //The size of the projection of the new force on the normalized skin vertex force.
                float newForceProjectedMagnitude = Vector3.Dot(newForce, skinVertexForceNormalized);

                if (newForceProjectedMagnitude < 0.0f)
                {
                    float multiplier = Mathf.Clamp01(0.5f - 0.33f * Mathf.Atan(skinVertexForce.magnitude - maximumPullForce));
                    newPosition = dragSkinVertex.currentPosition + newForce * multiplier;
                }
                dragSkinVertex.currentPosition = newPosition;
            }
        }
        else
        {
            _dragSkinVertex = null;
        }
    }
Ejemplo n.º 5
0
        public ClumpBuffers(ITagContainer diContainer, RWClump clump)
        {
            var device       = diContainer.GetTag <GraphicsDevice>();
            var atomic       = clump.FindChildById(SectionId.Atomic, recursive: false) as RWAtomic;
            var geometry     = clump.FindChildById(SectionId.Geometry, true) as RWGeometry;
            var materialList = geometry?.FindChildById(SectionId.MaterialList, false) as RWMaterialList;
            var materials    = materialList?.children.Where(s => s is RWMaterial).Cast <RWMaterial>().ToArray();
            var morphTarget  = geometry?.morphTargets[0]; // TODO: morph support for the one model that uses it?

            if (geometry == null || morphTarget == null || materials == null || atomic == null)
            {
                throw new InvalidDataException("Could not find valid section structure in clump");
            }
            RWGeometry    = geometry;
            BSphereCenter = morphTarget.bsphereCenter;
            BSphereRadius = morphTarget.bsphereRadius;
            IsSolid       = atomic.flags.HasFlag(AtomicFlags.CollisionTest);

            var vertices = new ModelStandardVertex[morphTarget.vertices.Length];
            var bounds   = new Box(morphTarget.vertices.First(), Vector3.Zero);

            for (int i = 0; i < vertices.Length; i++)
            {
                vertices[i].pos   = morphTarget.vertices[i];
                vertices[i].color = geometry.colors.Length > 0 ? geometry.colors[i] : new IColor(255);
                vertices[i].tex   = geometry.texCoords.Length > 0 ? geometry.texCoords[0][i] : Vector2.Zero;
                bounds            = bounds.Union(vertices[i].pos);
            }
            Bounds       = bounds;
            vertexBuffer = device.ResourceFactory.CreateBuffer(new BufferDescription((uint)vertices.Length * ModelStandardVertex.Stride, BufferUsage.VertexBuffer));
            device.UpdateBuffer(vertexBuffer, 0, vertices);

            // TODO: might have to correlate to the materialIndices member of materialList
            var trianglesByMatIdx = geometry.triangles.GroupBy(t => t.m).Where(g => g.Count() > 0);
            var indices           = trianglesByMatIdx.SelectMany(
                g => g.SelectMany(t => new[] { t.v1, t.v2, t.v3 })
                ).ToArray();

            subMeshes = new SubMesh[trianglesByMatIdx.Count()];
            int nextIndexPtr = 0;

            foreach (var(group, idx) in trianglesByMatIdx.Indexed())
            {
                subMeshes[idx] = new SubMesh(nextIndexPtr, group.Count() * 3, materials[group.Key]);
                nextIndexPtr  += subMeshes[idx].IndexCount;
            }
            indexBuffer = device.ResourceFactory.CreateBuffer(new BufferDescription((uint)indices.Length * 2, BufferUsage.IndexBuffer));
            device.UpdateBuffer(indexBuffer, 0, indices);

            Skin = clump.FindChildById(SectionId.SkinPLG, true) as RWSkinPLG;
            if (Skin != null)
            {
                if (vertices.Length != Skin.vertexWeights.GetLength(0))
                {
                    throw new InvalidDataException("Vertex count in skin is not equal to geometry");
                }
                var skinVertices = new SkinVertex[vertices.Length];
                for (int i = 0; i < skinVertices.Length; i++)
                {
                    skinVertices[i].bone0     = Skin.vertexIndices[i, 0];
                    skinVertices[i].bone1     = Skin.vertexIndices[i, 1];
                    skinVertices[i].bone2     = Skin.vertexIndices[i, 2];
                    skinVertices[i].bone3     = Skin.vertexIndices[i, 3];
                    skinVertices[i].weights.X = Skin.vertexWeights[i, 0];
                    skinVertices[i].weights.Y = Skin.vertexWeights[i, 1];
                    skinVertices[i].weights.Z = Skin.vertexWeights[i, 2];
                    skinVertices[i].weights.W = Skin.vertexWeights[i, 3];
                }
                skinBuffer = device.ResourceFactory.CreateBuffer(new BufferDescription((uint)skinVertices.Length * SkinVertex.Stride, BufferUsage.VertexBuffer));
                device.UpdateBuffer(skinBuffer, 0, skinVertices);
            }
        }
Ejemplo n.º 6
0
        private SkelletalMesh GetMesh(GMeshContainer meshContainer, Bone root, VertexDescriptor vd)
        {
            SlimDX.Direct3D9.Mesh d3dMesh = meshContainer.Mesh;

            var adjacency                 = meshContainer.GetAdjacency();
            var meshMaterials             = meshContainer.GetMaterials();
            List <MeshMaterial> materials = new List <MeshMaterial>();

            for (int i = 0; i < meshMaterials.Length; i++)
            {
                var matd3d = meshMaterials[i].MaterialD3D;

                string textureFilename = meshMaterials[i].TextureFileName;
                if (textureFilename != null && !Path.IsPathRooted(textureFilename))
                {
                    textureFilename = Path.Combine(Path.GetDirectoryName(xFile), textureFilename);
                }

                materials.Add(new MeshMaterial()
                {
                    Name          = root.Name + "_material" + i,
                    Alpha         = matd3d.Diffuse.Alpha,
                    Diffuse       = matd3d.Diffuse.ToVector3(),
                    Specular      = matd3d.Specular.ToVector3(),
                    SpecularPower = Math.Max(1, matd3d.Power),
                    Reflectivity  = 0,
                    Refractitity  = 0,
                    EmissiveColor = matd3d.Emissive.ToVector3(),
                    DiffuseMap    = textureFilename
                });
            }


            SkelletalMesh mesh = new SkelletalMesh(vd);

            mesh.Adjacency = adjacency;
            SkinVertex[] vertexes = new SkinVertex[d3dMesh.VertexCount];
            Array        indices;

            if (d3dMesh.IndexBuffer.Description.Format == Format.Index16)
            {
                indices = new ushort[d3dMesh.FaceCount * 3];
            }
            else
            {
                indices = new uint[d3dMesh.FaceCount * 3];
            }

            VertexDescriptor meshVD = new VertexDescriptor(d3dMesh.GetDeclaration());
            int positionOffset      = meshVD.GetOffset(DeclarationUsage.Position, 0);
            int normalOffset        = meshVD.GetOffset(DeclarationUsage.Normal, 0);
            int texCoordOffset      = meshVD.GetOffset(DeclarationUsage.TextureCoordinate, 0);
            int blendIndicesOffset  = meshVD.GetOffset(DeclarationUsage.BlendIndices, 0);
            int blendIndicesSize    = meshVD.SizeOfElement(DeclarationUsage.BlendIndices, 0);
            int blendWeightsOffset  = meshVD.GetOffset(DeclarationUsage.BlendWeight, 0);
            int blendWeightSize     = meshVD.SizeOfElement(DeclarationUsage.BlendWeight, 0);

            byte[] buffer;
            unsafe
            {
                DataStream vertexStream = d3dMesh.LockVertexBuffer(0);
                buffer = new byte[vertexStream.Length];
                vertexStream.Read(buffer, 0, (int)vertexStream.Length);
                fixed(byte *_pter = buffer)
                {
                    fixed(SkinVertex *pVertexes = vertexes)
                    {
                        byte *pter = _pter;
                        int   j    = 0;

                        for (int i = 0; i < d3dMesh.VertexCount; i++)
                        {
                            pVertexes[i].Position = *((Vector3 *)(pter + positionOffset));

                            if (normalOffset >= 0)
                            {
                                pVertexes[i].Normal = *((Vector3 *)(pter + normalOffset));
                            }
                            if (texCoordOffset >= 0)
                            {
                                pVertexes[i].TexCoord = *((Vector2 *)(pter + texCoordOffset));
                            }
                            if (blendIndicesOffset >= 0)
                            {
                                byte *indicesPter = (pter + blendIndicesOffset);
                                uint *pDest       = (uint *)&(pVertexes[i].BlendIndices);
                                for (j = 0; j < blendIndicesSize; j++)
                                {
                                    *(((byte *)pDest) + j) = *(indicesPter + j);
                                }
                            }
                            if (blendWeightsOffset >= 0)
                            {
                                byte *   weightsPter = (pter + blendWeightsOffset);
                                Vector4 *pDest       = &(pVertexes[i].BlendWeights);

                                for (j = 0; j < blendWeightSize; j++)
                                {
                                    *(((byte *)pDest) + j) = *(weightsPter + j);
                                }
                            }

                            pter += d3dMesh.BytesPerVertex;
                        }
                    }
                }

                d3dMesh.UnlockVertexBuffer();

                DataStream indexStream = d3dMesh.LockIndexBuffer(0);
                GCHandle   handler     = GCHandle.Alloc(indices, GCHandleType.Pinned);
                IntPtr     indexPter   = Marshal.UnsafeAddrOfPinnedArrayElement(indices, 0);

                buffer = new byte[indexStream.Length];
                indexStream.Read(buffer, 0, (int)indexStream.Length);
                Marshal.Copy(buffer, 0, indexPter, buffer.Length);

                handler.Free();
                d3dMesh.UnlockIndexBuffer();
            }

            mesh.CreateVertexBuffer(vertexes);
            if (d3dMesh.IndexBuffer.Description.Format == Format.Index16)
            {
                mesh.CreateIndexBuffer((ushort[])indices);
            }
            else
            {
                mesh.CreateIndexBuffer((uint[])indices);
            }

            List <MeshLayer> layers = new List <MeshLayer>();

            if (meshContainer.BoneCombinations == null || meshContainer.BoneCombinations.Length == 0)
            {
                MeshLayer component = new MeshLayer();
                materials.Add(MeshMaterial.CreateDefaultMaterial(meshContainer.Name + "_default"));
                component.materialIndex  = 0;
                component.primitiveCount = mesh.FaceCount;
                component.startIndex     = 0;
                component.startVertex    = 0;
                component.vertexCount    = mesh.VertexCount;
                layers.Add(component);
            }
            else
            {
                for (int i = 0; i < meshContainer.BoneCombinations.Length; i++)
                {
                    BoneCombination comb = meshContainer.BoneCombinations[i];

                    MeshLayer component = new MeshLayer();
                    component.materialIndex  = comb.AttributeId;
                    component.primitiveCount = comb.FaceCount;
                    component.startIndex     = comb.FaceStart * 3;
                    component.startVertex    = comb.VertexStart;
                    component.vertexCount    = comb.VertexCount;

                    layers.Add(component);
                }
            }

            var layerArray = layers.ToArray();

            mesh.Materials = materials.ToArray();
            mesh.SetLayers(layerArray);

            var skinInfo = meshContainer.SkinInfo;

            mesh.MaxVertexInfluences = skinInfo.MaximumVertexInfluences;

            var bones = new Bone[skinInfo.BoneCount];
            var boneOffsetMatrices = new Matrix[bones.Length];

            for (int i = 0; i < bones.Length; i++)
            {
                bones[i] = root.FindChild(skinInfo.GetBoneName(i));
                boneOffsetMatrices[i] = skinInfo.GetBoneOffsetMatrix(i);
            }

            mesh.Bones = bones;
            mesh.BoneBindingMatrices = boneOffsetMatrices;

            if (meshContainer.BoneCombinations != null && meshContainer.BoneCombinations.Length > 0)
            {
                for (int layerIndex = 0; layerIndex < layerArray.Length; layerIndex++)
                {
                    mesh.SetLayerBones(layerIndex, meshContainer.BoneCombinations[layerIndex].BoneIds);
                }
            }

            mesh.LockVertexBuffer();
            int[]   vertices;
            float[] weights;
            for (int i = 0; i < mesh.bones.Length; i++)
            {
                skinInfo.GetBoneInfluence(i, out vertices, out weights);
                VertexStreamView <Vector3> positions = mesh.GetVertexViewStream <Vector3>(DeclarationUsage.Position, 0, vertices);
            }
            mesh.UnlockVertexBuffer();

            meshVD.Dispose();

            if (normalOffset < 0)
            {
                mesh.ComputeNormals();
            }
            if (texCoordOffset < 0)
            {
                mesh.ComputeTextureCoords(CoordMappingType.Spherical);
            }

            mesh.ComputeTangents();

            return(mesh);
        }