Esempio n. 1
0
 public int[] GetBones(MeshPart layer)
 {
     if (layerBonesLookup != null)
     {
         return(layerBonesLookup[layer.LayerId]);
     }
     return(null);
 }
Esempio n. 2
0
            unsafe private bool AddTriangleBones(MeshPart layer, int iTriangle)
            {
                int *indices = stackalloc int[3];

                indices[0] = GetVertexIndex(layer.startIndex + 3 * iTriangle);
                indices[1] = GetVertexIndex(layer.startIndex + 3 * iTriangle + 1);
                indices[2] = GetVertexIndex(layer.startIndex + 3 * iTriangle + 2);

                if (AddTriangleBones(indices))
                {
                    foreach (var boneIdx in _tempBonesSet)
                    {
                        //add the bone to the layer
                        _boneLookup[boneIdx] = _layerBonesCount++;
                    }

                    //assign new bones indices tp trianglesVertices
                    for (int k = 0; k < 3; k++)
                    {
                        if (!_vertices[indices[k]])
                        {
                            //mark the vertex as processed
                            _vertices[indices[k]] = true;

                            float *pvBones   = GetVertexBones(indices[k]);
                            float *pvWeights = GetVertexWeights(indices[k]);

                            for (int j = 0; j < 4; j++)
                            {
                                if (pvWeights[j] > 0)
                                {
                                    pvBones[j] = _boneLookup[(int)pvBones[j]];
                                }
                            }
                        }
                    }

                    return(true);
                }

                return(false);
            }
Esempio n. 3
0
            void CloseLayer(MeshPart layer)
            {
                layer.IndexCount = layer.PrimitiveCount * 3;

                int vertexCount = 0;
                int startVertex = int.MaxValue;

                for (int i = 0; i < _vertices.Length; i++)
                {
                    if (_vertices[i])
                    {
                        vertexCount++;
                        startVertex = System.Math.Min(startVertex, i);
                    }
                    //reset processed vertex
                    _vertices[i] = false;
                }

                layer.vertexCount = vertexCount;
                layer.startVertex = startVertex;
                int[] invbones = new int[_layerBonesCount];
                for (int i = 0; i < _boneLookup.Length; i++)
                {
                    if (_boneLookup[i] >= 0)
                    {
                        invbones[_boneLookup[i]] = i;
                    }

                    //reset bones
                    _boneLookup[i] = -1;
                }

                _layerBones.Add(invbones);
                _newLayers.Add(layer);
                _layerBonesCount = 0;
            }
