void NewGrowDirectionFalling(RTBranchContainer branch) { Vector3 newGrowDirection = Vector3.Lerp(branch.growDirection, ivyParameters.gravity, branch.fallIteration / 10f); newGrowDirection = Quaternion.AngleAxis(Mathf.Sin(branch.branchSense * branch.totalLength * ivyParameters.directionFrequency * (1 + Random.Range(-ivyParameters.directionRandomness / 8f, ivyParameters.directionRandomness / 8f))) * ivyParameters.directionAmplitude * ivyParameters.stepSize * 5f * Mathf.Max(ivyParameters.directionRandomness / 8f, 1f), branch.GetLastBranchPoint().grabVector) * newGrowDirection; newGrowDirection = Quaternion.AngleAxis(Mathf.Sin(branch.branchSense * branch.totalLength * ivyParameters.directionFrequency / 2f * (1 + Random.Range(-ivyParameters.directionRandomness / 8f, ivyParameters.directionRandomness / 8f))) * ivyParameters.directionAmplitude * ivyParameters.stepSize * 5f * Mathf.Max(ivyParameters.directionRandomness / 8f, 1f), Vector3.Cross(branch.GetLastBranchPoint().grabVector, branch.growDirection)) * newGrowDirection; branch.rotationOnFallIteration = Quaternion.FromToRotation(branch.growDirection, newGrowDirection); branch.growDirection = newGrowDirection; }
//Cálculos de nuevas growdirection en diferentes casuísticas void NewGrowDirection(RTBranchContainer branch) { branch.growDirection = Vector3.Normalize(Vector3.ProjectOnPlane(Quaternion.AngleAxis(Mathf.Sin(branch.branchSense * branch.totalLength * ivyParameters.directionFrequency * (1 + Random.Range(-ivyParameters.directionRandomness, ivyParameters.directionRandomness))) * ivyParameters.directionAmplitude * ivyParameters.stepSize * 10f * Mathf.Max(ivyParameters.directionRandomness, 1f), branch.GetLastBranchPoint().grabVector) * branch.growDirection, branch.GetLastBranchPoint().grabVector)); }
//Añadimos punto y todo lo que ello conlleva. Está la posibilidad de spawnear una rama public void AddPoint(RTBranchContainer branch, Vector3 point, Vector3 normal) { branch.totalLength += ivyParameters.stepSize; RTBranchPoint branchPoint = GetNextFreeBranchPoint(); branchPoint.SetValues(point + normal * branch.currentHeight, -normal); branch.AddBranchPoint(branchPoint, ivyParameters.stepSize); CalculateVerticesLastPoint(branch); //Vector3 axis = GetLoopAxis(branchPoint, branch, rtIvyContainer, ivyGO); //Vector3 firstVector = GetFirstVector(branchPoint, branch, rtIvyContainer, ivyParameters, axis); //branchPoint.CalculateCenterLoop(ivyGO); //branchPoint.CalculateVerticesLoop(ivyParameters, rtIvyContainer, ivyGO, firstVector, axis); /*if(branch.branchPoints.Count >= 1) * { * branch.branchPoints[branch.branchPoints.Count - 2].CalculateVerticesLoop(ivyParameters, rtIvyContainer, ivyGO); * }*/ if (Random.value < ivyParameters.branchProvability && rtIvyContainer.branches.Count < ivyParameters.maxBranchs) { AddBranch(branch, branch.GetLastBranchPoint(), branch.branchPoints[branch.branchPoints.Count - 1].point, normal); } if (ivyParameters.generateLeaves) { AddLeave(branch); } }
protected virtual void AddNextBranch(int branchNumber) { lastIdxActiveBranch++; RTBranchContainer newBuildingBranch = activeBuildingBranches[lastIdxActiveBranch]; RTBranchContainer bakedBranch = rtIvyContainer.GetBranchContainerByBranchNumber(branchNumber); newBuildingBranch.AddBranchPoint(bakedBranch.branchPoints[0], ivyParameters.stepSize); newBuildingBranch.AddBranchPoint(bakedBranch.branchPoints[1], ivyParameters.stepSize); newBuildingBranch.leavesOrderedByInitSegment = bakedBranch.leavesOrderedByInitSegment; rtBuildingIvyContainer.AddBranch(newBuildingBranch); activeBakedBranches.Add(bakedBranch); activeBuildingBranches.Add(newBuildingBranch); meshBuilder.activeBranches.Add(newBuildingBranch); UpdateGrowingPoints(rtBuildingIvyContainer.branches.Count - 1); RTBranchPoint lastBranchPoint = newBuildingBranch.GetLastBranchPoint(); if (lastBranchPoint.newBranch) { AddNextBranch(lastBranchPoint.newBranchNumber); } }
protected virtual void Growing(int branchIndex, float deltaTime) { RTBranchContainer currentBranch = activeBuildingBranches[branchIndex]; CalculateFactors(srcPoints[branchIndex], dstPoints[branchIndex]); meshBuilder.SetLeafLengthCorrectionFactor(leafLengthCorrrectionFactor); growingFactorPerBranch[branchIndex] += currentSpeed * deltaTime; growingFactorPerBranch[branchIndex] = Mathf.Clamp(growingFactorPerBranch[branchIndex], 0f, 1f); currentBranch.totalLength = Mathf.Lerp(srcTotalLengthPerBranch[branchIndex], dstTotalLengthPerBranch[branchIndex], growingFactorPerBranch[branchIndex]); RTBranchPoint lastPoint = currentBranch.GetLastBranchPoint(); lastPoint.length = currentBranch.totalLength; lastPoint.point = Vector3.Lerp(srcPoints[branchIndex], dstPoints[branchIndex], growingFactorPerBranch[branchIndex]); if (growingFactorPerBranch[branchIndex] >= 1) { RefreshGeometry(); NextPoints(branchIndex); } }
//Añadimos punto y todo lo que ello conlleva. Es ligeramente diferente a AddPoint. Está la posibilidad de spawnear una rama void AddFallingPoint(RTBranchContainer branch) { Vector3 grabVector = branch.rotationOnFallIteration * branch.GetLastBranchPoint().grabVector; RTBranchPoint branchPoint = GetNextFreeBranchPoint(); branchPoint.point = branch.branchPoints[branch.branchPoints.Count - 1].point + branch.growDirection * ivyParameters.stepSize; branchPoint.grabVector = grabVector; branch.AddBranchPoint(branchPoint, ivyParameters.stepSize); CalculateVerticesLastPoint(branch); //Vector3 axis = GetLoopAxis(branchPoint, branch, rtIvyContainer, ivyGO); //Vector3 firstVector = GetFirstVector(branchPoint, branch, rtIvyContainer, ivyParameters, axis); //branchPoint.CalculateCenterLoop(ivyGO); //branchPoint.CalculateVerticesLoop(ivyParameters, rtIvyContainer, ivyGO, firstVector, axis); /*if (branch.branchPoints.Count >= 1) * { * branch.branchPoints[branch.branchPoints.Count - 2].CalculateVerticesLoop(ivyParameters, rtIvyContainer, ivyGO); * }*/ if (Random.value < ivyParameters.branchProvability && rtIvyContainer.branches.Count < ivyParameters.maxBranchs) { AddBranch(branch, branch.GetLastBranchPoint(), branch.branchPoints[branch.branchPoints.Count - 1].point, -branch.GetLastBranchPoint().grabVector); } if (ivyParameters.generateLeaves) { AddLeave(branch); } }
//Definimos el punto a checkear y la dirección a él. Tiramos un raycast y si está libre buscamos el suelo. Si por el contrario topamos con un muro, añadimos un punto y calculamos una nueva growdirection void CheckWall(RTBranchContainer branch) { RTBranchPoint checkPoint = GetNextFreeBranchPoint(); checkPoint.point = branch.GetLastBranchPoint().point + branch.growDirection * ivyParameters.stepSize + branch.GetLastBranchPoint().grabVector *branch.deltaHeight; checkPoint.index = branch.branchPoints.Count; //checkPoint.length = 0f; Vector3 direction = checkPoint.point - branch.GetLastBranchPoint().point; Ray ray = new Ray(branch.branchPoints[branch.branchPoints.Count - 1].point, direction); RaycastHit RC; if (!Physics.Raycast(ray, out RC, ivyParameters.stepSize * 1.15f, ivyParameters.layerMask.value)) { CheckFloor(branch, checkPoint, -branch.GetLastBranchPoint().grabVector); } else { NewGrowDirectionAfterWall(branch, -branch.GetLastBranchPoint().grabVector, RC.normal); AddPoint(branch, RC.point, RC.normal); } }
//Todo lo necesario para añadir una nueva hoja void AddLeave(RTBranchContainer branch) { if (branch.branchPoints.Count % (ivyParameters.leaveEvery + Random.Range(0, ivyParameters.randomLeaveEvery)) == 0) { int chosenLeaf = Random.Range(0, ivyParameters.leavesPrefabs.Length); RTBranchPoint initSegment = branch.branchPoints[branch.branchPoints.Count - 2]; RTBranchPoint endSegment = branch.branchPoints[branch.branchPoints.Count - 1]; Vector3 leafPoint = Vector3.Lerp(initSegment.point, endSegment.point, 0.5f); float leafScale = Random.Range(ivyParameters.minScale, ivyParameters.maxScale); RTLeafPoint leafAdded = GetNextLeafPoint(); leafAdded.SetValues(leafPoint, branch.totalLength, branch.growDirection, -branch.GetLastBranchPoint().grabVector, chosenLeaf, initSegment, endSegment, leafScale, ivyParameters); RTMeshData leafMeshData = leavesMeshesByChosenLeaf[leafAdded.chosenLeave]; leafAdded.CreateVertices(ivyParameters, leafMeshData, ivyGO); branch.AddLeaf(leafAdded); } }
void NewGrowDirectionAfterFall(RTBranchContainer branch, Vector3 newSurfaceNormal) { branch.growDirection = Vector3.Normalize(Vector3.ProjectOnPlane(-branch.GetLastBranchPoint().grabVector, newSurfaceNormal)); }
//Con esto tiramos rayos alrededor del último punto buscando una superficie donde agarrarnos. void CheckGrabPoint(RTBranchContainer branch) { for (int i = 0; i < 6; i++) { float angle = (Mathf.Rad2Deg * 2 * Mathf.PI / 6) * i; Ray ray = new Ray(branch.branchPoints[branch.branchPoints.Count - 1].point + branch.growDirection * ivyParameters.stepSize, Quaternion.AngleAxis(angle, branch.growDirection) * branch.GetLastBranchPoint().grabVector); RaycastHit RC; if (Physics.Raycast(ray, out RC, ivyParameters.stepSize * 2f, ivyParameters.layerMask.value)) { AddPoint(branch, RC.point, RC.normal); NewGrowDirectionAfterGrab(branch, RC.normal); branch.fallIteration = 0f; branch.falling = false; break; } else if (i == 5) { AddFallingPoint(branch); NewGrowDirectionFalling(branch); branch.fallIteration += 1f - ivyParameters.stiffness; branch.falling = true; } } }