/// <summary> /// 指定の LOD についての分割ロード要求をキューへ追加します。 /// </summary> /// <param name="interBlockMesh">BlockMesh のロード元となる InterBlockMesh。</param> /// <param name="blockMesh">分割ロード対応の BlockMesh。</param> /// <param name="levelOfDetail">対象とする LOD。</param> void Enqueue(InterBlockMesh interBlockMesh, BlockMesh blockMesh, int levelOfDetail) { for (int i = 0; i < blockMesh.MeshLods[levelOfDetail].MeshParts.Count; i++) { Enqueue(interBlockMesh, blockMesh, levelOfDetail, i); } }
/// <summary> /// InterBlockMesh の頂点情報とエフェクト情報をもとに BlockMesh を生成します。 /// </summary> /// <param name="interMesh">頂点情報とエフェクト情報を提供する InterBlockMesh。</param> /// <returns>生成された BlockMesh。</returns> public BlockMesh Create(InterBlockMesh interMesh) { var lodCount = interMesh.MeshLods.Length; var mesh = new BlockMesh(); mesh.SetMeshMaterials(interMesh.MeshMaterials); mesh.AllocateMeshLods(lodCount); for (int lod = 0; lod < lodCount; lod++) { var interMeshLod = interMesh.MeshLods[lod]; var meshLod = mesh.MeshLods[lod]; var meshPartCount = interMeshLod.MeshParts.Length; meshLod.AllocateMeshParts(GraphicsDevice, meshPartCount); for (int i = 0; i < meshPartCount; i++) { var interMeshPart = interMeshLod.MeshParts[i]; var meshPart = meshLod.MeshParts[i]; meshPart.MeshMaterial = mesh.MeshMaterials[interMeshPart.MeshMaterialIndex]; meshPart.PopulateVertices(interMeshPart.Vertices); meshPart.PopulateIndices(interMeshPart.Indices); } } return mesh; }
/// <summary> /// InterBlockMesh の頂点情報とエフェクト情報をもとに BlockMesh を生成します。 /// </summary> /// <param name="interMesh">頂点情報とエフェクト情報を提供する InterBlockMesh。</param> /// <returns>生成された BlockMesh。</returns> public BlockMesh Create(InterBlockMesh interMesh) { var lodCount = interMesh.MeshLods.Length; var mesh = new BlockMesh(); mesh.SetMeshMaterials(interMesh.MeshMaterials); mesh.AllocateMeshLods(lodCount); for (int lod = 0; lod < lodCount; lod++) { var interMeshLod = interMesh.MeshLods[lod]; var meshLod = mesh.MeshLods[lod]; var meshPartCount = interMeshLod.MeshParts.Length; meshLod.AllocateMeshParts(GraphicsDevice, meshPartCount); for (int i = 0; i < meshPartCount; i++) { var interMeshPart = interMeshLod.MeshParts[i]; var meshPart = meshLod.MeshParts[i]; meshPart.MeshMaterial = mesh.MeshMaterials[interMeshPart.MeshMaterialIndex]; meshPart.PopulateVertices(interMeshPart.Vertices); meshPart.PopulateIndices(interMeshPart.Indices); } } return(mesh); }
/// <summary> /// 分割ロード対応の BlockMesh を生成します。 /// </summary> /// <param name="graphicsDevice">GraphicsDevice。</param> /// <param name="interBlockMesh">BlockMesh のロード元となる InterBlockMesh。</param> /// <returns>分割ロード対応の BlockMesh。</returns> BlockMesh CreatePhasedBlockMesh(GraphicsDevice graphicsDevice, InterBlockMesh interBlockMesh) { var lodCount = interBlockMesh.MeshLods.Length; var blockMesh = new BlockMesh(); blockMesh.SetMeshMaterials(interBlockMesh.MeshMaterials); blockMesh.AllocateMeshLods(lodCount); for (int lod = 0; lod < lodCount; lod++) { var interMeshLod = interBlockMesh.MeshLods[lod]; var meshPartCount = interMeshLod.MeshParts.Length; var meshLod = blockMesh.MeshLods[lod]; meshLod.AllocateMeshParts(graphicsDevice, meshPartCount); for (int i = 0; i < meshPartCount; i++) { var interMeshPart = interMeshLod.MeshParts[i]; var meshPart = meshLod.MeshParts[i]; meshPart.MeshMaterial = blockMesh.MeshMaterials[interMeshPart.MeshMaterialIndex]; } } return(blockMesh); }
/// <summary> /// ThreadPool から提供される Thread から呼び出されます。 /// </summary> /// <param name="state">Task。</param> void WaitCallback(object state) { var taskInThread = state as TaskInThread; InterBlockMesh interBlockMesh = null; Exception exception = null; try { interBlockMesh = taskInThread.Task.Execute(); } catch (Exception e) { exception = e; } var result = new ResultInQueue { ResultCallback = taskInThread.Task.Callback, Name = taskInThread.Task.Name, InterBlockMesh = interBlockMesh, Exception = exception }; // 処理結果をキューへ入れます。 lock (resultQueue) resultQueue.Enqueue(result); // 空き Thread としてマークします。 lock (freeThread) freeThread.Enqueue(taskInThread); }
/// <summary> /// BlockMesh の分割ロード要求を追加します。 /// </summary> /// <param name="graphicsDevice">GraphicsDevice。</param> /// <param name="interBlockMesh">BlockMesh のロード元となる InterBlockMesh。</param> /// <returns>分割ロード対応の BlockMesh。</returns> public BlockMesh Load(GraphicsDevice graphicsDevice, InterBlockMesh interBlockMesh) { // 分割ロード対応の BlockMesh を生成します。 var blockMesh = CreatePhasedBlockMesh(graphicsDevice, interBlockMesh); // ロード要求をキューに追加します。 var coarsestLod = blockMesh.MeshLods.Count - 1; Enqueue(interBlockMesh, blockMesh, coarsestLod); // 分割ロード対応の BlockMesh を要求元へ返します。 return blockMesh; }
/// <summary> /// BlockMesh の分割ロード要求を追加します。 /// </summary> /// <param name="graphicsDevice">GraphicsDevice。</param> /// <param name="interBlockMesh">BlockMesh のロード元となる InterBlockMesh。</param> /// <returns>分割ロード対応の BlockMesh。</returns> public BlockMesh Load(GraphicsDevice graphicsDevice, InterBlockMesh interBlockMesh) { // 分割ロード対応の BlockMesh を生成します。 var blockMesh = CreatePhasedBlockMesh(graphicsDevice, interBlockMesh); // ロード要求をキューに追加します。 var coarsestLod = blockMesh.MeshLods.Count - 1; Enqueue(interBlockMesh, blockMesh, coarsestLod); // 分割ロード対応の BlockMesh を要求元へ返します。 return(blockMesh); }
/// <summary> /// 指定の BlockMeshPart のロード要求をキューへ追加します。 /// </summary> /// <param name="interBlockMesh">BlockMesh のロード元となる InterBlockMesh。</param> /// <param name="blockMesh">分割ロード対応の BlockMesh。</param> /// <param name="levelOfDetail">対象とする LOD。</param> /// <param name="meshPartIndex">対象とする BlockMeshPart のインデックス。</param> void Enqueue(InterBlockMesh interBlockMesh, BlockMesh blockMesh, int levelOfDetail, int meshPartIndex) { lock (this) { if (queue.Count == MaxCapacity) { throw new InvalidOperationException("This queue is full."); } var item = new Item { InterBlockMesh = interBlockMesh, BlockMesh = blockMesh, LevelOfDetail = levelOfDetail, MeshPartIndex = meshPartIndex }; queue.Add(item); } }
/// <summary> /// InterBlockMesh を生成します。 /// </summary> /// <param name="lodBlocks">各 LOD の InterBlock を要素とした配列。</param> /// <returns>生成された BlockMesh。</returns> static InterBlockMesh Create(InterBlock[] lodBlocks) { // InterBlockMesh を生成します。 var mesh = new InterBlockMesh(); // InterBlockEffect を生成します。 // LOD 間で Material は共有しているので、最大 LOD の Material から生成します。 mesh.MeshMaterials = new BlockMeshMaterial[lodBlocks[0].Materials.Count]; for (int i = 0; i < mesh.MeshMaterials.Length; i++) { var block = lodBlocks[0]; mesh.MeshMaterials[i] = new BlockMeshMaterial { DiffuseColor = block.Materials[i].DiffuseColor.ToVector3(), EmissiveColor = block.Materials[i].EmissiveColor.ToVector3(), SpecularColor = block.Materials[i].SpecularColor.ToVector3(), SpecularPower = block.Materials[i].SpecularPower }; } // 実際に必要となる LOD 数をもとめます。 int actualLodCount = 0; for (int lod = 0; lod < lodBlocks.Length; lod++) { // 要素数 0 の InterBlock は、それ以上粒度を荒くできなかったことを表します。 if (lodBlocks[lod].Elements.Count == 0) break; actualLodCount++; } // 実際の LOD 数の分だけ InterBlockMeshLod 領域を確保します。 mesh.MeshLods = new InterBlockMeshLod[actualLodCount]; var meshPartVS = new VertexSource<VertexPositionNormal, ushort>(); // LOD ごとに InterBlockMeshPart を生成します。 for (int lod = 0; lod < actualLodCount; lod++) { var block = lodBlocks[lod]; // Element を分類します。 var elementClassifier = ElementClassifier.Classify(block.Elements); var cubeSurfaceVS = cubeSurfaceVertexSourceMap[block.ElementSize]; int meshPartCount = elementClassifier.Parts.Count; var meshLod = new InterBlockMeshLod { MeshParts = new InterBlockMeshPart[meshPartCount] }; mesh.MeshLods[lod] = meshLod; // InterBlockMeshPart を生成して登録します。 for (int i = 0; i < meshPartCount; i++) { var part = elementClassifier.Parts[i]; // 頂点データを作成します。 meshPartVS.Clear(); MakeMeshPartVertexSource(meshPartVS, part, cubeSurfaceVS, block.ElementSize); // InterBlockMeshPart を生成します。 meshLod.MeshParts[i] = new InterBlockMeshPart { MeshMaterialIndex = part.MaterialIndex, Vertices = meshPartVS.Vertices.ToArray(), Indices = meshPartVS.Indices.ToArray() }; } } return mesh; }
/// <summary> /// InterBlockMesh を生成します。 /// </summary> /// <param name="lodBlocks">各 LOD の InterBlock を要素とした配列。</param> /// <returns>生成された BlockMesh。</returns> static InterBlockMesh Create(InterBlock[] lodBlocks) { // InterBlockMesh を生成します。 var mesh = new InterBlockMesh(); // InterBlockEffect を生成します。 // LOD 間で Material は共有しているので、最大 LOD の Material から生成します。 mesh.MeshMaterials = new BlockMeshMaterial[lodBlocks[0].Materials.Count]; for (int i = 0; i < mesh.MeshMaterials.Length; i++) { var block = lodBlocks[0]; mesh.MeshMaterials[i] = new BlockMeshMaterial { DiffuseColor = block.Materials[i].DiffuseColor.ToVector3(), EmissiveColor = block.Materials[i].EmissiveColor.ToVector3(), SpecularColor = block.Materials[i].SpecularColor.ToVector3(), SpecularPower = block.Materials[i].SpecularPower }; } // 実際に必要となる LOD 数をもとめます。 int actualLodCount = 0; for (int lod = 0; lod < lodBlocks.Length; lod++) { // 要素数 0 の InterBlock は、それ以上粒度を荒くできなかったことを表します。 if (lodBlocks[lod].Elements.Count == 0) { break; } actualLodCount++; } // 実際の LOD 数の分だけ InterBlockMeshLod 領域を確保します。 mesh.MeshLods = new InterBlockMeshLod[actualLodCount]; var meshPartVS = new VertexSource <VertexPositionNormal, ushort>(); // LOD ごとに InterBlockMeshPart を生成します。 for (int lod = 0; lod < actualLodCount; lod++) { var block = lodBlocks[lod]; // Element を分類します。 var elementClassifier = ElementClassifier.Classify(block.Elements); var cubeSurfaceVS = cubeSurfaceVertexSourceMap[block.ElementSize]; int meshPartCount = elementClassifier.Parts.Count; var meshLod = new InterBlockMeshLod { MeshParts = new InterBlockMeshPart[meshPartCount] }; mesh.MeshLods[lod] = meshLod; // InterBlockMeshPart を生成して登録します。 for (int i = 0; i < meshPartCount; i++) { var part = elementClassifier.Parts[i]; // 頂点データを作成します。 meshPartVS.Clear(); MakeMeshPartVertexSource(meshPartVS, part, cubeSurfaceVS, block.ElementSize); // InterBlockMeshPart を生成します。 meshLod.MeshParts[i] = new InterBlockMeshPart { MeshMaterialIndex = part.MaterialIndex, Vertices = meshPartVS.Vertices.ToArray(), Indices = meshPartVS.Indices.ToArray() }; } } return(mesh); }
/// <summary> /// 指定の BlockMeshPart のロード要求をキューへ追加します。 /// </summary> /// <param name="interBlockMesh">BlockMesh のロード元となる InterBlockMesh。</param> /// <param name="blockMesh">分割ロード対応の BlockMesh。</param> /// <param name="levelOfDetail">対象とする LOD。</param> /// <param name="meshPartIndex">対象とする BlockMeshPart のインデックス。</param> void Enqueue(InterBlockMesh interBlockMesh, BlockMesh blockMesh, int levelOfDetail, int meshPartIndex) { lock (this) { if (queue.Count == MaxCapacity) throw new InvalidOperationException("This queue is full."); var item = new Item { InterBlockMesh = interBlockMesh, BlockMesh = blockMesh, LevelOfDetail = levelOfDetail, MeshPartIndex = meshPartIndex }; queue.Add(item); } }
/// <summary> /// 分割ロード対応の BlockMesh を生成します。 /// </summary> /// <param name="graphicsDevice">GraphicsDevice。</param> /// <param name="interBlockMesh">BlockMesh のロード元となる InterBlockMesh。</param> /// <returns>分割ロード対応の BlockMesh。</returns> BlockMesh CreatePhasedBlockMesh(GraphicsDevice graphicsDevice, InterBlockMesh interBlockMesh) { var lodCount = interBlockMesh.MeshLods.Length; var blockMesh = new BlockMesh(); blockMesh.SetMeshMaterials(interBlockMesh.MeshMaterials); blockMesh.AllocateMeshLods(lodCount); for (int lod = 0; lod < lodCount; lod++) { var interMeshLod = interBlockMesh.MeshLods[lod]; var meshPartCount = interMeshLod.MeshParts.Length; var meshLod = blockMesh.MeshLods[lod]; meshLod.AllocateMeshParts(graphicsDevice, meshPartCount); for (int i = 0; i < meshPartCount; i++) { var interMeshPart = interMeshLod.MeshParts[i]; var meshPart = meshLod.MeshParts[i]; meshPart.MeshMaterial = blockMesh.MeshMaterials[interMeshPart.MeshMaterialIndex]; } } return blockMesh; }
void InterBlockMeshLoadTaskCallback(string name, InterBlockMesh result) { if (meshName == name) mesh = workspace.LoadBlockMesh(result); }
public BlockMesh LoadBlockMesh(InterBlockMesh interBlockMesh) { return blockMeshLoadQueue.Load(GraphicsDevice, interBlockMesh); }