void NewGrowDirectionFalling(BranchContainer branch) { Vector3 newGrowDirection = Vector3.Lerp(branch.growDirection, infoPool.ivyParameters.gravity, branch.fallIteration / 10f); newGrowDirection = Quaternion.AngleAxis(Mathf.Sin(branch.branchSense * branch.totalLenght * infoPool.ivyParameters.directionFrequency * (1 + Random.Range(-infoPool.ivyParameters.directionRandomness / 8f, infoPool.ivyParameters.directionRandomness / 8f))) * infoPool.ivyParameters.directionAmplitude * infoPool.ivyParameters.stepSize * 5f * Mathf.Max(infoPool.ivyParameters.directionRandomness / 8f, 1f), branch.GetLastBranchPoint().grabVector) * newGrowDirection; newGrowDirection = Quaternion.AngleAxis(Mathf.Sin(branch.branchSense * branch.totalLenght * infoPool.ivyParameters.directionFrequency / 2f * (1 + Random.Range(-infoPool.ivyParameters.directionRandomness / 8f, infoPool.ivyParameters.directionRandomness / 8f))) * infoPool.ivyParameters.directionAmplitude * infoPool.ivyParameters.stepSize * 5f * Mathf.Max(infoPool.ivyParameters.directionRandomness / 8f, 1f), Vector3.Cross(branch.GetLastBranchPoint().grabVector, branch.growDirection)) * newGrowDirection; branch.rotationOnFallIteration = Quaternion.FromToRotation(branch.growDirection, newGrowDirection); branch.growDirection = newGrowDirection; }
//Añadimos punto y todo lo que ello conlleva. Es ligeramente diferente a AddPoint. Está la posibilidad de spawnear una rama void AddFallingPoint(BranchContainer branch) { Vector3 grabVector = branch.rotationOnFallIteration * branch.GetLastBranchPoint().grabVector; branch.totalLenght += infoPool.ivyParameters.stepSize; branch.AddBranchPoint(branch.branchPoints[branch.branchPoints.Count - 1].point + branch.growDirection * infoPool.ivyParameters.stepSize, grabVector); if (Random.value < infoPool.ivyParameters.branchProvability && infoPool.ivyContainer.branches.Count < infoPool.ivyParameters.maxBranchs) { AddBranch(branch, branch.GetLastBranchPoint(), branch.branchPoints[branch.branchPoints.Count - 1].point, -branch.GetLastBranchPoint().grabVector); } AddLeave(branch); }
//Cálculos de nuevas growdirection en diferentes casuísticas void NewGrowDirection(BranchContainer branch) { branch.growDirection = Vector3.Normalize(Vector3.ProjectOnPlane(Quaternion.AngleAxis(Mathf.Sin(branch.branchSense * branch.totalLenght * infoPool.ivyParameters.directionFrequency * (1 + Random.Range(-infoPool.ivyParameters.directionRandomness, infoPool.ivyParameters.directionRandomness))) * infoPool.ivyParameters.directionAmplitude * infoPool.ivyParameters.stepSize * 10f * Mathf.Max(infoPool.ivyParameters.directionRandomness, 1f), branch.GetLastBranchPoint().grabVector) * branch.growDirection, branch.GetLastBranchPoint().grabVector)); }
//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(BranchContainer branch) { BranchPoint checkPoint = new BranchPoint( branch.GetLastBranchPoint().point + branch.growDirection * infoPool.ivyParameters.stepSize + branch.GetLastBranchPoint().grabVector *branch.deltaHeight, branch.branchPoints.Count, 0f, branch); 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, infoPool.ivyParameters.stepSize * 1.15f, infoPool.ivyParameters.layerMask.value)) { CheckFloor(branch, checkPoint, -branch.GetLastBranchPoint().grabVector); } else { NewGrowDirectionAfterWall(branch, -branch.GetLastBranchPoint().grabVector, RC.normal); AddPoint(branch, RC.point, RC.normal); } }
/*public void AddDrawingPoint(BranchContainer branch, Vector3 point, Vector3 normal, Vector3 paintDir) * { * //Vector3 dir = branch.branchPoints[branch.branchPoints.Count - 1].point - branch.branchPoints[branch.branchPoints.Count - 2].point; * //dir = dir.normalized; * * branch.AddBranchPoint(point + normal * branch.currentHeight, -normal); * * * branch.totalLenght += infoPool.ivyParameters.stepSize; * * branch.GetLastBranchPoint().length = branch.totalLenght; * branch.lenghts.Add(branch.totalLenght); * * AddLeave(branch); * }*/ //Añadimos punto y todo lo que ello conlleva. Está la posibilidad de spawnear una rama public void AddPoint(BranchContainer branch, Vector3 point, Vector3 normal) { branch.totalLenght += infoPool.ivyParameters.stepSize; branch.heightParameter += infoPool.ivyParameters.stepSize; branch.AddBranchPoint(point + normal * branch.currentHeight, -normal); //Con este if lo que comprobamos realmente es si estamos en modo procedural o en modo pintado if (growing) { if (Random.value < infoPool.ivyParameters.branchProvability && infoPool.ivyContainer.branches.Count < infoPool.ivyParameters.maxBranchs) { AddBranch(branch, branch.GetLastBranchPoint(), branch.branchPoints[branch.branchPoints.Count - 1].point, normal); } } AddLeave(branch); }
//Todo lo necesario para añadir una nueva hoja void AddLeave(BranchContainer branch) { if (branch.branchPoints.Count % (infoPool.ivyParameters.leaveEvery + Random.Range(0, infoPool.ivyParameters.randomLeaveEvery)) == 0) { /*BORRAR*/ //branch.branchPoints[branch.branchPoints.Count - 1].AddCurrentPointAsLeafPoint(); //branch.branchPoints[branch.branchPoints.Count - 1].AddLPLength(branch.totalLenght); //branch.branchPoints[branch.branchPoints.Count - 1].AddLPForward(branch.growDirection); //branch.branchPoints[branch.branchPoints.Count - 1].AddLPUpward(-branch.grabVectors[branch.grabVectors.Count - 1]); float[] probabilities = new float[infoPool.ivyParameters.leavesPrefabs.Length]; int chosenLeave = 0; float max = 0f; for (int i = 0; i < probabilities.Length; i++) { probabilities [i] = Random.Range(0f, infoPool.ivyParameters.leavesProb [i]); } for (int i = 0; i < probabilities.Length; i++) { if (probabilities [i] >= max) { max = probabilities [i]; chosenLeave = i; } } /*BORRAR*/ //branch.branchPoints[branch.branchPoints.Count - 1].AddLPType(chosenLeave); BranchPoint initSegment = branch.branchPoints[branch.branchPoints.Count - 2]; BranchPoint endSegment = branch.branchPoints[branch.branchPoints.Count - 1]; Vector3 leafPoint = Vector3.Lerp(initSegment.point, endSegment.point, 0.5f); branch.AddLeaf(leafPoint, branch.totalLenght, branch.growDirection, -branch.GetLastBranchPoint().grabVector, chosenLeave, initSegment, endSegment); } }
void NewGrowDirectionAfterFall(BranchContainer 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(BranchContainer 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 * infoPool.ivyParameters.stepSize, Quaternion.AngleAxis(angle, branch.growDirection) * branch.GetLastBranchPoint().grabVector); RaycastHit RC; if (Physics.Raycast(ray, out RC, infoPool.ivyParameters.stepSize * 2f, infoPool.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 - infoPool.ivyParameters.stiffness; branch.falling = true; } } }