private LeafPoint GetNextLeaf(LeafInfo leafInfo) { LeafPoint res = null; float length = overSegment[0].length + Vector3.Distance(leafInfo.pointWS, overSegment[0].point); for (int i = 0; i < overBranch.leaves.Count; i++) { if (res == null) { res = overBranch.leaves[i]; } else if (overBranch.leaves[i].lpLength < length) { res = overBranch.leaves[i]; } else { res = overBranch.leaves[i]; break; } } return(res); }
// Expects the leaves to be sorted. void _PartitionMajorMinorLeaves(List <LeafInfo> leaves) { int chunkymax = 0; int iMajorPartitionSize = leaves.Count / (int)majorcount; iMajorPartitionSize++; int majorremain = leaves.Count % (int)majorcount; int iMinorPartitionSize = leaves.Count / (int)(majorcount * minorcount); iMinorPartitionSize++; int minorremain = leaves.Count % (int)(majorcount * minorcount); if (iMinorPartitionSize <= 0) { iMinorPartitionSize = 1; } if (iMajorPartitionSize <= 0) { iMajorPartitionSize = 1; } short cur_Major_id = 0; for (int i = 0; i < leaves.Count;) { int chunkcurr = 0; short cur_Minor_id = 0; int j; for (j = i; j < i + iMajorPartitionSize && j < leaves.Count;) { int k; for (k = j; k < j + iMinorPartitionSize && k < leaves.Count && k < i + iMajorPartitionSize; k++) { LeafInfo pRangeItem = leaves[k]; data[pRangeItem.leaf_noffset].children_noffset = LEAF_BIT | ((uint)cur_Major_id * (uint)minorcount + (uint)cur_Minor_id); leaves[k] = pRangeItem; } j = k; if (cur_Minor_id < minorcount - 1) { ++cur_Minor_id; } else { ++chunkcurr; } } if (chunkcurr > chunkymax) { chunkymax = chunkcurr; } i = j; if (cur_Major_id < majorcount - 1) { ++cur_Major_id; } } }
private static int SolveSmall(string s, int offset, int failAllowed, LeafInfo processingLeaf) { var key = Tuple.Create(s, offset, failAllowed, processingLeaf); if (!Cache.ContainsKey(key)) { Cache[key] = DoSolveSmall(s, offset, failAllowed, processingLeaf); } return(Cache[key]); }
private void AddLeaf(LeafInfo leafInfo) { BranchPoint branchPoint = overBranch.GetNearestPointFrom(mousePoint); LeafPoint nextLeaf = GetNextLeaf(leafInfo); int leafIndex = overBranch.leaves.IndexOf(nextLeaf); lastLeafPoint = overBranch.AddRandomLeaf(leafInfo.pointWS, overSegment[0], overSegment[1], leafIndex, infoPool); RefreshMesh(true, true); }
public void AddWord(string word, int offset) { if (!Leaves.ContainsKey(word[offset])) { Leaves[word[offset]] = new LeafInfo(); } if (offset + 1 < word.Length) { Leaves[word[offset]].Branch.AddWord(word, offset + 1); } else { Leaves[word[offset]].IsTerminal = true; } }
private LeafInfo GetLeafPosition(Event currentEvent, float brushSize) { BranchPoint[] nearestSegment = infoPool.ivyContainer.GetNearestSegmentSS(currentEvent.mousePosition); Vector2 segmentDir = (nearestSegment[1].pointSS - nearestSegment[0].pointSS); Vector2 initSegmentToMousePoint = (currentEvent.mousePosition - nearestSegment[0].pointSS); Vector2 initToMouse = currentEvent.mousePosition - nearestSegment[0].pointSS; float distanceMouseToFirstPoint = initToMouse.magnitude; float t = distanceMouseToFirstPoint / segmentDir.magnitude; Vector2 leafPositionSS = Vector2.Lerp(nearestSegment[0].pointSS, nearestSegment[1].pointSS, distanceMouseToFirstPoint / segmentDir.magnitude); Vector3 leafPositionWS = Vector3.Lerp(nearestSegment[0].point, nearestSegment[1].point, t); LeafInfo res = new LeafInfo(leafPositionSS, leafPositionWS, t); return(res); }
public void UpdateMode(Event currentEvent, Rect forbiddenRect, float brushSize) { GetBranchesPointsSS(); SelectBranchPointSS(currentEvent.mousePosition, brushSize); if (toolPaintingAllowed) { DrawBrush(currentEvent, brushSize); if (overBranch != null) { Handles.BeginGUI(); RefreshBrushDistance(); RefreshBrushWS(currentEvent); mousePoint = brushWS; LeafInfo leafInfo = GetLeafPosition(currentEvent, brushSize); DrawLeafPointSS(leafInfo); if (currentEvent.button == 0) { if (currentEvent.type == EventType.MouseDown) { SaveIvy(); AddLeaf(leafInfo); } else if (currentEvent.type == EventType.MouseDrag) { float sqrDistanceToLastLeaf = (leafInfo.pointWS - lastLeafPoint.point).sqrMagnitude; if (sqrDistanceToLastLeaf > 0.025f) { AddLeaf(leafInfo); } } } } SceneView.RepaintAll(); } Handles.EndGUI(); }
//USED TO FIRST GENERATE THE LEAVES ON THE PLANT public void GenerateLeavesAndFLowers() { GeneratePoints(1f, points); actualLeavesNumber = 0; Vector3 randomVector = new Vector3(0.132354f, 1.98654f, -1.5646f).normalized; //CREATE THE PARENT OF ALL LEAVES if (leavesParent != null) { DestroyImmediate(leavesParent.gameObject); } leavesParent = new GameObject("LeaveParent").transform; leavesParent.parent = transform; leavesParent.transform.localPosition = Vector3.zero; int leavesIteration = 0; if (leavesRepartitionMode == LeavesRepartitionMode.Density) { leavesIteration = (int)(leavesDensity * totalLength); } else if (leavesRepartitionMode == LeavesRepartitionMode.Number) { leavesIteration = leavesNumber; } if (uniqueEndFlower) { leavesIteration += 1; } leaves = new LeafInfo[leavesIteration]; int iteration = 0; while (iteration < leavesIteration) { float lengthRatio = Random.value; float proba = leavesDistribution.Evaluate(lengthRatio); if (uniqueEndFlower && iteration == 0) { lengthRatio = 0.99f; proba = 2f; } if (Random.value < proba) { //POSITION int segment = (int)(lengthRatio * nbOfSegments); float lerpValue = (lengthRatio - (segment / (float)nbOfSegments)) * nbOfSegments; float value = Random.value; //POINT AND OPPOSED POINT int pointIndex1 = nbOfSides * segment + (int)(value * nbOfSides); int pointIndex2 = nbOfSides * segment + (int)((value + 0.5f > 1f ? value - 0.5f : value + 0.5f) * nbOfSides); // INTERPOLATION BETWEEN SEGMENTS Vector3 position = Vector3.zero; if (uniqueEndFlower && iteration == 0) { position = mf.sharedMesh.vertices [mf.sharedMesh.vertices.Length - 1]; } else { if (branchesOnlyOnSections) { position = mf.sharedMesh.vertices [pointIndex1]; } else { position = (1f - lerpValue) * mf.sharedMesh.vertices [pointIndex1] + lerpValue * mf.sharedMesh.vertices [pointIndex1 + nbOfSides]; } } //INITIAL DIRECTION Vector3 direction = mf.sharedMesh.normals[pointIndex1] - mf.sharedMesh.normals[pointIndex2]; //TANGEANT DIRECTION Vector3 tangentDirection = mf.sharedMesh.vertices [pointIndex1] - mf.sharedMesh.vertices [pointIndex1 + nbOfSides]; //ORIENTATION TOWARD THE SUN Vector3 up = (1f - sunOrientationIntensity) * tangentDirection.normalized + sunOrientationIntensity * Vector3.up * sunOrientationIntensityOverTime.Evaluate(time); direction.y *= sunOrientationIntensity * sunOrientationIntensityOverTime.Evaluate(time); if (uniqueEndFlower && iteration == 0) { int last = positionsAndNormals.pos.Length - 1; direction = positionsAndNormals.pos[last] - positionsAndNormals.pos[last - 1]; } direction.Normalize(); GameObject thing; bool isFlower = hasFlowers && ((uniqueEndFlower && iteration == 0) || (Random.value < leafChanceOfBeingFlower && !uniqueEndFlower)); //Debug.Log ("Is Leaf ? : " + !isFlower); float birthDate = 0f; float growthDuration = 0f; if (!isFlower) { //LEAF CREATION Leaf leaf = Instantiate(leafPrefab, position, Quaternion.identity); thing = leaf.gameObject; leaf.name = "Leaf_" + actualLeavesNumber.ToString(); leaf.initialDirection = direction; leaf.upDirection = up; growthDuration = leafGrowthDuration.RandomValue(); //Debug.Log (leafGrowthDuration.min + " " + leafGrowthDuration.max); //Debug.Log ("Leaf growthDuration = " + growthDuration); birthDate = Mathf.Lerp(ValueAt(trunkTimeOverTime, lengthRatio) * maxDuration, maxDuration - growthDuration, leavesBirthdateDistribution.Evaluate(Random.value)); leaf.transform.localScale *= leafSize.RandomValue(); leaf.time = 0f; } else { Flower flower = Instantiate(flowerPrefab, position, Quaternion.identity); thing = flower.gameObject; growthDuration = flowerGrowthDuration.RandomValue(); flower.name = "Flower_" + actualLeavesNumber.ToString(); if (!hasFixedDirection) { flower.initialDirection = direction; } //Debug.Log ("at time " + time + " : " + (Trunk.fruitSequence & (1 << Trunk.placedFruits))); if (hasFruits) { if (( Trunk.time == 0f && (Trunk.fruitRepartitionMode == LeavesRepartitionMode.Number && Trunk.placedFruits < Trunk.fruitNumber) || (Trunk.fruitRepartitionMode == LeavesRepartitionMode.Density && Random.value < Trunk.fruttiFlowersRatio)) || ((Trunk.fruitSequence & (1 << Trunk.placedFruits)) > 0)) { //Debug.Log ("j'arrive ICI"); Fruit fruit = (Fruit)Instantiate(fruitPrefab, flower.transform); fruit.transform.localPosition = Vector3.zero; fruit.initialDirection = flower.initialDirection; float sizeMult = fruitSize.RandomValue(); fruit.length *= sizeMult; fruit.radius *= sizeMult; flower.fruitGrowthDuration = fruitGrowthDuration.RandomValue(); flower.hasAFruit = true; flower.fruit = fruit; fruit.fruitIndex = Trunk.placedFruits; fruit.indexInPlantManager = Trunk.plantTypeIndex; growthDuration += flower.fruitGrowthDuration; //Debug.Log ("je met un fruit " + Trunk.placedFruits + "/" + Trunk.fruitNumber); if (time == 0f) { Trunk.fruitSequence = Trunk.fruitSequence | (1 << Trunk.placedFruits); } Trunk.placedFruits++; } else { Trunk.placedFruits++; } } flower.thisGrowthDuration = growthDuration; //flower.upDirection = up; birthDate = Mathf.Lerp(ValueAt(trunkTimeOverTime, lengthRatio) * maxDuration, maxDuration - growthDuration, flowersBirthdateDistribution.Evaluate(Random.value)); flower.transform.localScale *= flowerSize.RandomValue() * flowerSizeOverLength.Evaluate(lengthRatio); flower.time = 0f; flower.SetPlantRoot(Trunk); } thing.transform.parent = leavesParent; //Debug.Log ("growthDuration = " + growthDuration); LeafInfo l = new LeafInfo(uniqueEndFlower && iteration == 0, !isFlower, thing, lengthRatio, direction, pointIndex1, pointIndex2, lerpValue, birthDate, growthDuration); leaves [actualLeavesNumber] = l; //INCREMENTS actualLeavesNumber++; } iteration++; } }
//USED TO UPDATE THE LEAVES EVERY FRAME public void UpdateLeavesAndFlowers() { float absolutTime = time * maxDuration; for (int i = 0; i < actualLeavesNumber; i++) { //DISTANCE FROM ROOT / LENGTH LeafInfo thing = leaves [i]; if (thing.birthDate > absolutTime) { //NOT GROWN if (thing.isLeafOrFlower) { thing.leaf.time = 0f; } else { thing.flower.time = 0f; } } else { if (absolutTime - thing.birthDate < thing.growthDuration || !thing.grownOnce) { float localTime = 0f; if (thing.isLeafOrFlower) { localTime = Mathf.Min(1f, leafGrowthOverTime.Evaluate((absolutTime - thing.birthDate) / thing.growthDuration)); //Debug.Log (absolutTime + " " + thing.birthDate + " " + thing.growthDuration); //Debug.Log (localTime); thing.leaf.time = leafGrowthOverTime.Evaluate(localTime); } else { //Debug.Log (absolutTime + " " + thing.birthDate + " " + thing.growthDuration); localTime = Mathf.Min(1f, flowerGrowthOverTime.Evaluate((absolutTime - thing.birthDate) / thing.growthDuration)); //Debug.Log (localTime); thing.flower.time = flowerGrowthOverTime.Evaluate(localTime); } //Debug.Log ("growth duration : " + thing.growthDuration); //INTIAL DIRECTION Vector3 initialDirection = (mf.sharedMesh.vertices [thing.pointIndex1] - mf.sharedMesh.vertices [thing.pointIndex2]).normalized; initialDirection.y = Mathf.Lerp(initialDirection.y, 1f - sunOrientationIntensity, sunOrientationIntensityOverTime.Evaluate(localTime)); //TANGENT DIRECTION Vector3 tangentDirection = mf.sharedMesh.vertices [thing.pointIndex1] - mf.sharedMesh.vertices [thing.pointIndex1 + nbOfSides]; //UP DIRECTION Vector3 up = Vector3.Lerp(tangentDirection.normalized, Vector3.up * sunOrientationIntensityOverTime.Evaluate(localTime), sunOrientationIntensity); Vector3 localPosition = Vector3.Lerp(mf.sharedMesh.vertices [thing.pointIndex1], mf.sharedMesh.vertices [thing.pointIndex1 + nbOfSides], thing.lerpValue); if (thing.isLeafOrFlower) { thing.leaf.initialDirection = initialDirection.normalized; thing.leaf.transform.localPosition = localPosition; thing.leaf.upDirection = up.normalized; thing.leaf.UpdateMesh(); } else { if (!thing.isEndFlower && !hasFixedDirection) { thing.flower.initialDirection = initialDirection.normalized; if (thing.flower.hasAFruit) { thing.flower.fruit.initialDirection = thing.flower.initialDirection; } } thing.flower.transform.localPosition = localPosition; //thing.flower.upDirection = up.normalized; thing.flower.UpdateMesh(); } thing.grownOnce = true; } } } }
private void DrawLeafPointSS(LeafInfo leafInfo) { EditorGUI.DrawRect(new Rect(leafInfo.pointSS - Vector2.one * 2f, Vector2.one * 4f), Color.red); }
private static int DoSolveSmall(string s, int offset, int failAllowed, LeafInfo processingLeaf) { if (s.Length == offset) { if (processingLeaf.IsTerminal) { return(0); } else { return(-1); } } //Console.WriteLine("SolveSmall({0}, {1}, {2})", s, offset, failAllowed); int result = -1; foreach (var candidate in Candidates(s, offset, failAllowed, processingLeaf)) { if (candidate < 0) { continue; } if (result < 0 || candidate < result) { result = candidate; } if (result == 0) { return(result); } } return(result); /*if(processingBranch.Leaves.ContainsKey(ch)) { * foreach(var subBranch in processingBranch.Branches[ch]) { * var candidate = SolveSmall(s, offset+1, failAllowed, subBranch); * if (candidate == null) { * continue; * } * if(result == null || candidate.Item1 < result.Item1) { * result = Tuple.Create(candidate.Item1, ch + candidate.Item2); * } * } * } * * if(failAllowed <= offset) { * foreach(var kvp in processingBranch.Branches) { * if(kvp.Key == ch) { * continue; * } * * foreach(var subBranch in kvp.Value) { * var candidate = SolveSmall(s, offset+1, offset+5, subBranch); * if (candidate == null) { * continue; * } * if(result == null || candidate.Item1+1 < result.Item1) { * result = Tuple.Create(candidate.Item1+1, kvp.Key + candidate.Item2); * } * } * } * } * * return result;*/ /*foreach(var word in words) { * if(word.Length+offset > s.Length) { * continue; * } * * int actualFailAllowed = failAllowed; * bool fit = true; * int mistypes = 0; * for(int i=0; i<word.Length; i++) { * if(word[i] != s[offset+i]) { * if(offset+i < actualFailAllowed) { * fit = false; * } else { * actualFailAllowed = offset+i+5; * mistypes++; * } * } * } * * if(fit) { * var branch = SolveSmall(s, offset + word.Length, actualFailAllowed); * if(branch != null) { * if(result == null || result.Item1 > branch.Item1) { * result = Tuple.Create(mistypes+branch.Item1, word + " " + branch.Item2); * } * } * } * } * * return result;*/ }
private static IEnumerable <int> Candidates(string s, int offset, int failAllowed, LeafInfo processingLeaf) { char ch = s[offset]; var processingBranch = processingLeaf.Branch; if (processingBranch.Leaves.ContainsKey(ch)) { var resultA = SolveSmall(s, offset + 1, failAllowed, processingBranch.Leaves[ch]); if (resultA >= 0) { yield return(resultA); } } if (processingLeaf.IsTerminal) { if (Tree.Leaves.ContainsKey(ch)) { var resultB = SolveSmall(s, offset + 1, failAllowed, Tree.Leaves[ch]); if (resultB >= 0) { yield return(resultB); } } } if (failAllowed <= offset) { var newFailAllowed = offset + 5; var branches = processingBranch.Leaves.AsEnumerable(); if (processingLeaf.IsTerminal) { branches = branches.Concat(Tree.Leaves); } foreach (var kvp in branches) { if (kvp.Key == ch) { continue; } var resultC = SolveSmall(s, offset + 1, newFailAllowed, kvp.Value); if (resultC >= 0) { yield return(1 + resultC); } } } }