void RenderModelsInVoxels(VoxelChunk chunk, FastList <ModelInVoxel> mivs) { instancingManager.ClearChunk(chunk); Quaternion rotation = Misc.quaternionZero; Vector3 position; for (int k = 0; k < mivs.count; k++) { ModelInVoxel miv = mivs.values [k]; VoxelDefinition voxelDefinition = miv.vd; bool createGO = voxelDefinition.createGameObject || !voxelDefinition.gpuInstancing; if (createGO) { VoxelPlaceholder placeholder = GetVoxelPlaceholder(chunk, miv.voxelIndex, true); bool createModel = true; if (placeholder.modelInstance != null) { if (placeholder.modelTemplate != voxelDefinition.model) { DestroyImmediate(placeholder.modelInstance); } else { createModel = false; } } MeshFilter mf; Mesh mesh = null; if (createModel || placeholder.modelMeshFilter == null || placeholder.modelMeshFilter.sharedMesh == null || placeholder.modelMeshRenderer == null) { if (voxelDefinition.model == null) { continue; } placeholder.modelTemplate = voxelDefinition.model; placeholder.modelInstance = Instantiate(voxelDefinition.model); placeholder.modelInstance.name = "DynamicVoxelInstance"; // Note: placeHolder.modelInstance layer must be different from layerVoxels to allow dynamic voxels collide with terrain. So don't set its layer to layer voxels placeholder.modelMeshRenderer = placeholder.modelInstance.GetComponent <MeshRenderer> (); if (voxelDefinition.gpuInstancing) { if (placeholder.modelMeshRenderer != null) { placeholder.modelMeshRenderer.enabled = false; } } else { mf = placeholder.modelMeshFilter = placeholder.modelInstance.GetComponent <MeshFilter> (); if (mf != null) { mesh = mf.sharedMesh = Instantiate <Mesh> (mf.sharedMesh); mesh.hideFlags = HideFlags.DontSave; } } } else { mf = placeholder.modelMeshFilter; if (mf != null) { mesh = mf.sharedMesh; } } // Parent model to the placeholder Transform tModel = placeholder.modelInstance.transform; tModel.SetParent(placeholder.transform, false); tModel.transform.localPosition = Misc.vector3zero; tModel.transform.localScale = voxelDefinition.scale; if (voxelDefinition.gpuInstancing) { rotation = placeholder.transform.localRotation; } else { // Adjust lighting if (effectiveGlobalIllumination || chunk.voxels [miv.voxelIndex].isColored) { // Update mesh colors float voxelLight = chunk.voxels [miv.voxelIndex].lightMesh / 15f; Color32 color = chunk.voxels [miv.voxelIndex].color; color.r = (byte)(color.r * voxelLight); color.g = (byte)(color.g * voxelLight); color.b = (byte)(color.b * voxelLight); modelMeshColors.Clear(); for (int c = 0; c < mesh.vertexCount; c++) { modelMeshColors.Add(color); } mesh.SetColors(modelMeshColors); mesh.UploadMeshData(false); } } if (!tModel.gameObject.activeSelf) { tModel.gameObject.SetActive(true); } position = placeholder.transform.position; } else { // pure gpu instancing, no gameobject position = GetVoxelPosition(chunk, miv.voxelIndex); rotation = voxelDefinition.GetRotation(position); // deterministic rotation // User rotation float rot = chunk.voxels [miv.voxelIndex].GetTextureRotationDegrees(); if (rot != 0) { rotation *= Quaternion.Euler(0, rot, 0); } // Custom position position = position + rotation * voxelDefinition.GetOffset(position); } if (voxelDefinition.gpuInstancing) { instancingManager.AddVoxel(chunk, miv.voxelIndex, position, rotation, voxelDefinition.scale); } } }
void RenderModelsInVoxels(VoxelChunk chunk, FastList <ModelInVoxel> mivs) { instancedRenderer.ClearChunk(chunk); // deactivate all models in this chunk // we need to iterate the placeholders list entirely to address the case when the voxel is not using GPU instancing. In this case the gameobject renderer needs to be disabled // and we need to do this way because mivs won't contain the custom voxel since it may be termporarily converted to a transparent voxels due to see-through effect if (chunk.placeholders != null) { int count = chunk.placeholders.Count; for (int k = 0; k < count; k++) { if (chunk.placeholders.entries [k].key >= 0) { VoxelPlaceholder placeHolder = chunk.placeholders.entries [k].value; if (placeHolder != null) { placeHolder.ToggleRenderers(false); } } } } Quaternion rotation = Misc.quaternionZero; Vector3 position; for (int k = 0; k < mivs.count; k++) { ModelInVoxel miv = mivs.values [k]; VoxelDefinition voxelDefinition = miv.vd; bool createGO = voxelDefinition.createGameObject || !voxelDefinition.gpuInstancing; if (VoxelIsHidden(chunk, miv.voxelIndex)) { continue; } if (createGO) { VoxelPlaceholder placeholder = GetVoxelPlaceholder(chunk, miv.voxelIndex, true); bool createModel = true; if (placeholder.modelInstance != null) { if (placeholder.modelTemplate != voxelDefinition.prefab) { DestroyImmediate(placeholder.modelInstance); placeholder.originalMeshColors32 = null; placeholder.lastMivTintColor = Misc.color32White; } else { createModel = false; } } if (createModel || placeholder.modelInstance == null) { if (voxelDefinition.prefab == null) { continue; } placeholder.modelTemplate = voxelDefinition.prefab; placeholder.modelInstance = Instantiate(voxelDefinition.prefab); placeholder.modelInstance.name = "DynamicVoxelInstance"; // Note: placeHolder.modelInstance layer must be different from layerVoxels to allow dynamic voxels collide with terrain. So don't set its layer to layer voxels placeholder.modelMeshRenderers = placeholder.modelInstance.GetComponentsInChildren <MeshRenderer> (); if (voxelDefinition.gpuInstancing) { placeholder.ToggleRenderers(false); } else { placeholder.modelMeshFilter = placeholder.modelInstance.GetComponentInChildren <MeshFilter> (true); } // Parent model to the placeholder Transform tModel = placeholder.modelInstance.transform; tModel.SetParent(placeholder.transform, false); tModel.transform.localPosition = Misc.vector3zero; tModel.transform.localScale = voxelDefinition.scale; } else { placeholder.ToggleRenderers(true); } if (voxelDefinition.gpuInstancing) { rotation = placeholder.transform.localRotation; } else { // Adjust lighting if (effectiveGlobalIllumination || chunk.voxels [miv.voxelIndex].isColored) { // Update mesh colors MeshFilter mf = placeholder.modelMeshFilter; if (mf != null) { Mesh mesh = mf.sharedMesh; if (mesh != null) { Color32 tintColor = chunk.voxels [miv.voxelIndex].color; tintColor.a = (byte)(chunk.voxels[miv.voxelIndex].lightMesh + (chunk.voxels[miv.voxelIndex].torchLight << 4)); if (placeholder.lastMivTintColor.a != tintColor.a || placeholder.lastMivTintColor.r != tintColor.r || placeholder.lastMivTintColor.g != tintColor.g || placeholder.lastMivTintColor.b != tintColor.b) { mf.sharedMesh = BakeMeshLighting(mf, tintColor); placeholder.lastMivTintColor = tintColor; } } } } } if (!placeholder.modelInstance.gameObject.activeSelf) { placeholder.modelInstance.gameObject.SetActive(true); } position = placeholder.transform.position; } else { // pure gpu instancing, no gameobject position = GetVoxelPosition(chunk, miv.voxelIndex); rotation = voxelDefinition.GetRotation(position); // deterministic rotation // User rotation float rot = chunk.voxels [miv.voxelIndex].GetTextureRotationDegrees(); if (rot != 0) { rotation *= Quaternion.Euler(0, rot, 0); } // Custom position position += rotation * voxelDefinition.GetOffset(position); } if (voxelDefinition.gpuInstancing) { instancedRenderer.AddVoxel(chunk, miv.voxelIndex, position, rotation, voxelDefinition.scale); } } }