예제 #1
0
        public int RebuildBVH(BVHHandle bvhHandle)
        {
            // build baker context
            m_baker.m_sourcePaths   = new string[] { AssetDatabase.GetAssetPath(bvhHandle.SourceMeshData.sharedMesh) };
            m_baker.m_guids         = new string[] { "" + m_baker.m_meshes[0].GetUniqueId() };
            m_baker.m_meshRenderers = new MeshRenderer[] { bvhHandle.SourceMeshData.GetComponent <MeshRenderer>() };

            // parse data and fill in missing context
            BakeContext.BuildSceneContext(new MeshFilter[] { bvhHandle.SourceMeshData }, m_baker);

#if DDR_RUNTIME_DLL_LINKING_
            int err = Invoke <int, _RebuildBVH>(bvhHandle.Ptr(), m_baker.m_meshIdsPtr, m_baker.m_vertexCountsPtr, m_baker.m_triangleCountPtr
                                                , m_baker.m_matDataPtr, m_baker.m_meshDataPtr, m_baker.m_triangleDataPtr, m_baker.m_bakeOptionsPtr, 1, m_baker.m_guids, m_baker.m_sourcePaths);
#else
            int err = _RebuildBVH(bvhHandle.Ptr(), m_baker.m_meshIdsPtr, m_baker.m_vertexCountsPtr, m_baker.m_triangleCountPtr
                                  , m_baker.m_matDataPtr, m_baker.m_meshDataPtr, m_baker.m_triangleDataPtr, m_baker.m_bakeOptionsPtr, 1, m_baker.m_guids, m_baker.m_sourcePaths);
#endif

            m_baker.FreeContext();

            if (err != 0)
            {
                string error = GetLastError();
                VertexBakerLib.LogError(error);
            }

            return(err);
        }
예제 #2
0
        public int TessellateTriangles(BVHHandle bvhHandle, Vector3 startPoint, Vector3 endPoint)
        {
            m_baker.m_sourcePaths   = new string[] { AssetDatabase.GetAssetPath(bvhHandle.SourceMeshData.sharedMesh) };
            m_baker.m_guids         = new string[] { "" + m_baker.m_meshes[0].GetUniqueId() };
            m_baker.m_meshRenderers = new MeshRenderer[] { bvhHandle.SourceMeshData.GetComponent <MeshRenderer>() };
            List <MeshFilter> meshes = new List <MeshFilter>()
            {
                bvhHandle.SourceMeshData
            };

            m_baker.InitBakeContext(meshes, null);
            BakeContext.IVertex vertexFormat = new BakeContext.DefaultVertex();
            BakeContext.BuildSceneContext(m_baker.m_meshes.ToArray(), m_baker, vertexFormat);

            int[] outIndex = new int[1];
            outIndex[0] = -1;
#if DDR_RUNTIME_DLL_LINKING_
            bool success = Invoke <bool, _TessellateTriangles>(bvhHandle.Ptr()
                                                               , m_baker.m_meshIdsPtr
                                                               , m_baker.m_vertexCountsPtr
                                                               , m_baker.m_triangleCountPtr
                                                               , vertexFormat.ElementCount
                                                               , vertexFormat.Definition.ToArray()
                                                               , m_baker.m_matDataPtr
                                                               , m_baker.m_meshDataPtr
                                                               , m_baker.m_triangleDataPtr
                                                               , m_baker.m_bakeOptionsPtr
                                                               , m_baker.m_guids
                                                               , m_baker.m_sourcePaths
                                                               , m_baker.m_settingsPtrs);
            #else
            bool success = _TessellateTriangles(bvhHandle.Ptr()
                                                , m_baker.m_meshIdsPtr
                                                , m_baker.m_vertexCountsPtr
                                                , m_baker.m_triangleCountPtr
                                                , vertexFormat.ElementCount
                                                , vertexFormat.Definition.ToArray()
                                                , m_baker.m_matDataPtr
                                                , m_baker.m_meshDataPtr
                                                , m_baker.m_triangleDataPtr
                                                , m_baker.m_bakeOptionsPtr
                                                , m_baker.m_guids
                                                , m_baker.m_sourcePaths
                                                , m_baker.m_settingsPtrs);
            #endif
            if (!success)
            {
                string error = GetLastError();
                VertexBakerLib.LogError(error);
            }

            return(outIndex[0]);
        }
