コード例 #1
0
        private static void RunPrimitiveCmd(byte **pIn, byte **pOut, PrimitiveDecodeCommand *pCmd, int cmdCount,
                                            ushort *pIndex, int count)
        {
            int buffer;

            while (count-- > 0)
            {
                for (int i = 0; i < cmdCount; i++)
                {
                    buffer = pCmd[i].Index;
                    switch ((SemanticType)pCmd[i].Cmd)
                    {
                    case SemanticType.None:
                        *pIndex += 1;
                        break;

                    case SemanticType.VERTEX:
                        //Can't do remap table because weights haven't been assigned yet!
                        *(ushort *)pOut[buffer] = *pIndex++;
                        pOut[buffer]           += 2;
                        break;

                    case SemanticType.NORMAL:
                        *(Vector3 *)pOut[buffer] = ((Vector3 *)pIn[buffer])[*pIndex++];
                        pOut[buffer]            += 12;
                        break;

                    case SemanticType.COLOR:
                        float *p  = (float *)(pIn[buffer] + *pIndex++ *16);
                        byte * p2 = pOut[buffer];
                        for (int x = 0; x < 4; x++)
                        {
                            *p2++ = (byte)(*p++ *255.0f + 0.5f);
                        }

                        pOut[buffer] = p2;
                        break;

                    case SemanticType.TEXCOORD:
                        //Flip y axis so coordinates are bottom-up
                        Vector2 v = ((Vector2 *)pIn[buffer])[*pIndex++];
                        v._y = 1.0f - v._y;
                        *(Vector2 *)pOut[buffer] = v;
                        pOut[buffer]            += 8;
                        break;
                    }
                }
            }
        }
