Пример #1
0
        /// <summary>This method will create a single index for the primitives
        /// This will not work on polygons and polylist, since vcount is not taken in count there
        /// So you need to first run ConvexTriangulator (or equivalent)
        /// <para>This will make it directly usable as a index vertexArray for drawing</para>
        /// </summary>
        static public void Reindexor(Document doc)
        {
            String[] channelFlags =
            {
                "POSITION",
                "NORMAL",
                "TEXCOORD",
                "COLOR",
                "TANGENT",
                "BINORMAL",
                "UV",
                "TEXBINORMAL",
                "TEXTANGENT"
            };

            Dictionary <string, int> channelCount              = new Dictionary <string, int>();
            Dictionary <string, int> maxChannelCount           = new Dictionary <string, int>();
            Dictionary <string, List <Document.Input> > inputs = new Dictionary <string, List <Document.Input> >();;



            foreach (Document.Geometry geo in doc.geometries)
            {
                // Skip geometry if there are no primitives defined
                if (geo.mesh.primitives.Count == 0)
                {
                    continue;
                }

                foreach (string i in channelFlags)
                {
                    maxChannelCount[i] = 0;
                }

                // Check if all parts have the same vertex definition
                bool first = true;
                foreach (Document.Primitive primitive in geo.mesh.primitives)
                {
                    foreach (string i in channelFlags)
                    {
                        channelCount[i] = 0;
                    }

                    foreach (Document.Input input in COLLADAUtil.GetAllInputs(primitive))
                    {
                        channelCount[input.semantic]++;
                    }
                    if (first)
                    {
                        foreach (string i in channelFlags)
                        {
                            if (maxChannelCount[i] < channelCount[i])
                            {
                                maxChannelCount[i] = channelCount[i];
                            }
                        }
                        first = false;
                    }
                    else
                    {
                        foreach (string i in channelFlags)
                        {
                            if (maxChannelCount[i] != channelCount[i])
                            {
                                throw new Exception("TODO:  mesh parts have different vertex buffer definition in geometry " + geo.id);
                            }
                        }
                    }
                }

                // create new float array and index
                List <List <int> >       indexList = new List <List <int> >();
                List <int>               indexes;
                List <float>             farray     = new List <float>();
                Dictionary <string, int> checkIndex = new Dictionary <string, int>();
                int index = 0;

                foreach (Document.Primitive primitive in geo.mesh.primitives)
                {
                    foreach (string i in channelFlags)
                    {
                        inputs[i] = new List <Document.Input>();
                    }

                    foreach (Document.Input input in COLLADAUtil.GetAllInputs(primitive))
                    {
                        inputs[input.semantic].Add(input);
                    }

                    indexes = new List <int>();
                    indexList.Add(indexes);

                    int          k = 0;
                    string       indexKey;
                    List <float> tmpValues;
                    try
                    {
                        while (true)
                        {
                            indexKey  = "";
                            tmpValues = new List <float>();
                            foreach (string i in channelFlags)
                            {
                                foreach (Document.Input input in inputs[i])
                                {
                                    int j = COLLADAUtil.GetPValue(input, primitive, k);
                                    indexKey += j.ToString() + ",";
                                    float[] values = COLLADAUtil.GetSourceElement(doc, input, j);
                                    for (int l = 0; l < values.Length; l++)
                                    {
                                        tmpValues.Add(values[l]);
                                    }
                                }
                            }
                            k++;
                            if (checkIndex.ContainsKey(indexKey))
                            {
                                indexes.Add(checkIndex[indexKey]);
                            }
                            else
                            {
                                indexes.Add(index);
                                checkIndex[indexKey] = index++;
                                foreach (float f in tmpValues)
                                {
                                    farray.Add(f);
                                }
                            }
                        }
                    }
                    catch { } // catch for index out of range.
                }
                // remove old sources and array
                foreach (Document.Source source in geo.mesh.sources)
                {
                    if (source.array != null)
                    {
                        doc.dic.Remove(((Document.Array <float>)source.array).id);
                    }
                    doc.dic.Remove(source.id);
                }

                // create all the new source
                int stride = 0;
                foreach (Document.Source source in geo.mesh.sources)
                {
                    stride += source.accessor.stride;
                }

                List <Document.Source> newSources = new List <Document.Source>();
                Document.Source        newSource;
                Document.Accessor      newAccessor;
                Document.Array <float> newArray;
                int    offset     = 0;
                string positionId = ((Document.Source)inputs["POSITION"][0].source).id;
                foreach (Document.Source source in geo.mesh.sources)
                {
                    newAccessor = new Document.Accessor(doc, farray.Count / stride, offset, stride, "#" + geo.id + "-vertexArray", source.accessor.parameters);
                    offset     += source.accessor.stride;
                    if (source.id == positionId)
                    {
                        newArray = new Document.Array <float>(doc, geo.id + "-vertexArray", farray.ToArray());
                    }
                    else
                    {
                        newArray = null;
                    }
                    newSource = new Document.Source(doc, source.id, newArray, newAccessor);
                    newSources.Add(newSource);
                }

                // Create the new vertices
                List <Document.Input> newInputs = new List <Document.Input>();
                Document.Input        newInput;
                foreach (string i in channelFlags)
                {
                    foreach (Document.Input input in inputs[i])
                    {
                        // no offset, all inputs share the same index
                        newInput = new Document.Input(doc, 0, input.semantic, input.set, ((Document.Source)input.source).id);
                        newInputs.Add(newInput);
                    }
                }
                Document.Vertices newVertices = new Document.Vertices(doc, geo.mesh.vertices.id, newInputs);

                // now create the new primitives
                List <Document.Primitive> newPrimitives = new List <Document.Primitive>();
                Document.Primitive        newPrimitive;

                index  = 0;
                offset = 0;
                foreach (Document.Primitive primitive in geo.mesh.primitives)
                {
                    newInputs = new List <Document.Input>();
                    newInput  = new Document.Input(doc, 0, "VERTEX", -1, geo.mesh.vertices.id);
                    newInputs.Add(newInput);

                    if (primitive is Document.Triangle)
                    {
                        newPrimitive = new Document.Triangle(doc, primitive.count, newInputs, indexList[index].ToArray());
                    }
                    else if (primitive is Document.Line)
                    {
                        newPrimitive = new Document.Line(doc, primitive.count, newInputs, indexList[index].ToArray());
                    }
                    else
                    {
                        throw new Exception("TODO: need to take care of " + primitive.GetType().ToString());
                    }
                    newPrimitive.material = primitive.material;
                    newPrimitive.extras   = primitive.extras;
                    newPrimitive.name     = primitive.name;
                    newPrimitives.Add(newPrimitive);

                    index++;
                }

                // change the primitive to use the new array and indexes.

                // 1) - remove the old sources, vertices and primitives

                geo.mesh.sources.Clear();
                geo.mesh.vertices.inputs.Clear();
                geo.mesh.primitives.Clear();

                // 2) - Add all the sources, only the POSITION will have the values

                geo.mesh.sources    = newSources;
                geo.mesh.primitives = newPrimitives;
                geo.mesh.vertices   = newVertices;
            } // foreach geometry
        }     // Reindexor()