예제 #3
0
        public string BuildBVH(MeshFilter[] meshes, ref BVHHandle[] bvhHandles)
        {
            m_baker.m_guids         = new string[meshes.Length];
            m_baker.m_sourcePaths   = new string[meshes.Length];
            m_baker.m_meshRenderers = new MeshRenderer[meshes.Length];
            for (int i = 0; i < meshes.Length; ++i)
            {
                m_baker.m_sourcePaths[i]   = AssetDatabase.GetAssetPath(meshes[i].sharedMesh);
                m_baker.m_guids[i]         = "" + meshes[i].GetUniqueId();
                m_baker.m_meshRenderers[i] = meshes[i].GetComponent <MeshRenderer>();
            }
            m_baker.m_meshCount = meshes.Length;

            BakeContext.BuildSceneContext(meshes, m_baker);

            IntPtr[] handles = new IntPtr[meshes.Length];
            for (int i = 0; i < handles.Length; ++i)
            {
                handles[i] = IntPtr.Zero;
            }
#if DDR_RUNTIME_DLL_LINKING_
            string msg = Marshal.PtrToStringAnsi(Invoke <IntPtr, _BuildBVH>(m_baker.m_meshIdsPtr, m_baker.m_vertexCountsPtr, m_baker.m_triangleCountPtr, m_baker.m_matDataPtr
                                                                            , m_baker.m_meshDataPtr, m_baker.m_triangleDataPtr, m_baker.m_bakeOptionsPtr, m_baker.m_meshCount
                                                                            , m_baker.m_guids, m_baker.m_sourcePaths, m_baker.m_settingsIndicesPtr, m_baker.m_settingsPtrs, handles));
#else
            string msg = Marshal.PtrToStringAnsi(_BuildBVH(m_baker.m_meshIdsPtr, m_baker.m_vertexCountsPtr, m_baker.m_triangleCountPtr, m_baker.m_matDataPtr
                                                           , m_baker.m_meshDataPtr, m_baker.m_triangleDataPtr, m_baker.m_bakeOptionsPtr, m_baker.m_meshCount
                                                           , m_baker.m_guids, m_baker.m_sourcePaths, m_baker.m_settingsIndicesPtr, m_baker.m_settingsPtrs, handles));
#endif
            m_baker.FreeContext();

            // output specialized handle
            bvhHandles = new BVHHandle[handles.Length];
            for (int i = 0; i < handles.Length; ++i)
            {
                bvhHandles[i] = new BVHHandle(meshes[i], handles[i], this);
            }

            return(msg);
        }
        // Prepare sub-mesh data in a flexible way based on vertex definition
        static void BuildMesh(BakeContext ctx, Mesh mesh, IVertex vertex, List <int> optSubMeshIndices, ref int ptrOffset)
        {
            int vertexCount = optSubMeshIndices == null ? mesh.vertices.Length : optSubMeshIndices.Count;

            var vertElementIter = vertex.Definition.GetEnumerator();

            while (vertElementIter.MoveNext())
            {
                VertexElementType elType = vertElementIter.Current.GetElType;
                VertexElement     elDef  = vertElementIter.Current;
                int componentCount       = elDef.ComponentCount;

                // pointer to new data
                IntPtr dataPtr = new IntPtr(ctx.m_meshDataPtr.ToInt64() + ptrOffset * SIZE_FLOAT);

                if (elType == VertexElementType.kTangent && mesh.tangents.Length == 0)
                {
                    // If the data type is kTangent and there is not tangent data, copy UV0 data into the first half of the tangent
                    // data buffer, leave the second half empty. The UV0 data will be used by the baker to generate the tangent data, which
                    // will then be re-written into the tangent buffer.
                    VertexElement uvElement = new VertexElement(VertexElementType.kUV0, 2, SIZE_FLOAT);
                    CopyVectorArrayFromMesh(dataPtr, vertexCount * uvElement.TotalByteSize, vertexCount * uvElement.TotalByteSize, mesh, uvElement);
                }
                else if (elType == VertexElementType.kNormal && mesh.normals.Length == 0)
                {
                    // Do Nothing!
                    // If the data type is kNormal and there is no data skip this step but still increment pointer to leave a 'hole' in the buffer
                    // that he baker can fill with dynamically generated normals. This statement is just here for reader clarity.
                }
                else
                {
                    // if here just copy data of the element size into the dataPtr (the buffer)
                    CopyVectorArrayFromMesh(dataPtr, vertexCount * elDef.TotalByteSize, vertexCount * elDef.TotalByteSize, mesh, elDef, optSubMeshIndices);
                }

                // regardless of which 'if-statement' we fall, in always increment the pointer by the full amount
                ptrOffset += vertexCount * componentCount;
            }
        }
        // Helper method for marshaling mesh data with sub mesh definition
        public static void BuildSceneContext(MeshFilter[] meshes, List <List <int> > subMeshIndices, List <List <int> > subMeshTriangleIndices, BakeContext ctx, IVertex vertex = null)
        {
            if (vertex == null)
            {
                vertex = new DefaultVertex();
            }

            ctx.m_vertexEementCount = vertex.ElementCount;
            ctx.m_vertexDefinition  = vertex.Definition.ToArray();

            int totalVertCount = 0;
            int totalTriCount  = 0;
            int meshCount      = meshes.Length;

            // extract mesh renderer options
            MeshRenderer[] renderer = ctx.m_meshRenderers;

            // calculate mesh data size
            for (int i = 0; i < meshCount; ++i)
            {
                // if a sub mesh is defined use it for vert count
                if (subMeshIndices != null && subMeshIndices[i] != null)
                {
                    totalVertCount += subMeshIndices[i].Count;
                }
                else
                {
                    totalVertCount += meshes[i].sharedMesh.vertices.Length;
                }

                // if a sub mesh is defined use it for triangle index count
                if (subMeshTriangleIndices != null && subMeshTriangleIndices[i] != null)
                {
                    totalTriCount += subMeshTriangleIndices[i].Count;
                }
                else
                {
                    totalTriCount += meshes[i].sharedMesh.triangles.Length;
                }
            }

            // data size
            const int triangleSize = 3;
            const int matSize      = 16;

            int totalMatrixDataSize = matSize * meshCount * SIZE_FLOAT;
            // mesh size depends on vertex definition
            int totalMeshDataSize     = totalVertCount * SIZE_FLOAT * (vertex.VertexSize + meshCount);
            int totalTriangleDataSize = totalTriCount * triangleSize * SIZE_INT;

            VertexBakerLib instance = VertexBakerLib.Instance;

            ctx.m_meshIdsPtr         = instance.Alloc(meshCount * SIZE_INT);
            ctx.m_vertexCountsPtr    = instance.Alloc(meshCount * SIZE_INT);
            ctx.m_triangleCountPtr   = instance.Alloc(meshCount * SIZE_INT);
            ctx.m_matDataPtr         = instance.Alloc(totalMatrixDataSize);
            ctx.m_meshDataPtr        = instance.Alloc(totalMeshDataSize);
            ctx.m_triangleDataPtr    = instance.Alloc(totalTriangleDataSize);
            ctx.m_settingsIndicesPtr = instance.Alloc(meshCount * SIZE_INT);
            ctx.m_bakeOptionsPtr     = instance.Alloc(meshCount * SIZE_INT);
            ctx.m_layerPtr           = instance.Alloc(meshCount * SIZE_INT);

            // temp buffer for matrix
            float[] matArr = new float[16];

            int matDestOffset      = 0;
            int meshDestOffset     = 0;
            int triangleDestOffset = 0;

            int[]  vertexCounts   = new int[meshCount];
            int[]  triangleCounts = new int[meshCount];
            int[]  ids            = new int[meshCount];
            uint[] perMeshBakeOpt = new uint[meshCount];
            uint[] layerMask      = new uint[meshCount];

            // data for settings
            int[]         settingsIdx  = new int[meshCount];
            List <IntPtr> settingsList = new List <IntPtr>();

            // global settings
            int    globalSettingsIdx = 0;
            IntPtr globalSettings    = SettingsToIntPtr(BakeData.Instance().GetBakeSettings().SelectedBakeSet);

            settingsList.Add(globalSettings);

            for (int m = 0; m < meshCount; ++m)
            {
                bool processSubMesh = false;

                // assume sub mesh
                if (subMeshIndices != null && subMeshIndices[m] != null &&
                    subMeshTriangleIndices != null && subMeshTriangleIndices[m] != null)
                {
                    processSubMesh = true;
                }
                // setup settings
                settingsIdx[m] = globalSettingsIdx;
                // check for override settings
                VertexLightingOverride ovrdSettings = meshes[m].GetComponent <VertexLightingOverride>();
                if (ovrdSettings != null)
                {
                    // point at this overrides index
                    settingsIdx[m] = settingsList.Count;
                    // ensure ambient settings (copy from global which contains the valid ambient settings for now)
                    ovrdSettings.m_bakeSettingsOverride.CopyAmbient(BakeData.Instance().GetBakeSettings().SelectedBakeSet);
                    IntPtr settingsPtr = SettingsToIntPtr(ovrdSettings.m_bakeSettingsOverride);
                    settingsList.Add(settingsPtr);
                }

                Mesh mesh = meshes[m].sharedMesh;
                ids[m] = meshes[m].GetUniqueId();

                // layer mask
                layerMask[m] = (uint)(1 << meshes[m].gameObject.layer);

                // clear data
                perMeshBakeOpt[m] = 0;

                // if mesh has no normals or tangents flag them for generation
                // should calculate normals
                if (meshes[m].sharedMesh.normals.Length == 0)
                {
                    // set bit for normals
                    perMeshBakeOpt[m] |= BakeOptions.kCalcNormals;
                }
                // should calculate tangents
                if (meshes[m].sharedMesh.tangents.Length == 0)
                {
                    // set bit for tangents
                    perMeshBakeOpt[m] |= BakeOptions.kCalcTangents;
                }

                // extract shadowing options from renderer
                switch (renderer[m].shadowCastingMode)
                {
                case UnityEngine.Rendering.ShadowCastingMode.Off:
                {
                    perMeshBakeOpt[m] |= BakeOptions.kShadowsOff;
                }
                break;

                case UnityEngine.Rendering.ShadowCastingMode.TwoSided:
                {
                    perMeshBakeOpt[m] |= BakeOptions.kTwoSided;
                }
                break;

                case UnityEngine.Rendering.ShadowCastingMode.On:
                {
                    perMeshBakeOpt[m] |= BakeOptions.kShadowsOn;
                }
                break;

                case UnityEngine.Rendering.ShadowCastingMode.ShadowsOnly:
                {
                    perMeshBakeOpt[m] |= BakeOptions.kShadowsOnly;
                }
                break;

                default:
                    break;
                }

                if (renderer[m].receiveShadows)
                {
                    perMeshBakeOpt[m] |= BakeOptions.kReceiveShadow;
                }
                else
                {
                    perMeshBakeOpt[m] &= ~BakeOptions.kReceiveShadow;
                }

                // use the list of unique indices of the sub mesh to find the count here unless its null then assume all vertices are being processed
                int vertexCount = processSubMesh ? subMeshIndices[m].Count : mesh.vertices.Length;

                // use the list of triangles from the sub mesh to find the count here unless its null then assume all triangles are being processed
                int triangleCount = processSubMesh ? subMeshTriangleIndices[m].Count : mesh.triangles.Length;

                vertexCounts[m]   = vertexCount;
                triangleCounts[m] = triangleCount;

                // copy mesh data into mesh buffer starting with world matrix
                int matIndex = 0;
                AssignMat4(ref matArr, meshes[m].transform.localToWorldMatrix, ref matIndex); // 64 bytes

                IntPtr matDestPtr = new IntPtr(ctx.m_matDataPtr.ToInt64() + matDestOffset * SIZE_FLOAT);
                Marshal.Copy(matArr, 0, matDestPtr, 16);
                matDestOffset += 16;

                if (processSubMesh)
                {
                    // build sub mesh
                    BuildMesh(ctx, meshes[m].sharedMesh, vertex, subMeshIndices[m], ref meshDestOffset);
                }
                else
                {
                    // build entire mesh
                    BuildMesh(ctx, meshes[m].sharedMesh, vertex, ref meshDestOffset);
                }

                // triangles
                IntPtr indexPtr = new IntPtr(ctx.m_triangleDataPtr.ToInt64() + triangleDestOffset * SIZE_INT);
                if (processSubMesh)
                {
                    // copy sub mesh triangle list
                    Marshal.Copy(subMeshTriangleIndices[m].ToArray(), 0, indexPtr, triangleCount);
                }
                else
                {
                    // copy entire triangle list
                    Marshal.Copy(mesh.triangles, 0, indexPtr, triangleCount);
                }

                triangleDestOffset += triangleCount;
            }

            // copy the mesh into pointer
            instance.CopyArray(ctx.m_meshIdsPtr, meshCount * SIZE_INT, ids, meshCount * SIZE_INT);
            instance.CopyArray(ctx.m_vertexCountsPtr, meshCount * SIZE_INT, vertexCounts, meshCount * SIZE_INT);
            instance.CopyArray(ctx.m_triangleCountPtr, meshCount * SIZE_INT, triangleCounts, meshCount * SIZE_INT);
            instance.CopyUIntArray(ctx.m_bakeOptionsPtr, meshCount * SIZE_INT, perMeshBakeOpt, meshCount * SIZE_INT);
            instance.CopyUIntArray(ctx.m_layerPtr, meshCount * SIZE_INT, layerMask, meshCount * SIZE_INT);
            instance.CopyArray(ctx.m_settingsIndicesPtr, meshCount * SIZE_INT, settingsIdx, meshCount * SIZE_INT);

            ctx.m_settingsPtrs = settingsList.ToArray();
            ctx.m_vertCounts   = vertexCounts;
        }
 // Helper method for marshaling mesh data
 public static void BuildSceneContext(MeshFilter[] meshes, BakeContext ctx, IVertex vertex = null)
 {
     BuildSceneContext(meshes, null, null, ctx, vertex);
 }
        static void BuildLightContext(MeshFilter[] meshes, List <Light> lights, BakeContext ctx)
        {
            int lightCount = lights.Count;

            // light data size
            const int lightPosSize   = 3; // padded with extra float
            const int LightDirSize   = 3; // padded with extra float
            const int lightColorSize = 3; // padded with extra float (don't need alpha)
            const int lightRIATSize  = 4; // range, intensity, angle, type

            int totalLightSize = lightCount * SIZE_FLOAT * (lightPosSize + LightDirSize + lightColorSize + lightRIATSize);

            VertexBakerLib instance = VertexBakerLib.Instance;

            ctx.m_lightsDataPtr = instance.Alloc(totalLightSize);
            ctx.m_lightsOptPtr  = instance.Alloc(lightCount * SIZE_LONG);
            int lightDestOffset = 0;

            float[] riat = new float[4];
            long[]  data = new long[lightCount];

            // light layout
            for (int l = 0; l < lightCount; ++l)
            {
                Light light = lights[l];
                riat[0] = light.range;
                riat[1] = light.intensity;
                riat[2] = light.spotAngle;
                riat[3] = (float)light.type;

                // position data
                IntPtr lightPosPtr = new IntPtr(ctx.m_lightsDataPtr.ToInt64() + lightDestOffset * SIZE_FLOAT);
                instance.CopyVector4(lightPosPtr, lightPosSize * SIZE_FLOAT, light.transform.position.ToVector4(1f), lightPosSize * SIZE_FLOAT);
                lightDestOffset += lightPosSize;

                // direction data
                IntPtr lightDirPtr = new IntPtr(ctx.m_lightsDataPtr.ToInt64() + lightDestOffset * SIZE_FLOAT);
                instance.CopyVector4(lightDirPtr, LightDirSize * SIZE_FLOAT, light.transform.forward.ToVector4(0f), LightDirSize * SIZE_FLOAT);
                lightDestOffset += LightDirSize;

                // color data
                IntPtr lightColorPtr = new IntPtr(ctx.m_lightsDataPtr.ToInt64() + lightDestOffset * SIZE_FLOAT);
                instance.CopyVector4(lightColorPtr, lightColorSize * SIZE_FLOAT, light.color.ToVector4(1f), lightColorSize * SIZE_FLOAT);
                lightDestOffset += LightDirSize;

                // IRAT data
                IntPtr lightIRATPtr = new IntPtr(ctx.m_lightsDataPtr.ToInt64() + lightDestOffset * SIZE_FLOAT);
                instance.CopyFloatArray(lightIRATPtr, lightRIATSize * SIZE_FLOAT, riat, lightRIATSize * SIZE_FLOAT);
                lightDestOffset += lightRIATSize;

                // set lighting options
                ulong dataValue = 0;
                // 3 bits
                dataValue |= (ulong)lights[l].shadows;
                // 32 bits max
                dataValue |= (ulong)(((long)lights[l].cullingMask) << 3);

                data[l] |= (long)dataValue;
            }

            Marshal.Copy(data, 0, ctx.m_lightsOptPtr, lightCount);
        }
 // Prepare mesh data in a flexible way based on vertex definition
 static void BuildMesh(BakeContext ctx, Mesh mesh, IVertex vertex, ref int ptrOffset)
 {
     BuildMesh(ctx, mesh, vertex, null, ref ptrOffset);
 }