コード例 #2
0
        private static PrimitiveManager DecodePrimitives(GeometryEntry geo)
        {
            uint[] pTriarr = null, pLinarr = null;
            uint   pTri = 0, pLin = 0;
            long * pInDataList = stackalloc long[12];
            long * pOutDataList = stackalloc long[12];
            int *  pData = stackalloc int[16];
            int    faces = 0, lines = 0, points = 0;
            uint   fIndex = 0, lIndex = 0, temp;

            PrimitiveDecodeCommand *pCmd = (PrimitiveDecodeCommand *)pData;
            byte **pInData               = (byte **)pInDataList;
            byte **pOutData              = (byte **)pOutDataList;

            PrimitiveManager manager = new PrimitiveManager();

            //Assign vertex source
            foreach (SourceEntry s in geo._sources)
            {
                if (s._id == geo._verticesInput._source)
                {
                    pInData[0] = (byte *)((UnsafeBuffer)s._arrayData).Address;
                    break;
                }
            }

            foreach (PrimitiveEntry prim in geo._primitives)
            {
                //Get face/line count
                if (prim._type == ColladaPrimitiveType.lines || prim._type == ColladaPrimitiveType.linestrips)
                {
                    lines += prim._faceCount;
                }
                else
                {
                    faces += prim._faceCount;
                }

                //Get point total
                points += prim._pointCount;

                //Signal storage buffers and set type offsets
                foreach (InputEntry inp in prim._inputs)
                {
                    int offset = -1;

                    switch (inp._semantic)
                    {
                    case SemanticType.VERTEX:
                        offset = 0;
                        break;

                    case SemanticType.NORMAL:
                        offset = 1;
                        break;

                    case SemanticType.COLOR:
                        if (inp._set < 2)
                        {
                            offset = 2 + inp._set;
                        }

                        break;

                    case SemanticType.TEXCOORD:
                        if (inp._set < 8)
                        {
                            offset = 4 + inp._set;
                        }

                        break;
                    }

                    if (offset != -1)
                    {
                        manager._dirty[offset] = true;
                    }

                    inp._outputOffset = offset;
                }
            }

            manager._pointCount = points;

            //Create primitives
            if (faces > 0)
            {
                manager._triangles = new GLPrimitive(faces * 3, OpenTK.Graphics.OpenGL.PrimitiveType.Triangles);
                pTriarr            = manager._triangles._indices;
            }

            if (lines > 0)
            {
                manager._lines = new GLPrimitive(lines * 2, OpenTK.Graphics.OpenGL.PrimitiveType.Lines);
                pLinarr        = manager._lines._indices;
            }

            manager._indices = new UnsafeBuffer(points * 2);
            //Create face buffers and assign output pointers
            for (int i = 0; i < 12; i++)
            {
                if (manager._dirty[i])
                {
                    int stride;
                    if (i == 0)
                    {
                        stride = 2;
                    }
                    else if (i == 1)
                    {
                        stride = 12;
                    }
                    else if (i < 4)
                    {
                        stride = 4;
                    }
                    else
                    {
                        stride = 8;
                    }

                    manager._faceData[i] = new UnsafeBuffer(points * stride);
                    if (i == 0)
                    {
                        pOutData[i] = (byte *)manager._indices.Address;
                    }
                    else
                    {
                        pOutData[i] = (byte *)manager._faceData[i].Address;
                    }
                }
            }

            //Decode primitives
            foreach (PrimitiveEntry prim in geo._primitives)
            {
                int count = prim._inputs.Count;
                //Map inputs to command sequence
                foreach (InputEntry inp in prim._inputs)
                {
                    if (inp._outputOffset == -1)
                    {
                        pCmd[inp._offset].Cmd = 0;
                    }
                    else
                    {
                        pCmd[inp._offset].Cmd   = (byte)inp._semantic;
                        pCmd[inp._offset].Index = (byte)inp._outputOffset;

                        //Assign input buffer
                        foreach (SourceEntry src in geo._sources)
                        {
                            if (src._id == inp._source)
                            {
                                pInData[inp._outputOffset] = (byte *)((UnsafeBuffer)src._arrayData).Address;
                                break;
                            }
                        }
                    }
                }

                //Decode face data using command list
                foreach (PrimitiveFace f in prim._faces)
                {
                    fixed(ushort *p = f._pointIndices)
                    {
                        RunPrimitiveCmd(pInData, pOutData, pCmd, count, p, f._pointCount);
                    }
                }

                //Process point indices
                switch (prim._type)
                {
                case ColladaPrimitiveType.triangles:
                    count = prim._faceCount * 3;
                    while (count-- > 0)
                    {
                        pTriarr[pTri++] = fIndex++;
                    }

                    break;

                case ColladaPrimitiveType.trifans:
                case ColladaPrimitiveType.polygons:
                case ColladaPrimitiveType.polylist:
                    foreach (PrimitiveFace f in prim._faces)
                    {
                        count   = f._pointCount - 2;
                        temp    = fIndex;
                        fIndex += 2;
                        while (count-- > 0)
                        {
                            pTriarr[pTri++] = temp;
                            pTriarr[pTri++] = fIndex - 1;
                            pTriarr[pTri++] = fIndex++;
                        }
                    }

                    break;

                case ColladaPrimitiveType.tristrips:
                    foreach (PrimitiveFace f in prim._faces)
                    {
                        count   = f._pointCount;
                        fIndex += 2;
                        for (int i = 2; i < count; i++)
                        {
                            if ((i & 1) == 0)
                            {
                                pTriarr[pTri++] = fIndex - 2;
                                pTriarr[pTri++] = fIndex - 1;
                                pTriarr[pTri++] = fIndex++;
                            }
                            else
                            {
                                pTriarr[pTri++] = fIndex - 2;
                                pTriarr[pTri++] = fIndex;
                                pTriarr[pTri++] = fIndex++ - 1;
                            }
                        }
                    }

                    break;

                case ColladaPrimitiveType.linestrips:
                    foreach (PrimitiveFace f in prim._faces)
                    {
                        count = f._pointCount - 1;
                        lIndex++;
                        while (count-- > 0)
                        {
                            pLinarr[pLin++] = lIndex - 1;
                            pLinarr[pLin++] = lIndex++;
                        }
                    }

                    break;

                case ColladaPrimitiveType.lines:
                    foreach (PrimitiveFace f in prim._faces)
                    {
                        count = f._pointCount;
                        while (count-- > 0)
                        {
                            pLinarr[pLin++] = lIndex++;
                        }
                    }

                    break;
                }
            }

            return(manager);
        }