Пример #2
0
        /// <summary>This method will create a single index for the primitives
        /// This will not work on polygons and polylist, since vcount is not taken in count there
        /// So you need to first run ConvexTriangulator (or equivalent) 
        /// <para>This will make it directly usable as a index vertexArray for drawing</para>
        /// </summary>
        public static void Reindexor(Document doc)
        {
            String[] channelFlags =
            {
                "POSITION",
                "NORMAL",
                "TEXCOORD",
                "COLOR",
                "TANGENT",
                "BINORMAL",
                "UV",
                "TEXBINORMAL",
                "TEXTANGENT"
            };

            Dictionary<string,int> channelCount = new Dictionary<string,int>();
            Dictionary<string, int> maxChannelCount = new Dictionary<string, int>();
            Dictionary<string, List<Document.Input>> inputs = new Dictionary<string, List<Document.Input>>(); ;

            foreach (Document.Geometry geo in doc.geometries)
            {
                // Skip geometry if there are no primitives defined
                if (geo.mesh.primitives.Count == 0)
                    continue;

                foreach (string i in channelFlags)
                    maxChannelCount[i] = 0;

                // Check if all parts have the same vertex definition
                bool first=true;
                foreach (Document.Primitive primitive in geo.mesh.primitives)
                {
                    foreach (string i in channelFlags)
                        channelCount[i] = 0;

                    foreach (Document.Input input in COLLADAUtil.GetAllInputs(primitive))
                    {
                        channelCount[input.semantic]++;
                    }
                    if (first)
                    {
                        foreach (string i in channelFlags)
                            if (maxChannelCount[i] < channelCount[i]) maxChannelCount[i] = channelCount[i];
                        first = false;
                    }
                     else
                    {
                        foreach (string i in channelFlags)
                            if (maxChannelCount[i] != channelCount[i])
                                throw new Exception("TODO:  mesh parts have different vertex buffer definition in geometry " + geo.id);
                    }
                }

                // create new float array and index
                List<List<int>> indexList = new List<List<int>>();
                List<int> indexes;
                List<float> farray = new List<float>();
                Dictionary<string,int> checkIndex = new Dictionary<string,int>();
                int index=0;

                foreach (Document.Primitive primitive in geo.mesh.primitives)
                {
                    foreach (string i in channelFlags)
                        inputs[i] = new List<Document.Input>();

                    foreach (Document.Input input in COLLADAUtil.GetAllInputs(primitive))
                        inputs[input.semantic].Add(input);

                    indexes = new List<int>();
                    indexList.Add(indexes);

                    int k=0;
                    string indexKey;
                    List<float> tmpValues;
                    try
                    {
                        while (true)
                        {
                            indexKey = "";
                            tmpValues = new List<float>();
                            foreach (string i in channelFlags)
                                foreach (Document.Input input in inputs[i])
                                {
                                    int j = COLLADAUtil.GetPValue(input, primitive, k);
                                    indexKey += j.ToString() + ",";
                                    float[] values = COLLADAUtil.GetSourceElement(doc,input, j);
                                    for (int l = 0; l < values.Length; l++) tmpValues.Add(values[l]);
                                }
                            k++;
                            if (checkIndex.ContainsKey(indexKey))
                                indexes.Add(checkIndex[indexKey]);
                            else
                            {
                                indexes.Add(index);
                                checkIndex[indexKey] = index++;
                                foreach (float f in tmpValues) farray.Add(f);
                            }
                        }
                    }
                    catch { } // catch for index out of range.
                }
                // remove old sources and array
                foreach (Document.Source source in geo.mesh.sources)
                {
                    if (source.array != null)
                        doc.dic.Remove(((Document.Array<float>)source.array).id);
                    doc.dic.Remove(source.id);
                }

                // create all the new source
                int stride = 0;
                foreach (Document.Source source in geo.mesh.sources)
                {
                    stride += source.accessor.stride;
                }

                List<Document.Source> newSources = new List<Document.Source>();
                Document.Source newSource;
                Document.Accessor newAccessor;
                Document.Array<float> newArray;
                int offset = 0;
                string positionId = ((Document.Source)inputs["POSITION"][0].source).id;
                foreach (Document.Source source in geo.mesh.sources)
                {
                    newAccessor = new Document.Accessor(doc, farray.Count / stride, offset, stride, "#"+geo.id + "-vertexArray", source.accessor.parameters);
                    offset += source.accessor.stride;
                    if (source.id == positionId)
                    {
                        newArray = new Document.Array<float>(doc, geo.id + "-vertexArray", farray.ToArray());
                    }
                    else
                    {
                        newArray = null;
                    }
                    newSource = new Document.Source(doc, source.id, newArray, newAccessor);
                    newSources.Add(newSource);
                }

                // Create the new vertices
                List<Document.Input> newInputs = new List<Document.Input>();
                Document.Input newInput;
                foreach (string i in channelFlags)
                {
                    foreach (Document.Input input in inputs[i])
                    {
                        // no offset, all inputs share the same index
                        newInput = new Document.Input(doc, 0, input.semantic, input.set, ((Document.Source)input.source).id);
                        newInputs.Add(newInput);
                    }
                }
                Document.Vertices newVertices = new Document.Vertices(doc, geo.mesh.vertices.id, newInputs);

                // now create the new primitives
                List<Document.Primitive> newPrimitives = new List<Document.Primitive>();
                Document.Primitive newPrimitive;

                index = 0;
                offset = 0;
                foreach (Document.Primitive primitive in geo.mesh.primitives)
                {

                    newInputs = new List<Document.Input>();
                    newInput = new Document.Input(doc, 0, "VERTEX", -1, geo.mesh.vertices.id);
                    newInputs.Add(newInput);

                    if (primitive is Document.Triangle)
                        newPrimitive = new Document.Triangle(doc, primitive.count, newInputs, indexList[index].ToArray());
                    else if (primitive is Document.Line)
                        newPrimitive = new Document.Line(doc, primitive.count, newInputs, indexList[index].ToArray());
                    else
                        throw new Exception("TODO: need to take care of " + primitive.GetType().ToString());
                    newPrimitive.material = primitive.material;
                    newPrimitive.extras = primitive.extras;
                    newPrimitive.name = primitive.name;
                    newPrimitives.Add(newPrimitive);

                    index++;
                }

                // change the primitive to use the new array and indexes.

                // 1) - remove the old sources, vertices and primitives

                geo.mesh.sources.Clear();
                geo.mesh.vertices.inputs.Clear();
                geo.mesh.primitives.Clear();

                // 2) - Add all the sources, only the POSITION will have the values

                geo.mesh.sources = newSources;
                geo.mesh.primitives = newPrimitives;
                geo.mesh.vertices = newVertices;

            } // foreach geometry
        }