- Home /
Problem with Windswept Procedural tree
I am new to Unity and trying my first project. In the project I need a specific type of windswept tree that players climb so I want the tree as realistic as possible. The Unity-generated tree produces square branches for the smaller ones. I wanted something more realistic. I grabbed "Procedural Tree" (https://www.assetstore.unity3d.com/en/#!/content/32907) from the asset store. It makes nice trees, round branches,... but not windswept. I went into the code and tried to modify the rotations to preferentially have the limbs bend in a specific world direction. I can't seem to get the rotations correct. I can bend the branches but the orthogonal rings don't rotate (the branches turn inside out) or I can bend them in the local system and get corkscrew trees - interesting but not what I need. I have never worked with quaternions so that it where I am messed up.
It is clear that my use of transform.InverseTransformDirection is incorrect. I have tried it using quaternions instead of vector components, rotating the quaternion toward an object. switching the entire code to vectors,... not having much luck. I have contacted wasabimole who wrote the code a couple of times but haven't heard back from them.
Any help would be greatly appreciated. What I need are suggestions on the best and simplest way to do this and hints to understand what is happening so I can do it myself in the future.
Thank you in advance.
The recursive branch code with my modifications is:
// Add ring vertices
for (var n = 0; n <= NumberOfSides; n++, ang += angInc)
{
var r = ringShape[n] * radius;
offset.x = r * Mathf.Cos(ang); // Get X, Z vertex offsets
offset.z = r * Mathf.Sin(ang);
vertexList.Add(position + quaternion * offset); // Add Vertex position
uvList.Add(texCoord); // Add UV coord
texCoord.x += textureStepU;
}
if (lastRingVertexIndex >= 0) // After first base ring is added ...
{
// Create new branch segment quads, between last two vertex rings
for (var currentRingVertexIndex = vertexList.Count - NumberOfSides - 1; currentRingVertexIndex < vertexList.Count - 1; currentRingVertexIndex++, lastRingVertexIndex++)
{
triangleList.Add(lastRingVertexIndex + 1); // Triangle A
triangleList.Add(lastRingVertexIndex);
triangleList.Add(currentRingVertexIndex);
triangleList.Add(currentRingVertexIndex); // Triangle B
triangleList.Add(currentRingVertexIndex + 1);
triangleList.Add(lastRingVertexIndex + 1);
}
}
// Do we end current branch?
radius *= RadiusStep;
if (radius < MinimumRadius || vertexList.Count + NumberOfSides >= MaxNumVertices + 65000) // End branch if reached minimum radius, or ran out of vertices
{
// Create a cap for ending the branch
vertexList.Add(position); // Add central vertex
uvList.Add(texCoord + Vector2.one); // Twist UVs to get rings effect
for (var n = vertexList.Count - NumberOfSides - 2; n < vertexList.Count - 2; n++) // Add cap
{
triangleList.Add(n);
triangleList.Add(vertexList.Count - 1);
triangleList.Add(n + 1);
}
return;
}
// Code added for windswept tree
var x = (transform.InverseTransformDirection(0f,0f,1f).x);
var y = (transform.InverseTransformDirection(0f,0f,1f).y);
var z = (transform.InverseTransformDirection(0f,0f,1f).z);
position += quaternion * new Vector3(x, (y + SegmentLength * Mathf.Sqrt (Mathf.Sqrt(radius))), z);
transform.Rotate(x, y, z);
// Code added for windswept tree
x += (Random.value - 0.5f) * Twisting;
y += 0f;
z += (Random.value - 0.5f) * Twisting;
transform.Rotate(x, y, z);
// Continue current branch (randomizing the angle)
texCoordV += 0.0625f * (SegmentLength + SegmentLength / radius);
lastRingVertexIndex = vertexList.Count - NumberOfSides - 1;
Branch(transform.rotation, position, lastRingVertexIndex, radius, texCoordV); // Next segment
// Do we branch?
if (vertexList.Count + NumberOfSides >= MaxNumVertices || Random.value > BranchProbability) return;
// Yes, add a new branch
transform.rotation = quaternion;
x = Random.value * 70f - 35f;
x += x > 0 ? 10f : -10f;
y = 0f;
z = Random.value * 70f - 35f;
z += z > 0 ? 10f : -10f;
transform.Rotate(x, 0f, z);
Branch(transform.rotation, position, lastRingVertexIndex, radius, texCoordV);
}
cjdev,
ringShape is a parameter supplied by the user that makes the branch round or more random shape - a bit more natural shaped. See SetTreeRingShape() in the code below
quaternion is passed to the recursive branch routine. $$anonymous$$y understanding is that there is a position - passed as "position" to the branch subroutine - vector used to give the location and direction of the next segment of the branch. Also transform.rotation is passed and this is the quaternion it uses. I can change the position vector as needed to give me the windswept tree but not the corresponding transform.rotation so the corresponding ring for the segment is not orthogonal to the segment axis. This is the crux of the problem. $$anonymous$$y lack of knowledge on quaternions is where I have problems.
Below is the full code including the segment above... sorry I didn't want to paste too much...
I don't think it will let you post that much code in the comments, but from what I can see it looks like ringShape is a modifier that deter$$anonymous$$es the offset of the verts from a circle. And then quaternion is what deter$$anonymous$$es the direction and facing of the circle. If you want to modify the direction of the tree branches I think your best bet would be to modify the position and quaternion directly. Ins$$anonymous$$d of trying to visualize quaternions in general though I'd recommend using Unity's helper methods, like Quaternion.Euler. $$anonymous$$ultiplying your slight rotation by quaternion every circle and tweaking the position a bit should get you close to some windswept branches.
cjdev,
I tried to post the code though it is in moderation at the moment. It is available at the asset store but for now I appreciate any insights you might have.
Yes, I have been able to modify just the position and get nice windswept trees but the the ring of vertices goes from orthogonal to 45 degree tilt to parallel to the direction to more than 90 degree... at this point the branches turn inside out and the mesh gets destroyed - collisions are wrong, colors are weird...branches look like flat ribbons and half tubes.
The original author was able to bend the branches correctly when the twisting component is implemented - just below where I added my piece of code. I was hoping to repeat this only in a consistent world direction.
Answer by Bunny83 · Jan 26, 2016 at 04:36 AM
I just had a look at your added code. Well, there are a few things strange / wrong. InverseTransformDirection transforms a worldspace direction into a local space direction. "localspace" inside the branch however means local to the current section as he's adjusting the transform position / rotation for each step. This is reverted when the tree creation is finished. He basically uses the Transform as temp position / rotation marker.
So your x,y and z values would now contain the local space equivalent of the world space vector (0,0,1). I'm not sure why you rotate that vector by the quaternion value as this would basically revert the vector back to (0,0,1).
You then shift the next branch step by this vector which would still make a bit of sense. However using the same values in Rotate makes not much sense. The vector is a normalized vector while Rotate() takes angles in degrees.
I've just downloaded the original asset from the assetstore and added "some code" for a "wind" parameter. The script now has an additional "windStrength" variable and a vector to define the direction of the wind. That vector is in local space of the tree object (not local to each branch). I also added an "worldWindSource" Transform variable which allows you to assign an empty gameobject. If a gameobject is provided the script will use the objects forward vector as wind direction and convert it into local space.
The modified script can be found here.
I enclosed all changes with comments like this:
// <windswept>
the changes
// </windswept>
So if you want to know what i changed, just look out for those or use the search function and search for "".
Bunny83,
Thank you for the answer. It looks great!! The tree truly has the windswept look and the branches hold their shape. I will have to go through it in detail to understand what you did but I really appreciate your help. Thanks! If you need anything I can help with in the future just let me know. I fI get through this I will also send you a version of what I am making... it should be fun.