/// <summary> /// Create Foliage mesh instances for a certain index and foliage size. /// </summary> /// <param name="meshInstances"></param> /// <param name="prototypeIndex"></param> public static void GenerateFoliageMeshInstanceForIndex(int prototypeIndex, FoliageResolutions resolution) { Dictionary <int, GPUMesh> meshInstances = prototypeMeshInstances[resolution]; FoliagePrototype prototype = FoliageDB.sortedPrototypes[prototypeIndex]; if (!FoliageCore_MainManager.instance.enabled) { return; } bool prototypeMeshExists = prototypeMeshInstances != null && meshInstances.ContainsKey(prototypeIndex); if (prototypeMeshExists) { meshInstances[prototypeIndex].Destroy(); meshInstances.Remove(prototypeIndex); } Mesh[] meshes = new Mesh[prototype.meshLodsCount]; int[] densities = new int[prototype.meshLodsCount]; List <UNPhysicsTemplate>[] physicsObjects = new List <UNPhysicsTemplate> [prototype.meshLodsCount]; for (int i = 0; i < prototype.meshLodsCount; i++) { meshes[i] = CreateNewMesh(); densities[i] = Mathf.FloorToInt((float)prototype.maxGeneratedDensity / (i + 1)); FoliageMeshInstance.CreateGPUMesh(prototype, meshes[i], densities[i]); } meshInstances.Add(prototypeIndex, new GPUMesh(meshes, densities, prototypeIndex, physicsObjects, resolution)); }
public static FoliageMeshInstance CreateFoliageMesh(FoliagePrototype prototype, Vector3 position, int maxInstancesPerMesh) { FoliageMeshInstance instance = new FoliageMeshInstance(); instance.prototype = prototype; instance.position = position; instance.maxInstancesPerMesh = maxInstancesPerMesh; return(instance); }
public GPUMesh(Mesh[] LODMeshes, int[] LODLevels, int prototypeIndex, List <UNPhysicsTemplate>[] physicsInformation, FoliageResolutions resolution) { if (LODMeshes.Length != LODLevels.Length) { Debug.LogError("uNature Foliage : Generating LODs Failed!, Array sizes are different!"); return; } LODMeshInstances = new FoliageMeshInstancesGroup[LODMeshes.Length]; for (int i = 0; i < LODMeshes.Length; i++) { meshes.Add(new GPUMeshLOD(LODMeshes[i], LODLevels[i], prototypeIndex, physicsInformation[i])); LODMeshInstances[i] = FoliageMeshInstance.CreateFoliageInstances(prototypeIndex, LODLevels[i], resolution); } }
public static FoliageMeshInstancesGroup CreateFoliageInstances(int prototypeIndex, int density, FoliageResolutions resolution) { float resMultiplier = (float)resolution / FoliageCore_MainManager.FOLIAGE_INSTANCE_AREA_SIZE; FoliagePrototype prototype = FoliageDB.sortedPrototypes[prototypeIndex]; int maxGenerationInstancesPerMesh = (int)(CalculatePerMeshInstances(prototype, density) / resMultiplier); int generationAmountPerRadius = GENERATION_AMOUNT_PER_RADIUS(maxGenerationInstancesPerMesh); FoliageMeshInstancesGroup meshGroup = new FoliageMeshInstancesGroup(); Vector3 position; int gAmountX = generationAmountPerRadius - (int)prototype.meshInstancesGenerationOffset.x; if (gAmountX == 0) { gAmountX = 1; // dont clamp, it can be minus } int gAmountZ = generationAmountPerRadius - (int)prototype.meshInstancesGenerationOffset.y; if (gAmountZ == 0) { gAmountZ = 1; // dont clamp, it can be minus } for (int x = 0; x < gAmountX; x++) { for (int z = 0; z < gAmountZ; z++) { position = new Vector3(z * maxGenerationInstancesPerMesh, 0, x * maxGenerationInstancesPerMesh); meshGroup.AddMeshInstance(FoliageMeshInstance.CreateFoliageMesh(prototype, position, maxGenerationInstancesPerMesh)); } } return(meshGroup); }
public void OnDrawCamera(Camera camera) { if (!FoliageCore_MainManager.instance.enabled || prototypeMeshInstances == null) { return; } bool runCameraCheck = true; FoliageReceiver receiver = null; #if UNITY_EDITOR runCameraCheck = !UnityEditor.SceneView.GetAllSceneCameras().Contains(camera); #endif if (runCameraCheck) { if (FoliageReceiver.FReceivers.Count == 0) { return; } for (int i = 0; i < FoliageReceiver.FReceivers.Count; i++) { if (camera == FoliageReceiver.FReceivers[i].playerCamera) { receiver = FoliageReceiver.FReceivers[i]; break; } if (i == FoliageReceiver.FReceivers.Count - 1) { return; } } } if (receiver != null && !receiver.isGrassReceiver) { return; } int areaSizeIntegral = FoliageCore_MainManager.FOLIAGE_INSTANCE_AREA_SIZE; FoliageCore_Chunk[] targetedChunks = null; FoliageCore_Chunk currentMChunk; if (receiver == null) { targetedChunks = UNStandaloneUtility.GetFoliageChunksNeighbors(camera.transform.position - transform.position, targetedChunks); latestManagerChunk = targetedChunks[4]; } else { targetedChunks = receiver.neighbors; latestManagerChunk = receiver.middleFoliageChunkFromNeighbors; } Vector3 normalizedCameraPosition; FoliageManagerInstance mInstance; FoliageSector sector; FoliageChunk chunk; float density = FoliageCore_MainManager.instance.density; int instancesResolution = FoliageCore_MainManager.instance.instancesSectorResolution; #region PER_INSTANCE GPUMesh gpuInstance = null; FoliageChunk currentInstanceChunk; Vector3 pos; Material mat; int chunkIndex; FoliageMeshInstancesGroup meshGroup; FoliagePrototype prototype; int maxDensity; FoliageMeshInstance meshInstance; Vector3 chunkPos; int gpuMeshIndex = -1; Camera renderCamera = Application.isPlaying ? camera : null; List <FoliageChunk> chunks; Mesh targetMesh; Dictionary <int, GPUMesh> prototypeInstances; bool useQualitySettingsShadows = FoliageCore_MainManager.instance.useQualitySettingsShadowDistance; float shadowsDistance = FoliageCore_MainManager.instance.foliageShadowDistance; #endregion propertyBlock.SetVector("_StreamingAdjuster", UNStandaloneUtility.GetStreamingAdjuster()); if (receiver != null) { propertyBlock.SetFloat("_InteractionResolution", receiver.interactionMapResolutionIntegral); } for (int i = 0; i < targetedChunks.Length; i++) { currentMChunk = targetedChunks[i]; if (currentMChunk == null) { continue; } normalizedCameraPosition = camera.transform.position; if (!currentMChunk.InBounds(normalizedCameraPosition, 100) || !currentMChunk.isFoliageInstanceAttached) { continue; } mInstance = currentMChunk.GetOrCreateFoliageManagerInstance(); normalizedCameraPosition -= mInstance.transform.position; normalizedCameraPosition.x = Mathf.Clamp(normalizedCameraPosition.x, 0, areaSizeIntegral - 1); normalizedCameraPosition.z = Mathf.Clamp(normalizedCameraPosition.z, 0, areaSizeIntegral - 1); sector = mInstance.sector; chunks = sector.FoliageChunks; prototypeInstances = mInstance.meshInstances; chunk = sector.getChunk(normalizedCameraPosition) as FoliageChunk; if (chunk == null) { continue; } if (receiver != null) { propertyBlock.SetVector(PROPERTY_ID_FOLIAGE_INTERACTION_POSITION, chunk.position3D); } DEBUG_ResetValues(); mInstance.UpdateMaterialBlock(propertyBlock); for (int prototypeIndex = 0; prototypeIndex < FoliageDB.unSortedPrototypes.Count; prototypeIndex++) { prototype = FoliageDB.unSortedPrototypes[prototypeIndex]; if (!prototype.enabled) { continue; } int chunkOffset = FoliageMeshInstance.GENERATION_RANGE_OFFSET(prototype); int prototypeRadius = (int)prototype.FoliageGenerationRadius; propertyBlock.SetTexture(PROPERTY_ID_GRASSMAP, mInstance.grassMaps[prototype].map); //DEBUG _lastRenderedPrototypes++; try { gpuInstance = prototypeInstances[prototype.id]; } catch (System.Exception ex) { Debug.LogError(ex.ToString()); return; } try { mat = prototype.FoliageInstancedMeshData.mat; } catch { // if Foliage db was deleted/ a detail was removed... FoliageCore_MainManager.DestroyMeshInstance(prototype.id); OnDrawCamera(camera); return; } int xIndex; int zIndex; for (int x = 0; x < prototypeRadius; x++) { for (int z = 0; z < prototypeRadius; z++) { xIndex = chunk.x + (x - chunkOffset); zIndex = chunk.z + (z - chunkOffset); if (xIndex < 0 || zIndex < 0) { continue; } chunkIndex = xIndex + (zIndex * instancesResolution); if (chunkIndex >= chunks.Count) { continue; } currentInstanceChunk = chunks[chunkIndex]; if (currentInstanceChunk != null) { chunkPos = currentInstanceChunk.position3D; maxDensity = (int)(currentInstanceChunk.GetMaxDensityOnArea(prototype.id) * density); gpuMeshIndex = gpuInstance.GetMesh(maxDensity); if (gpuMeshIndex != -1) { //meshGroup = gpuInstance.LODMeshInstances[x, z, gpuMeshIndex]; meshGroup = gpuInstance.LODMeshInstances[gpuMeshIndex]; targetMesh = gpuInstance.meshes[gpuMeshIndex].mesh; for (int j = 0; j < meshGroup.Count; j++) { meshInstance = meshGroup[j]; pos = meshInstance.GetPosition(chunkPos); if (pos.x < 0 || pos.z < 0 || pos.x >= areaSizeIntegral || pos.z >= areaSizeIntegral) { continue; } propertyBlock.SetVector(PROPERTY_ID_WORLDPOSITION, pos); //DEBUG _lastRenderedVertices += targetMesh.vertexCount; //DEBUG _lastRenderedDrawCalls++; meshInstance.DrawAndUpdate(pos, targetMesh, mat, renderCamera, normalizedCameraPosition, prototype, propertyBlock, useQualitySettingsShadows, shadowsDistance); } } } } } } } }
public void AddMeshInstance(FoliageMeshInstance instance) { meshInstances.Add(instance); count = meshInstances.Count; }