Esempio n. 4
0
            public void ReSkin(MeshSkin skin, int maxPalleteEntries)
            {
                _maxPalleteEntries = maxPalleteEntries;
                _mesh            = skin.Mesh;
                _sixteenBits     = _mesh.IndexBuffer.Is16BitsIndices;
                _primitiveStride = 3 * (_sixteenBits ? 2 : 4);
                _vertexStride    = _mesh.VertexDescriptor.Size;
                _indicesOffset   = _mesh.VertexDescriptor.OffsetOf(VertexSemantic.BlendIndices, 0);
                _weightsOffset   = _mesh.VertexDescriptor.OffsetOf(VertexSemantic.BlendWeights, 0);
                _tempBonesSet    = new HashSet <int>();

                _ibDataStream = _mesh.IndexBuffer.Pin();
                _vbNewData    = _mesh.VertexBuffer.ToArray();

                //holds an array of bones indices into the skin bones array, an array of bones for each layer
                _layerBones = new List <int[]>();

                //table containing a mapping betwing a skin bone index and a layer bone index
                _boneLookup = new int[skin._bones.Length];

                //a set of vertices indices into the vertex buffer
                _vertices = new bool[_mesh.VertexCount];

                //list of new layers
                _newLayers = new List <MeshPart>(_mesh.Layers.Length);

                //reset the bones mapping
                for (int i = 0; i < _boneLookup.Length; i++)
                {
                    _boneLookup[i] = -1;
                }

                //reset the vertex set
                Array.Clear(_vertices, 0, _vertices.Length);

                //current processing layer
                MeshPart newLayer = null;

                GCHandle pinH = GCHandle.Alloc(_vbNewData, GCHandleType.Pinned);

                _pVbDAta = (byte *)Marshal.UnsafeAddrOfPinnedArrayElement(_vbNewData, 0);

                //get  a  pointer to the indexbuffer stream
                _pIbData = (byte *)_ibDataStream.ToPointer();
                for (int matIdx = 0; matIdx < _mesh.MaterialSlots; matIdx++)
                {
                    //for each material get the corresponding layers
                    var layers = _mesh.GetLayersByMaterial(matIdx);

                    //create the first layer for matIdx
                    newLayer = new MeshPart();
                    newLayer.materialIndex = matIdx;
                    newLayer.startIndex    = layers[0].startIndex;

                    int primitiveCount = 0;

                    foreach (var layer in layers)
                    {
                        //loop through add to the layer as much bones as maxPalleteEntries
                        //newLayer.startIndex = Math.Min(newLayer.startIndex, layer.startIndex);
                        for (int itriangle = 0; itriangle < layer.primitiveCount; itriangle++)
                        {
                            primitiveCount++;
                            //check if the triangle can be added to the newLayer
                            if (!AddTriangleBones(layer, itriangle))
                            {
                                //the layer is full, close it and open a new layer
                                newLayer.primitiveCount = primitiveCount - 1;
                                CloseLayer(newLayer);

                                //start a new Layer
                                newLayer = new MeshPart();
                                newLayer.materialIndex = matIdx;
                                newLayer.startIndex    = layer.startIndex + 3 * itriangle;

                                //add the triangle to the newlayer
                                AddTriangleBones(layer, itriangle);
                                primitiveCount = 1;
                            }
                        }
                    }

                    newLayer.primitiveCount = primitiveCount;
                    CloseLayer(newLayer);
                }

                _mesh.Layers = _newLayers.ToArray();
                for (int i = 0; i < _layerBones.Count; i++)
                {
                    skin.SetBones(i, _layerBones[i]);
                }

                pinH.Free();


                _mesh.IndexBuffer.UnPin();
                _mesh.VertexBuffer.UnPin();

                _mesh.VertexBuffer.SetData(_vbNewData);
            }
Esempio n. 5
0
        public unsafe void BlendLayers()
        {
            Dictionary <int, List <MeshPart> > materialList = new Dictionary <int, List <MeshPart> >(_materialLayersLookup.Length);

            for (int i = 0; i < _materialLayersLookup.Length; i++)
            {
                materialList.Add(i, new List <MeshPart>(_materialLayersLookup[i]));
            }

            List <MeshPart> newLayers = new List <MeshPart>();

            var ds = _ib.Pin();

            byte *pIndices = (byte *)ds;

            byte[] newIndices = new byte[_ib.Length];

            fixed(byte *pNewIndices = newIndices)
            {
                int iIndex = 0;
                Dictionary <uint, bool> vertexLookup = new Dictionary <uint, bool>();

                foreach (var v in materialList)
                {
                    vertexLookup.Clear();

                    MeshPart newLayer = new MeshPart();
                    if (newLayer == null)
                    {
                        _ib.UnPin();
                        return;
                    }
                    newLayers.Add(newLayer);
                    newLayer.materialIndex = v.Key;
                    newLayer.startIndex    = iIndex;
                    newLayer.startVertex   = int.MaxValue;

                    foreach (var layer in v.Value)
                    {
                        newLayer.primitiveCount += layer.primitiveCount;
                        newLayer.startVertex     = System.Math.Min(newLayer.startVertex, layer.startVertex);

                        int indicesCount = layer.primitiveCount * 3;
                        for (int i = layer.startIndex; i < layer.startIndex + indicesCount; i++)
                        {
                            uint vertexIndex;
                            if (_ib.Is16BitsIndices)
                            {
                                vertexIndex = ((ushort *)pIndices)[i];
                                ((ushort *)pNewIndices)[iIndex] = ((ushort *)pIndices)[i];
                            }
                            else
                            {
                                vertexIndex = ((uint *)pIndices)[i];
                                ((uint *)pNewIndices)[iIndex] = ((uint *)pIndices)[i];
                            }
                            iIndex++;
                            vertexLookup[vertexIndex] = true;
                        }
                    }
                    newLayer.vertexCount = vertexLookup.Keys.Count;
                    newLayer.indexCount  = newLayer.primitiveCount * 3;
                    materialList[v.Key].Clear();
                    materialList[v.Key].Add(newLayer);
                }

                Layers = newLayers.ToArray();

                _ib.UnPin();
                _ib.SetData(newIndices);
            }
        }