예제 #1
0
        /// <summary>
        /// Helper function, returns the element of a source for the given index
        /// </summary>
        /// <param name="doc">The COLLADA document</param>
        /// <param name="input">The "<input>" element we need the index of.</param>
        /// <param name="index"> The index for which we need the value.</param>
        public static float[] GetSourceElement(Document doc, Document.Input input, int index)
        {
            Document.Source src = (Document.Source)input.source;

            // resolve array
            // Note: this will work only if the array is in the current document...
            //       TODO: create a resolver funtion rather than access to doc.dic directly...
            //             enable loading array from binary raw file as well

            object array = doc.dic[src.accessor.source.Fragment];

            if (array is Document.Array <float> )
            {
                Document.Array <float> farray = (Document.Array <float>)(array);
                float[] returnValue           = new float[src.accessor.stride];
                for (int i = 0; i < returnValue.Length; i++)
                {
                    returnValue[i] = farray[src.accessor[i, index]];
                }
                return(returnValue);
            }
            else
            {
                throw new Exception("Unsupported array type");
            }
            // Note: Rarelly int_array could be used for geometry values
        }
예제 #2
0
        /// <summary>
        /// Helper function, returns the element of a source for the given index
        /// </summary>
        /// <param name="doc">The COLLADA document</param>
        /// <param name="input">The "<input>" element we need the index of.</param>
        /// <param name="index"> The index for which we need the value.</param>
        public static float[] GetSourceElement(Document doc, Document.Input input, int index)
        {
            Document.Source src    = (Document.Source)input.source;
            int             stride = src.accessor.stride;
            int             offset = src.accessor.offset;

            // resolve array
            // Note: this will work only if the array is in the current document...
            //       TODO: create a resolver funtion rather than access to doc.dic directly...
            //             enable loading array from binary raw file as well

            object array = doc.dic[src.accessor.source.Fragment];

            if (array is Document.Array <float> )
            {
                Document.Array <float> farray = (Document.Array <float>)(array);

                if (src.accessor.ParameterCount == 1)
                {
                    float[] returnValue = new float[1];
                    returnValue[0] = farray[src.accessor[0, index]];
                    return(returnValue);
                }
                else if (src.accessor.ParameterCount == 2)
                {
                    float[] returnValue = new float[2];
                    returnValue[0] = farray[src.accessor[0, index]];
                    returnValue[1] = farray[offset + index * stride + src.accessor[1]];
                    return(returnValue);
                }
                else if (src.accessor.ParameterCount == 3)
                {
                    float[] returnValue = new float[3];
                    returnValue[0] = farray[src.accessor[0, index]];
                    returnValue[1] = farray[offset + index * stride + src.accessor[1]];
                    returnValue[2] = farray[offset + index * stride + src.accessor[2]];
                    return(returnValue);
                }
                else
                {
                    throw new Exception("Unsupported accessor size");
                }
            }
            else
            {
                throw new Exception("Unsupported array type");
            }
            // Note: Rarelly int_array could be used for geometry values
        }
예제 #3
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()
예제 #4
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
        }