protected static void Init(MeshFilter meshFilter, Mesh untessellatedMesh) { if (!Directory.Exists(FBSConstants.BasePath + "/Cache/")) { Directory.CreateDirectory(FBSConstants.BasePath + "/Cache/"); } if (!Directory.Exists(FBSConstants.BasePath + "/BVHCache/")) { Directory.CreateDirectory(FBSConstants.BasePath + "/BVHCache/"); } if (meshFilter.sharedMesh == null) { Debug.LogWarning(meshFilter.gameObject.GetPath() + " is missing its source mesh"); return; } s_debugState = BakeData.Instance().GetDebugState(); #if _DAYDREAM_STATIC_LIGHTING_DEBUG DateTime start = DateTime.Now; // if we still have a handle for some reason try to free it if (s_lastInstanceId != meshFilter.GetUniqueId()) { if (s_bvhHandle != null) { VertexBakerLib.Instance.FreeHandle(s_bvhHandle.Ptr()); } s_bvhHandle = null; BuildWorldVertices(meshFilter); s_debugState.m_tessFaces = null; } TryLoadBVH(meshFilter); s_lastInstanceId = meshFilter.GetUniqueId(); if (s_bvhWrapper == null) { s_bvhWrapper = new BVHNode_FBWrapper(); } string sourceAssetPath = AssetDatabase.GetAssetPath(untessellatedMesh); if (!string.IsNullOrEmpty(sourceAssetPath) && !Application.isPlaying) { Debug.LogWarning("Could not find asset " + untessellatedMesh.name + " the asset may be an instance. Some debug data may not be available."); } string path = BVH.ConvertMeshIdToBVHPath(s_lastInstanceId); s_bvhWrapper.SetPath(path); s_bvhWrapper.Validate(); s_cacheWrapper.SetPath("" + s_lastInstanceId); s_cacheWrapper.Validate(); VertexBakerLib.Log("Debug setup time: " + (DateTime.Now - start).TotalSeconds + " seconds"); #endif }
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); }
protected static void TryLoadBVH(MeshFilter meshFilter) { if (meshFilter != null && meshFilter.sharedMesh != null) { if (!VertexBakerLib.Instance.LoadBVH(meshFilter, ref s_bvhHandle)) { // Load from scratch VertexBakerLib.Log("Could not load BVH data, building from scratch"); VertexBakerLib.BVHHandle[] bvhHandles = new VertexBakerLib.BVHHandle[1]; // build BVH and get handle VertexBakerLib.Instance.BuildBVH(new MeshFilter[] { meshFilter }, ref bvhHandles); // make sure its good if (bvhHandles != null && VertexBakerLib.Instance.ValidHandle(bvhHandles[0].Ptr())) { s_bvhHandle = bvhHandles[0]; if (VertexBakerLib.s_logging == VertexBakerLib.Logging.kVerbose) { VertexBakerLib.Log("BVH build success!"); } } else { s_bvhHandle = null; VertexBakerLib.LogError("Invalid BVH Handle, BVH not built"); } } } }
public bool LoadBVHScene(List <MeshFilter> meshes, out Handle bvhHandle) { // filter items meshes.RemoveAll(delegate(MeshFilter mf) { BakeFilter bf = mf.GetComponent <BakeFilter>(); if (bf != null) { return(bf.m_bakeFilter == BakeFilter.Filter.ExcludeFromBake); } return(false); }); // find BVH to rebuild List <MeshFilter> rebuildList = new List <MeshFilter>(); foreach (MeshFilter mf in meshes) { if (!IsValidBVH(mf)) { rebuildList.Add(mf); } } // build BVH for missing/out-of-date BVH's if (rebuildList.Count > 0) { BuildBVH(rebuildList.ToArray()); } // build id list IntPtr meshIdsPtr = Alloc(meshes.Count * SIZE_INT); int[] ids = new int[meshes.Count]; for (int m = 0; m < meshes.Count; ++m) { ids[m] = meshes[m].GetUniqueId(); } CopyArray(meshIdsPtr, meshes.Count * SIZE_INT, ids, meshes.Count * SIZE_INT); IntPtr[] handle = new IntPtr[1]; #if DDR_RUNTIME_DLL_LINKING_ int err = Invoke <int, _LoadBVHScene>(meshIdsPtr, meshes.Count, handle); #else int err = _LoadBVHScene(meshIdsPtr, meshes.Count, handle); #endif Free(meshIdsPtr); bvhHandle = new Handle(handle[0], this); if (err != 0) { string error = GetLastError(); VertexBakerLib.LogError(error); return(false); } return(true); }
public void BVHToLineSegment(Handle bvhSceneHandle, Vector3 startPoint, Vector3 endPoint, List <Vector3> outCenters, List <Vector3> outSizes) { IntPtr[] outCenterSizePtr = new IntPtr[1]; outCenterSizePtr[0] = IntPtr.Zero; int[] outCount = new int[1]; outCount[0] = 0; #if DDR_RUNTIME_DLL_LINKING_ int err = Invoke <int, _BVHToLineSegment>(bvhSceneHandle.Ptr(), startPoint, endPoint, outCenterSizePtr, outCount); #else int err = _BVHToLineSegment(bvhSceneHandle.Ptr(), ToFloatArray(startPoint), ToFloatArray(endPoint), outCenterSizePtr, outCount); #endif if (err == 0) { int count = outCount[0]; IntPtr dataPtr = outCenterSizePtr[0]; if (outCount[0] > 0 && dataPtr != IntPtr.Zero) { float[] rawData = new float[outCount[0]]; Marshal.Copy(dataPtr, rawData, 0, outCount[0]); for (int i = 0; i < count; i += 6) { outCenters.Add(new Vector3(rawData[i], rawData[i + 1], rawData[i + 2])); outSizes.Add(new Vector3(rawData[i + 3], rawData[i + 4], rawData[i + 5])); } Free(dataPtr); } } else { string error = GetLastError(); VertexBakerLib.LogError(error); } }
public void GetAsVec2(Mesh mesh, List <int> subMeshIndices, ref Vector2[] outData) { VertexElementType elType = (VertexElementType)m_elType; Vector2[] data = null; switch (elType) { case VertexElementType.kPosition: VertexBakerLib.LogError("Type Not Supported: " + elType); break; case VertexElementType.kNormal: VertexBakerLib.LogError("Type Not Supported: " + elType); break; case VertexElementType.kTangent: VertexBakerLib.LogError("Type Not Supported: " + elType); break; case VertexElementType.kColor: VertexBakerLib.LogError("Type Not Supported: " + elType); break; case VertexElementType.kUV0: data = mesh.uv; break; case VertexElementType.kUV1: data = mesh.uv2; break; case VertexElementType.kUV2: data = mesh.uv3; break; case VertexElementType.kUV3: data = mesh.uv4; break; default: VertexBakerLib.LogError("Type Not Supported: " + elType); outData = null; break; } if (subMeshIndices != null) { outData = new Vector2[subMeshIndices.Count]; for (int i = 0, k = subMeshIndices.Count; i < k; ++i) { outData[i] = data[subMeshIndices[i]]; } } else { outData = data; } }
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]); }
//private static void BuildWorldVertices(DaydreamVertexLighting source) //{ // s_debugState.m_worldVerPos = source.m_sourceMesh.vertices; // s_debugState.m_worldNormals = source.m_sourceMesh.normals; // for (int i = 0; i < s_debugState.m_worldNormals.Length; ++i) // { // s_debugState.m_worldVerPos[i] = source.transform.TransformPoint(s_debugState.m_worldVerPos[i]); // s_debugState.m_worldNormals[i] = source.transform.TransformVector(s_debugState.m_worldNormals[i]).normalized; // } //} #region Test Methods public void TestBuildBVHNative(DaydreamVertexLighting source) { DateTime start = DateTime.Now; MeshFilter meshFilter = source.GetComponent <MeshFilter>(); if (meshFilter != null) { VertexBakerLib.Instance.BuildBVH(new MeshFilter[] { meshFilter });; } VertexBakerLib.Log("Seconds to complete: " + (DateTime.Now - start).TotalSeconds); }
public int CopyVector4(IntPtr dest, int destSize, Vector4 src, int byteCount) { #if DDR_RUNTIME_DLL_LINKING_ int errno = Invoke <int, _CopyVector4>(dest, destSize, src, byteCount); #else int errno = _CopyVector4(dest, destSize, ref src, byteCount); #endif if (errno != 0) { VertexBakerLib.LogError("Error copying data in memcpy_s, errno " + errno); } return(errno == 0 ? byteCount : 0); }
public IntPtr Alloc(int size) { #if DDR_RUNTIME_DLL_LINKING_ IntPtr ptr = Invoke <IntPtr, _Alloc>(size); #else IntPtr ptr = _Alloc(size); #endif if (ptr == IntPtr.Zero) { VertexBakerLib.LogError("Alloc null"); } return(ptr); }
public bool LoadBVH(MeshFilter mesh, ref BVHHandle bvhHandle) { IntPtr[] handle = new IntPtr[1]; #if DDR_RUNTIME_DLL_LINKING_ int err = Invoke <int, _LoadBVH>(mesh.GetUniqueId(), handle); #else int err = _LoadBVH(mesh.GetUniqueId(), handle); #endif bvhHandle = new BVHHandle(mesh, handle[0], this); if (err != 0) { string error = GetLastError(); VertexBakerLib.LogError(error); return(false); } return(true); }
public void TestFileSystem() { #if DDR_RUNTIME_DLL_LINKING_ bool pass = Invoke <bool, _TestFileSystem>(); #else bool pass = _TestFileSystem(); #endif if (!pass) { VertexBakerLib.LogError("TestFileSystem failed"); } else { VertexBakerLib.Log("TestFileSystem pass"); } }
public int RayToIndex(Handle bvhSceneHandle, Vector3 startPoint, Vector3 endPoint) { int[] outIndex = new int[1]; outIndex[0] = -1; #if DDR_RUNTIME_DLL_LINKING_ int err = Invoke <int, _RayToIndex>(bvhSceneHandle.Ptr(), ToFloatArray(startPoint), ToFloatArray(endPoint), outIndex); #else int err = _RayToIndex(bvhSceneHandle.Ptr(), ToFloatArray(startPoint), ToFloatArray(endPoint), outIndex); #endif if (err != 0) { string error = GetLastError(); VertexBakerLib.LogError(error); } return(outIndex[0]); }
public void GetAsColor(Mesh mesh, List <int> subMeshIndices, ref Color[] outData) { Color[] data = null; VertexElementType elType = (VertexElementType)m_elType; switch (elType) { case VertexElementType.kPosition: VertexBakerLib.LogError("Type Not Supported: " + elType); break; case VertexElementType.kNormal: VertexBakerLib.LogError("Type Not Supported: " + elType); break; case VertexElementType.kTangent: VertexBakerLib.LogError("Type Not Supported: " + elType); break; case VertexElementType.kColor: data = mesh.colors; break; case VertexElementType.kUV0: case VertexElementType.kUV1: case VertexElementType.kUV2: case VertexElementType.kUV3: default: VertexBakerLib.LogError("Type Not Supported: " + elType); data = null; break; } if (subMeshIndices != null) { outData = new Color[subMeshIndices.Count]; for (int i = 0, k = subMeshIndices.Count; i < k; ++i) { outData[i] = data[subMeshIndices[i]]; } } else { outData = data; }; }
public string TestArrayOfInts(Matrix4x4 matrix) { int[] matrixArr = new int[16]; for (int i = 0; i < 16; ++i) { matrixArr[i] = (int)matrix[i]; } int size = matrixArr.Length; string msg = Marshal.PtrToStringAnsi(Invoke <IntPtr, _TestArrayOfInts>(matrixArr, size)); for (int i = 0; i < 16; ++i) { VertexBakerLib.Log("val " + matrixArr[i]); } return(msg); }
public void OccludersAtVertex(Handle bvhhandle, int vertIndex, Vector3 worldPos, Vector3 worldNorm , ref List <Vector3> testPoints, ref List <Vector3> colPoints, ref float accessability, ref Vector3 accumulatedRayDir) { // dest points data IntPtr[] testPointsPtr = new IntPtr[1]; int[] testPointCount = new int[1]; testPointsPtr[0] = IntPtr.Zero; testPointCount[0] = 0; // col Points data IntPtr[] colPointsPtr = new IntPtr[1]; int[] colCount = new int[1]; colPointsPtr[0] = IntPtr.Zero; colCount[0] = 0; // data to hold accessability float[] accessabilityOut = new float[1] { 0f }; // data to hold accumulated ray dir Vector3[] accumulatedRayDirOut = new Vector3[1] { Vector3.zero }; #if DDR_RUNTIME_DLL_LINKING_ int err = Invoke <int, _OccludersAtVertex>(bvhhandle.Ptr(), vertIndex, worldPos, worldNorm, testPointsPtr, testPointCount, colPointsPtr, colCount, accessabilityOut, accumulatedRayDirOut); #else int err = _OccludersAtVertex(bvhhandle.Ptr(), vertIndex, worldPos, worldNorm, testPointsPtr, testPointCount, colPointsPtr, colCount, accessabilityOut, accumulatedRayDirOut); #endif if (err == 0) { CopyFloatPtrToVectorList(testPointsPtr[0], testPointCount[0], ref testPoints); CopyFloatPtrToVectorList(colPointsPtr[0], colCount[0], ref colPoints); accessability = accessabilityOut[0]; accumulatedRayDir = accumulatedRayDirOut[0]; } else { string error = GetLastError(); VertexBakerLib.LogError(error); } }
public void LightBlockersAtVertex(Handle bvhhandle, int vertIndex, Vector3 worldPos, Vector3 worldNorm, Vector3 worldLightPos, Vector3 worldLightDir, Vector3 lightColor, Vector4 lightRIAT, ref List <Vector3> outStartPoints, ref List <Vector3> outEndPoints, ref List <Vector3> outColPoints) { IntPtr[] startPoints = new IntPtr[1]; IntPtr[] endPoints = new IntPtr[1]; int[] pointCount = new int[1]; startPoints[0] = IntPtr.Zero; endPoints[0] = IntPtr.Zero; pointCount[0] = 0; IntPtr[] colPoints = new IntPtr[1]; int[] colCount = new int[1]; colPoints[0] = IntPtr.Zero; colCount[0] = 0; #if DDR_RUNTIME_DLL_LINKING_ int err = Invoke <int, _LightBlockersAtVertex>(bvhhandle.Ptr(), vertIndex, worldPos, worldNorm, worldLightPos, worldLightDir , lightColor, lightRIAT, startPoints, endPoints, pointCount, colPoints, colCount); #else float[] wPosArr = ToFloatArray(worldPos); float[] wNormArr = ToFloatArray(worldNorm); float[] wLightPosArr = ToFloatArray(worldLightPos); float[] wLightDirArr = ToFloatArray(worldLightDir); float[] lightColorArr = ToFloatArray(lightColor); float[] lightRIATArr = ToFloatArray(lightRIAT); int err = _LightBlockersAtVertex(bvhhandle.Ptr(), vertIndex, wPosArr, wNormArr, wLightPosArr, wLightDirArr , lightColorArr, lightRIATArr, startPoints, endPoints, pointCount, colPoints, colCount); #endif if (err == 0) { CopyFloatPtrToVectorList(startPoints[0], pointCount[0], ref outStartPoints); CopyFloatPtrToVectorList(endPoints[0], pointCount[0], ref outEndPoints); CopyFloatPtrToVectorList(colPoints[0], colCount[0], ref outColPoints); } else { string error = GetLastError(); VertexBakerLib.LogError(error); } }
public void TestLoadBVH(DaydreamVertexLighting source) { DateTime start = DateTime.Now; MeshFilter meshFilter = source.GetComponent <MeshFilter>(); if (meshFilter != null) { try { VertexBakerLib.BVHHandle bvhHandle = null; if (VertexBakerLib.Instance.LoadBVH(meshFilter, ref bvhHandle)) { VertexBakerLib.Instance.FreeHandle(bvhHandle.Ptr()); } } catch (Exception e) { Debug.LogError(e.Message + "\n" + e.StackTrace); } } VertexBakerLib.Log("Seconds to complete: " + (DateTime.Now - start).TotalSeconds); }
public void Bake() { try { #if DDR_RUNTIME_DLL_LINKING_ m_result = VertexBakerLib.Instance.InvokeAsync <int, _Bake>(m_meshIdsPtr, m_vertexCountsPtr, m_triangleCountPtr, m_matDataPtr , m_meshDataPtr, m_triangleDataPtr, m_bakeOptionsPtr, m_layerPtr, m_meshCount, m_vertexEementCount, m_vertexDefinition, m_guids , m_sourcePaths, m_settingsIndicesPtr, m_settingsPtrs, m_lightsDataPtr, m_lightsOptPtr , m_lightCount, m_outBasis0, m_outBasis1, m_outBasis2); #else m_result = _Bake(m_meshIdsPtr, m_vertexCountsPtr, m_triangleCountPtr, m_matDataPtr , m_meshDataPtr, m_triangleDataPtr, m_bakeOptionsPtr, m_layerPtr, m_meshCount, m_vertexEementCount, m_vertexDefinition, m_guids , m_sourcePaths, m_settingsIndicesPtr, m_settingsPtrs, m_lightsDataPtr, m_lightsOptPtr , m_lightCount, m_outBasis0, m_outBasis1, m_outBasis2); #endif m_run = false; m_callback(); } catch (Exception e) { VertexBakerLib.LogError(e.Message); VertexBakerLib.LogError(e.StackTrace); } }
// 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; }
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); }
public int BakeFinish(OnFinishedUpdate onUpdate) { VertexBakerLib.Assert(this != null && !m_run, "BakeFinished called but bake is still in process"); string outputPath = BakeData.DataPath; if (!Directory.Exists(outputPath)) { Directory.CreateDirectory(outputPath); } if (m_result != 0) { string error = VertexBakerLib.Instance.GetLastError(); VertexBakerLib.LogError(error); } else if (!m_cancel && m_outBasis0[0] != IntPtr.Zero && m_outBasis1[0] != IntPtr.Zero && m_outBasis2[0] != IntPtr.Zero) { string bakeSetId = BakeData.Instance().GetBakeSettings().SelectedBakeSet.m_settingsId; BakeSets bakeSets = BakeData.Instance().GetBakeSets(); MeshContainer meshContainer = BakeData.Instance().GetMeshContainer(bakeSetId); EditorUtility.SetDirty(meshContainer); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); AssetDatabase.StartAssetEditing(); try { int ptrOffset = 0; int meshOffset = 0; for (int m = 0; m < m_meshes.Count; ++m) { int count = m_vertCounts[m]; int floatCount = count * 3; // the ID used to look up this mesh later string objectId = "" + m_lightBakers[m].GetUniqueId(); m_lightBakers[m].m_currentContainer = meshContainer; Mesh outputMesh = meshContainer.m_list.Find(delegate(Mesh mesh) { if (mesh != null) { return(mesh.name == bakeSetId + "_" + objectId); } return(false); }); if (outputMesh == null) { if (m_lightBakers[m].VertexLighting != null) { // if we are here than the mesh name may have changed, try and remove the stale data string oldName = m_lightBakers[m].VertexLighting.name; Mesh found = meshContainer.m_list.Find(delegate(Mesh mesh) { // remove the old reference if (mesh != null) { return(mesh.name == oldName); } // remove null mesh return(false); }); if (found != null) { GameObject.DestroyImmediate(found, true); } } // if no mesh exists for this target create it here outputMesh = new Mesh(); BakeData.Instance().AddToMeshContainer(meshContainer, outputMesh); //meshContainer.m_list.Add(outputMesh); //// add to the container asset //string outputFileName = bakeSetId + "_lighting"; //AssetDatabase.AddObjectToAsset(outputMesh, outputPath + "/" + outputFileName + ".asset"); } outputMesh.name = bakeSetId + "_" + objectId; // HACK: Work around to make Unity happy. If vertices are not found the additional vertex stream fails //outMeshes[m].vertices = m_meshes[m].sharedMesh.vertices; outputMesh.vertices = m_meshes[m].sharedMesh.vertices; // 3 floats per vector float[] rawData0 = new float[floatCount]; float[] rawData1 = new float[floatCount]; float[] rawData2 = new float[floatCount]; // offset pointer to next mesh IntPtr basis0 = new IntPtr(m_outBasis0[0].ToInt64() + ptrOffset * SIZE_FLOAT); IntPtr basis1 = new IntPtr(m_outBasis1[0].ToInt64() + ptrOffset * SIZE_FLOAT); IntPtr basis2 = new IntPtr(m_outBasis2[0].ToInt64() + ptrOffset * SIZE_FLOAT); ptrOffset += floatCount; // marshal data into float arrays Marshal.Copy(basis0, rawData0, 0, floatCount); Marshal.Copy(basis1, rawData1, 0, floatCount); Marshal.Copy(basis2, rawData2, 0, floatCount); // lists to hold output vectors List <Color> colorList0 = new List <Color>(); colorList0.Resize(count, Color.black); List <Vector3> colorList1 = new List <Vector3>(); colorList1.Resize(count, Vector3.zero); List <Vector3> colorList2 = new List <Vector3>(); colorList2.Resize(count, Vector3.zero); // copy float arrays into mesh data for (int i = 0; i < count; ++i) { int idx = i * 3; colorList0[i] = new Color(rawData0[idx], rawData0[idx + 1], rawData0[idx + 2], 1.0f); colorList1[i] = new Vector3(rawData1[idx], rawData1[idx + 1], rawData1[idx + 2]); colorList2[i] = new Vector3(rawData2[idx], rawData2[idx + 1], rawData2[idx + 2]); } // this offset is target uv sets 1, 2, and 3 for data destination const int uvOffset = 1; outputMesh.SetColors(colorList0); outputMesh.SetUVs(uvOffset + 1, colorList1); outputMesh.SetUVs(uvOffset + 2, colorList2); //outputMesh.UploadMeshData(true); meshOffset += count; EditorUtility.SetDirty(meshContainer); m_meshRenderers[m].additionalVertexStreams = outputMesh; m_lightBakers[m].m_bakeSets = bakeSets; m_lightBakers[m].VertexLighting = outputMesh; m_lightBakers[m].m_bakeId = objectId; EditorUtility.SetDirty(m_lightBakers[m]); onUpdate("Uploading Mesh Data", m_meshCount / (float)m); } // remove any null slots meshContainer.m_list.RemoveAll(delegate(Mesh m) { return(m == null); }); // aggregate containers under one super container int existingIdx = bakeSets.m_containers.FindIndex(delegate(MeshContainer mc) { return(mc.name == meshContainer.name); }); if (existingIdx != -1) { // replace existing entry bakeSets.m_containers[existingIdx] = meshContainer; } else { bakeSets.m_containers.Add(meshContainer); } BakeSetsInspector.CleanupStaleReferences(bakeSets); EditorUtility.SetDirty(bakeSets); AssetDatabase.SaveAssets(); } finally { onUpdate("Uploading Mesh Data", 1f); AssetDatabase.StopAssetEditing(); } } else { VertexBakerLib.LogWarning("Bake completed successfully but there was no output data available"); } // free data FreeContext(true); // since basis memory was allocated in one chunk // freeing this handle frees all basis memory VertexBakerLib.Instance.Free(m_outBasis0[0]); EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene()); EditorSceneManager.SaveScene(EditorSceneManager.GetActiveScene()); VertexBakerLib.Log("Bake time: " + (DateTime.Now - m_bakeStart).TotalSeconds + " seconds"); while (VertexBakerLib.Instance.GetErrorCount() > 0) { string err = VertexBakerLib.Instance.GetLastError(); VertexBakerLib.LogError(err); } GC.Collect(); return(m_result); }
public void GetAsVec4(Mesh mesh, List <int> subMeshIndices, ref Vector4[] outData) { Vector4[] data = null; VertexElementType elType = (VertexElementType)m_elType; switch (elType) { case VertexElementType.kPosition: VertexBakerLib.LogError("Type Not Supported: " + elType); break; case VertexElementType.kNormal: VertexBakerLib.LogError("Type Not Supported: " + elType); break; case VertexElementType.kTangent: data = mesh.tangents; break; case VertexElementType.kColor: case VertexElementType.kUV0: { List <Vector4> v = new List <Vector4>(); mesh.GetUVs(0, v); data = v.ToArray(); break; } case VertexElementType.kUV1: { List <Vector4> v = new List <Vector4>(); mesh.GetUVs(1, v); data = v.ToArray(); break; } case VertexElementType.kUV2: { List <Vector4> v = new List <Vector4>(); mesh.GetUVs(2, v); data = v.ToArray(); break; } case VertexElementType.kUV3: { List <Vector4> v = new List <Vector4>(); mesh.GetUVs(3, v); data = v.ToArray(); break; } default: VertexBakerLib.LogError("Type Not Supported: " + elType); data = null; break; } if (subMeshIndices != null) { outData = new Vector4[subMeshIndices.Count]; for (int i = 0, k = subMeshIndices.Count; i < k; ++i) { outData[i] = data[subMeshIndices[i]]; } } else { outData = data; } }
public Handle(IntPtr handle, VertexBakerLib lib) { m_handle = handle; m_lib = lib; }
private static void BakeHelper(GameObject[] bakeRoots) { VertexBakerLib.Instance.BakeReset(); DateTime bakeStart = DateTime.Now; List <MeshFilter> meshes = new List <MeshFilter>(); s_meshRenderers = new List <MeshRenderer>(); // gather meshes in selection foreach (GameObject go in bakeRoots) { MeshFilter[] filters = go.GetComponentsInChildren <MeshFilter>(); foreach (MeshFilter filter in filters) { MeshRenderer mr = filter.GetComponent <MeshRenderer>(); if (filter.sharedMesh == null) { Debug.LogWarning(filter.gameObject.GetPath() + " has a missing mesh"); } bool staticLit = (StaticEditorFlags.LightmapStatic & GameObjectUtility.GetStaticEditorFlags(filter.gameObject)) > 0; if (filter.sharedMesh != null && filter.gameObject.activeSelf && staticLit && mr != null && mr.enabled) { s_meshRenderers.Add(mr); meshes.Add(filter); } } } if (meshes.Count == 0) { EditorUtility.DisplayDialog(Styles.kEditorTitle, Styles.kNoStaticMeshes, "ok"); return; } if (meshes.Count != s_meshRenderers.Count) { EditorUtility.DisplayDialog(Styles.kEditorTitle, "MeshRenderers are not 1 to 1 with Mesh Filters", "ok"); return; } List <Light> lights = new List <Light>(); DDRSettings settingsData = BakeData.Instance().GetBakeSettings(); if (settingsData.SelectedBakeSet.m_forceAllLights) { List <GameObject> sceneRoots = Utilities.GetAllRoots(); foreach (GameObject go in sceneRoots) { Light[] lightList = go.GetComponentsInChildren <Light>(); foreach (Light light in lightList) { if (light.IsLightmapLight()) { lights.Add(light); } } } } else { List <LightEntry> lightFilter = settingsData.SelectedBakeSet.m_lightList; Dictionary <int, Light> localFileIdToLight = Utilities.LightsByLocalFileId(); foreach (LightEntry lightEntry in lightFilter) { Light light = null; // group if lights if (!string.IsNullOrEmpty(lightEntry.m_group)) { // get parent objects for each path that matches the group path List <GameObject> parents = Utilities.FindAll(lightEntry.m_group); // gather all lights under group if (parents.Count > 0) { // add lights to the new group foreach (GameObject parent in parents) { for (int i = 0; i < parent.transform.childCount; ++i) { GameObject child = parent.transform.GetChild(i).gameObject; light = child.GetComponent <Light>(); if (light.IsLightmapLight()) { lights.Add(light); } } } } } else { // ungrouped light if (localFileIdToLight.TryGetValue(lightEntry.m_idInFile, out light)) { if (light.IsLightmapLight()) { lights.Add(light); } } } } } VertexBakerLib.Log("Collect data time: " + (DateTime.Now - bakeStart).TotalSeconds + " seconds"); /////////////// // native bake /////////////// try { // stop listening for changes m_ignoreNextChange = true; // int activeLightCount = DaydreamRendererSceneData.GetActiveLightCount(); // DaydreamRendererSceneData sceneData = TypeExtensions.FindOrCreateScriptableAsset<DaydreamRendererSceneData>(VertexBakerLib.DataPath, "scenedata"); s_bakeInProgress = true; VertexBakerLib.Instance.Bake(meshes, lights, delegate() { s_bakeIsFinished = true; }); } catch (Exception e) { Debug.LogError(e.Message); Debug.LogError(e.StackTrace); } }
public BVHHandle(MeshFilter source, IntPtr handle, VertexBakerLib lib) : base(handle, lib) { SourceMeshData = source; }