Linear Impulse values - java

I'm creating my own Game Application using Box2D and i'm facing some problems. I managed to render every body i wanted, moving them but i have to put high value to move them correctly. For example here is my Player body definition :
bodyDefPlayer = new BodyDef();
bodyDefPlayer.type = BodyType.DynamicBody;
bodyDefPlayer.position.set(positionX, (positionY * tileHeight) + 50);
playerBody = world.createBody(bodyDefPlayer);
polygonPlayer = new PolygonShape();
polygonPlayer.setAsBox(50, 50);
fixturePlayer = new FixtureDef();
fixturePlayer.shape = polygonPlayer;
fixturePlayer.density = 0.8f;
fixturePlayer.friction = 0.5f;
fixturePlayer.restitution = 0.0f;
playerBody.createFixture(fixturePlayer);
playerBody.setFixedRotation(true);
And here is how i have to apply my impulse to move him :
Vector2 vel = this.player.playerBody.getLinearVelocity();
Vector2 pos = this.player.playerBody.getWorldCenter();
player.playerBody.applyLinearImpulse(new Vector2(vel.x + 20000000, vel.y * 1000000), pos, true);
As you can see my values are pretty high plus the player isn't doing a curve when he is going down but more going straight down when he can.
I'd like to have some help please :)
Thanks !

It seems like you are using the Linear Impulse when you should be just applying forces. The Linear Impulse "smacks" a body with a large force to give it a hefty instantaneous velocity. This is good if you are hitting a golf ball (large force, small time), or simulating a fired bullet, but it does not look good for the movement of real bodies.
This is a function that I use on my Entities, which are a class to hold the box2D body and apply control forces to the body. In this case, this function, ApplyThrust, makes the body move towards a target (seek behavior):
void ApplyThrust()
{
// Get the distance to the target.
b2Vec2 toTarget = GetTargetPos() - GetBody()->GetWorldCenter();
toTarget.Normalize();
b2Vec2 desiredVel = GetMaxSpeed()*toTarget;
b2Vec2 currentVel = GetBody()->GetLinearVelocity();
b2Vec2 thrust = desiredVel - currentVel;
GetBody()->ApplyForceToCenter(GetMaxLinearAcceleration()*thrust);
}
In this case, the Entity has been given the command to move to a Target position, which it caches internally and can be recovered using GetTargetPos(). The function applies force to the body by generating a difference vector between the desired maximum velocity (towards the target) and the current velocity. If the body is already headed towards the target at the maximum velocity, the contribution from this function is effectively 0 (same vectors).
Note that this does NOT change the orientation of the body. There is actually a separate function for that.
Note the original question appears to be in Java (libgdx?). This is in C++, but the general idea is applicable and should work in any Box2d implementation by using references instead of pointers, etc.
There is a code base with samples of doing this located here. You can read more about this code base in this post. Watch the video...I suspect it will tell you immediately if this is the information you are looking for.
The Normalize function, which should be a member of the b2Vec2 class is:
/// Convert this vector into a unit vector. Returns the length.
float32 b2Vec2::Normalize()
{
float32 length = Length();
if (length < b2_epsilon)
{
return 0.0f;
}
float32 invLength = 1.0f / length;
x *= invLength;
y *= invLength;
return length;
}
This converts a vector to a unit vector (length = 1) pointing in the same direction.
NOTE This is an in-place operation. It changes the actual b2Vec2 object, it does not return a new object. Adapt to Java as you see fit.
Was this helpful?

You are using the same units for graphics and physics (pixels). There are two reasons why such approach is bad:
It will scale poorly on different resolutions
Box2D is tuned to work with some range of values (due to floating number precision). You can find the range of values in Box2D manual. They are in meters there, but how you name the units is actually not important, since Box2D does not keep track of the units, but instead operates on values. For example you can say that the speed of the body is 10 meters per second or 10 foots per second. For calculations it is not important. It will become important when you will interpret the result of calculations. For example, traveled distance over time: in first case it will be meters and in second one foots. But that is not Box2D business. You just pass values to it (For example, body.pos.set(2, 3) //no info about units here)
The common technics to overcome these problems is to have different units for use with Box2D and for graphics, and just to rescale between them (look for PTM_RATIO in cocos examples)

Related

Getting a point from begginning coordinates, angle and distance

I want to get a Vector containing a coordinate. I know my beginning coordinates, angle and distance. So far I've tried doing:
Vector2 pos = new Vector2(beginningX, beginningY).add(distance, distance).rotate(angle);
But it doesn't work as I expect it to. When the rotation isn't 0 the coordinates become big, and the ending point isn't where I expect it to be. I know this must be a simple problem, but I just can't solve it.
EDIT:
Tried doing:
Vector2 pos = new Vector2(beginningX, beginningY).add(distance, 0).rotate(angle);
(Adding distance to x only) Still no success.
I'd say you're doing it wrong: you need to rotate the distance vector and add it to the position vector:
Vector2 pos = new Vector2(beginningX, beginningY).add(new Vector2(distance, 0).rotate(angle) );
You might want to read up on vector math but basically it amounts to this (if I correctly understood what you're trying to do):
If you rotate a vector you're always rotating around point 0/0. Thus you'll want to create a vector that covers the distance from 0/0 to your distance on the x-axis:
0---------------->d
Now you rotate that vector by some angle:
d
/
/
/
/
/
0
Then you offset that vector by your starting point, i.e. you add the two vectors (for simplicity I assume your starting point lies on the y-axis):
d
/
/
/
/
/
s
|
|
|
0
You need to rotate only the distance vector, rather than a sum of beginning and distance. Addition is the same in either order (commutative), so you can try this way:
Vector2 pos = new Vector2(distance, 0).rotate(angle).add(beginningX, beginningY);
Advantage: This chained call does not create a temporary Vector2 for the beginning position that would immediately become garbage for the garbage collector. Conserving space and garbage collection time will be important when your code handles millions of vectors.
This is simple vector addition. I'm assuming 2D coordinates, with angles measured counterclockwise from x-axis:
x(new) = x(old) + distance*cos(angle)
y(new) = y(old) + distance*sin(angle)
Be sure that your angles are in radians when you plug them into trig functions.

How to divide Array Length into arrays with lengths that are multiples of 3

So I have a fairly large array that contains xyz coordinates, where array[0] = x0, array[1] = y0, array[2] = z0, array[3] = x1, array[4] = y1... and so on.
I'm running an algorithm on this array that is taking longer than I would like it to, and I want to split the work amongst threads. I have my threads set up, but I am not sure how to divide this array properly so I can distribute this work across 3 threads.
Even though I have an array length that is divisible by 3, this won't work, because splitting into 3 can split an xyz coordinate (for instance, if my array was size 15, dividing it by 3 will give me arrays of size 5, which means I'm splitting an XYZ coordinate.
How can I split this array (it doesn't have to necessarily be equal in size) so that I can distribute the work? (for instance, in the previous example, I would like to have two arrays of size 6 and one of size 3).
Note: The size of the array is variable, but is always divisible by 3.
EDIT: Sorry, should have mentioned that I'm working in Java. My algorithm iterates through a collection of coordinates and determines which coordinates lie inside of a particular 3d shape (such as an ellipsoid). It saves these coordinates and I perform other tasks with these coordinates (I'm working on a computer graphics app).
EDIT2: I'm going to elaborate on the algorithm a bit more.
Basically, I am working in Android OpenGL-ES-3.0. I have complex 3D-object with somewhere around 230000 vertices and close to a million triangles.
In the app, the user moves either a ellipsoid or box (they choose which one) to a location close to or on the object. After moving it, they click a button, which runs my algorithm.
The purpose of the algorithm is to determine which points from my object lie inside of the ellipsoid or box. These points are subsequently changed to a different color. To add to the complexity, however, is the fact that I have transformation matrices applied to both the points of the object and the points of the ellipsoid/box.
My current algorithm begins by iterating through all the points of the object. For those of you unclear on my iteration, this is my loop.
for(int i = 0; i < numberOfVertices*3;)
{
pointX = vertices[i];
i++;
pointY = vertices[i];
i++;
pointZ = vertices[i];
i++;
//consider transformations, then run algorithm
}
I perform the necessary steps to consider all my transformations, and after that is finished, I have a point from my object and the location of my ellipsoid/box centroid.
Then, depending on the shape, one of the following algorithms is used:
Ellipsoid: I use the centroid of the ellipse and apply the formula
(x−c)T RT A R(x−c) (sorry I don't know how to format that, I'll explain the formula). x is a column vector describing the xyz point from my object that I am on in my iteration. c is a column vector describing the xyz point of my centroid. T is supposed to mean transpose. R is my rotation matrix. A is a diagonal matrix with entries with entries (1/a^2, 1/b^2, 1/c^2), and I have values for a b and c. If this formula is > 1, then x lies outside of my ellipsoid and is not a valid point. If it is <=1, then I save x.
Box: I simply check if the point falls within a range. If the point of the object lies a certain distance in the X-direction, Y-direction, and Z-direction from the centroid, I save it.
These algorithms are accurate, and work as intended. The issue, is obviously efficiency. I don't seem to have a good understanding of what makes my app strain and what doesn't. I thought multi-threading would work, and I tried some of the techniques described but they didn't have a significant improvement on performance. If anyone has ideas on filtering out my search so I'm not iterating through all these points, it would help.
May I suggest a slightly different way to handle it. I know this isn't a direct answer to your question, but please consider it.
This could be easier to see if you implemented it as coordinate Objects, each with x, y and z values. Your "array" would now be 1/3 as long. You might think this would be less efficient--and you might be right--but you'd be surprised at how well java can optimize things. Often Java optimizes for the cases people use the most and your manually manipulating this array as you suggest is possibly even slower than using objects. Until you've proven the most readable design too slow you shouldn't optimize it.
Now you have a collection of coordinate objects. Java has queues that multiple threads can pull from efficiently. Dump all your objects into a queue and have each of your threads pull one and work on it by processing it and putting it in a "Completed" queue. Note that this gives you the ability to add or remove threads easily, without effecting your code except for 1 number. How would you take the array based solution to 4 or 6 threads?
Good luck
Here is a demo of the work explained below.
Observations
Each coordinate is 3 indexes.
You have 3 threads.
Let's say you have 17 coordinates, that's 51 indexes. You want to split the 17 coordinates among your 3 threads.
var arraySize = 51;
var numberOfThreads = 3;
var numberOfIndexesPerCoordinate = 3;
var numberOfCoordinates = arraySize / numberOfIndexesPerCoordinate; //17 coordinates
Now split that 17 coordinates among your threads.
var coordinatesPerThread = numberOfCoordinates / numberOfThreads; //5.6667
This isn't an even number, so you need to distribute unevenly. We can use Math.floor and modulo to distribute.
var floored = Math.floor(coordinatesPerThread); //5 - every thread gets at least 5.
var modulod = numberOfCoordinates % floored; // 2 - there will be 2 left that need to be placed sequentially into your thread pool
This should give you all the information you need. Without knowing what language you are using, I don't want to give any real code samples.
I see you edited your question to specify Java as your language. I'm not going to do the threading work for you, but I'll give a rough idea.
float[] coordinates = new float[17 * 3]; //17 coordinates with 3 indexes each.
int numberOfThreads = 3;
int numberOfIndexesPerCoordinate = 3;
int numberOfCoordinates = coordinates.length / numberOfIndexesPerCoordinate ; //coordinates * 3 indexes each = 17
//Every thread has this many coordinates
int coordinatesPerThread = Math.floor(numberOfCoordinates / numberOfThreads);
//This is the number of coordinates remaining that couldn't evenly be split.
int remainingCoordinates = numberOfCoordinates % coordinatesPerThread
//To make things easier, I'm just going to track the offset in the original array. It could probably be computed instead, but its just an int.
int offset = 0;
for (int i = 0; i < numberOfThreads; i++) {
int numberOfIndexes = coordinatesPerThread * numberOfIndexesPerCoordinate;
//If this index is one of the remainders, then increase by 1 coordinate (3 indexes).
if (i < remainingCoordinates)
numberOfIndexes += numberOfIndexesPerCoordinate ;
float[] dest = new float[numberOfIndexes];
System.arraycopy(coordinates, offset, dest, 0, numberOfIndexes);
offset += numberOfIndexes;
//Put the dest array of indexes into your threads.
}
Another, potentially better option would be to use a Concurrent Deque that has all of your coordinates, and have each thread pull from it as they need a new coordinate to work with. For this solution, you'd need to create Coordinate objects.
Declare a Coordinate object
public static class Coordinate {
protected float x;
protected float y;
protected float z;
public Coordinate(float x, float y, float z) {
this.x = x;
this.y = y;
this.z = z;
}
}
Declare a task to do your work, and pass it your concurrent deque.
public static class CoordinateTask implements Runnable {
private final Deque<Coordinate> deque;
public CoordinateTask(Deque<Coordinate> deque) {
this.deque = deque;
}
public void run() {
Coordinate coordinate;
while ((coordinate = this.deque.poll()) != null) {
//Do your processing here.
System.out.println(String.format("Proccessing coordinate <%f, %f, %f>.",
coordinate.x,
coordinate.y,
coordinate.z));
}
}
}
Here's the main method showing the example in action
public static void main(String []args){
Coordinate[] coordinates = new Coordinate[17];
for (int i = 0; i < coordinates.length; i++)
coordinates[i] = new Coordinate(i, i + 1, i + 2);
final Deque<Coordinate> deque = new ConcurrentLinkedDeque<Coordinate>(Arrays.asList(coordinates));
Thread t1 = new Thread(new CoordinateTask(deque));
Thread t2 = new Thread(new CoordinateTask(deque));
Thread t3 = new Thread(new CoordinateTask(deque));
t1.start();
t2.start();
t3.start();
}
See this demo.
Before trying to optimize with concurrency, try to minimize the amount of points you need to test, and minimize the cost of those tests, by using the most efficient collision detection methods at your disposal.
Some general suggestions:
Consider normalizing everything to a common frame of reference before running through your calculations. For example, instead of applying transformations to each point, transform the selection box/ellipsoid into the shape's coordinate system so you can perform your collision detection without the transformations within each iteration.
You may also be able to combine some or all of your transformations (rotation, translation, etc.) into a single matrix calculation, but that won't gain you much unless you're performing a lot of transformations, which you should try to avoid.
Generally speaking it's beneficial to keep the transformation pipeline as streamlined as possible, and keep all coordinate calculations in the same space to avoid transformations as much as possible.
Try to minimize the number of points you need to perform your slowest calculations on. The most accurate collision test should only be necessary for points that you can't rule out as being inside the shape by faster means, using an approximation of the shape, such as a collection of spheres, or the shape's convex hull. Simplifying the shape allows you to limit the slowest calculations to only those points that lie very close to your shape's actual bounds.
In my own 2D work in the past I found that even calculating the convex hulls for hundreds of complex animated shapes in real time was faster than doing collision detection directly without using their convex hulls, because they enable much faster collision calculations.
Consider calculating/storing additional information about the shape, such as an inner and outer collision sphere (one sphere inside all points, and one outside all points) which you can use as a fast initial filter. Anything inside the smaller sphere is guaranteed to be inside your shape, anything outside the outer sphere is known to be outside your shape. You might even want to store a simplified version of your shape, (or its convex hull), which you could calculate in advance and use to aid collision detection.
Similarly, consider using one or more spheres to approximate your ellipsoid in initial calculations, to minimize which points you need to test for collision.
Instead of calculating actual distances, calculate the squared distances and use those for comparison. However, prefer using faster tests for collision if possible. For example, for convex polygons you can use the Separating Axis Theorem, which projects vertices onto a common axis/plane to permit very quick overlap calculations.

How to generate some identically distributed pseudo-random vectors with a fixed length r in a programming language?

For example, for the dimension d=2, it means that we could generate a random angle 0<=a<2*pi, and then we could just use
(x_1,x_2)=(r*cos(a),r*sin(a)) as the random vector.
However, for the dimension d>=3, we could not just generate an angle and use it to represent the vector. Then how could we generate such a vector (x_1,...,x_d), which is identically distributed on x_1^2+x_2^2+...+x_d^2=r^2?
I have just come up with a new idea, that we could generate a vector (x_1,...,x_d) such that -r<=x_i<r for all i, normalize it if x_1^2+x_2^2+...+x_d^2<=r^2 and abondon it if x_1^2+x_2^2+...+x_d^2>r^2.
However, there is a drawback that the probability that x_1^2+x_2^2+...+x_d^2<=r^2 would become very small if d is very large. Does there exist some better solutions?
Generate random variables (X_1, X_2, ... X_d) that are independent and have standard normal distributions, and then normalize by dividing by sqrt(X_1^2+...+X_d^2)/r.
That the joint distribution of independent normal distributions is rotationally symmetric is not just true, it characterizes normal distributions.
You can generate pairs of independent variables with a standard normal distribution efficiently from uniform random variables using the Box-Muller transform.
I see two ways around it.
The straightforward way is, in pseudo-code:
1. build n-dimensional vector x[0] through x[n-1] with random components
2. find radius
3. go to step 1 if radius > r; otherwise, normalize to radius r
This is non-deterministic, because there is no way to know how many times you will need to cycle before you find an acceptable sphere. Additionally, the probability of finding a bad point goes up with the number of dimensions.
To understand why (thanks commenters!), imagine a 1x1 square. Add a r=1 circle inside. Fill the square with random points. All the points between the center and the circle are evenly distributed when projected on the circle. All the points between the circle and the square's border are not - because there's too many at, say, 45º; and none at, say, 90º.
The non-straightforward version is a generalization of your 2-dimensional approach:
1. assume that we are on an n-sphere; generate angles phi[0], ...phi[n-2]
for a polar-coordinates point
2. convert to cartesian coordinates x[0] through x[n-1]
According to the n-sphere page in wikipedia, the formula is
x[0] = r*cos(phi[0]);
x[1] = r*sin(phi[0])*cos(phi[1]);
x[2] = r*sin(phi[0])*sin(phi[1]);
...
x[n-2] = r*sin(phi[0])*sin(phi[1])* /*...*/ sin(phi[n-3])*sin(phi[n-2])
x[n-1] = r*sin(phi[0])*cos(phi[1])* /*...*/ sin(phi[n-3])*cos(phi[n-2])
The actual algorithm can be implemented a lot more efficiently (sin(phi[0]) is getting calculated a lot, for example)
To avoid non-determinism, I recommend the second approach.
Edit
The recommended approach, not listed above, is in Douglas's answer and many reference sites:
https://mathoverflow.net/questions/136314/what-is-a-good-method-to-find-random-points-on-the-n-sphere-when-n-is-large
http://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform
http://mathworld.wolfram.com/HyperspherePointPicking.html

How to move along sinus function at constant speed

I have a Java program that moves an object according to a sinus function asin(bx).
The object moves at a certain speed by changing the x parameter by the time interval x the speed. However, this only moves the object at a constant speed along the x axis.
What I want to do is move the object at a constant tangential speed along the curve of the function. Could someone please help me? Thanks.
Let's say you have a function f(x) that describes a curve in the xy plane. The problem consists in moving a point along this curve at a constant speed S (i.e., at a constant tangential speed, as you put it.)
So, let's start at an instant t and a position x. The point has coordinates (x, f(x)). An instant later, say, at t + dt the point has moved to (x + dx, f(x + dx)).
The distance between these two locations is:
dist = sqrt((x + dx - dx)2 + (f(x+dx) - f(x))2) = sqrt(dx2 + (f(x+dx) - f(x))2)
Now, let's factor out dx to the right. We get:
dist = sqrt(1 + f'(x)2) dx
where f'(x) is the derivative (f(x+dx) - f(x)) /dx.
If we now divide by the time elapsed dt we get
dist/dt = sqrt(1 + f'(x)2) dx/dt.
But dist/dt is the speed at which the point moves along the curve, so it is the constant S. Then
S = sqrt(1 + f'(x)2) dx/dt
Solving for dx
dx = S / sqrt(1 + f'(x)2) dt
which gives you how much you have to move the x-coordinate of the point after dt units of time.
The arc length on a sine curve as a function of x is an elliptic integral of the second kind. To determine the x coordinate after you move a particular distance (or a particular time with a given speed) you would need to invert this elliptic integral. This is not an elementary function.
There are ways to approximate the inverse of the elliptic integral that are much simpler than you might expect. You could combine a good numerical integration algorithm such as Simpson's rule with either Newton's method or binary search to find a numerical root of arc length(x) = kt. Whether this is too computationally expensive depends on how accurate you need it to be and how often you need to update it. The error will decrease dramatically if you estimate the length of one period once, and then reduce t mod the arc length on one period.
Another approach you might try is to use a different curve than a sine curve with a more tractable arc length parametrization. Unfortunately, there are few of those, which is why the arc length exercises in calculus books repeat the same types of curves over and over. Another possibility is to accept a speed that isn't constant but doesn't go too far above or below a specified constant, which you can get with some Fourier analysis.
Another approach is to recognize the arc length parametrization as a solution to a 2-dimensional ordinary differential equation. A first order numerical approximation (Euler's method) might suffice, and I think that's what Leandro Caniglia's answer suggests. If you find that the round off errors are too large, you can use a higher order method such as Runge-Kutta.

Coloring the Barnsley Fern fractal

While rendering the Barnsley fern fractal I come up with single color images or at most four color images i.e. the bottom left, bottom right, bottom stem and the rest of the leaves. Here is the image I get for example:
What I want however is to bring shades in the leaves and making stem thicker and of different color like:
I digged a bit about the algorithms that can be used, then I read in Draves's paper about fractal flames that during iteration of Iterated Function Systems a single point may be rendered many times if we use a single color which results in a loss of information so we need to create a histogram of how many times a point was to be rendered and then perform a rendering pass using the histogram with shades of colors log-density coloring.
I have brought myself to the point where I have the histogram but don't know how to use it to render the shades or using the log-density render technique. Can someone help me with such type of rendering or at least direct me to a source where I can read more about this with practical examples.
Here is what I have tried:
AffineTransformation f1 = new AffineTransformation(0,0,0,0.25,0,-0.4);
AffineTransformation f2 = new AffineTransformation(0.95,0.005,-0.005,0.93,-0.002,0.5);
AffineTransformation f3 = new AffineTransformation(0.035,-0.2,0.16,0.04,-0.09,0.02);
AffineTransformation f4 = new AffineTransformation(-0.04,0.2,0.16,0.04,0.083,0.12);
int N=Width*Height;
int pixelhistogram[] = new int[N];
for(int i=0;i< N*25;i++)
{
Point newpoint = new Point();
double probability = Math.random();
if(probability < 0.01)
{
newpoint = f1.transform(point);
}
else if(probability < 0.94)
{
newpoint = f2.transform(point);
}
else if(probability < 0.97)
{
newpoint = f3.transform(point);
}
else
{
newpoint = f4.transform(point);
}
point = newpoint;
// Translating the point to pixel in the image and
// incrementing that index in the pixelHistogram array by 1
// W and H are the Width and Height
int X=((int)(point.getX()*W/3)+W/2)/2 + W/4-1;
int Y=H-((int)(point.getY()*H/8) + H/9) -1;
pixelhistogram[W*Y+X]++;
}
// Now that I have the pixelhistogram
// I don't know how to render the shades using this
AffineTransformation is a simple class which performs Affine Transformation on a point. I omitted the code because otherwise the question would have become too lengthy.
A simple coloring would be to render pixel (X,Y) light green, green, or brown according to whether pixels[W*Y+X] is less than n1, between n1 and n2, or greater than n2. To determine n1 and n2, trial and error would probably be the simplest solution, but you could make an actual histogram of the log of the pixel counts that you have recorded to help judge where to put the cuts (or more generally you could use clustering algorithms to do it automatically).
PS: In the image that you show it looks like the stem is rendered with an L-system and the fronds are rendered using the three leaf transforms only (i.e. omit the fourth "stem-transform"); I would guess they are using the log pixel counts to shade the level of green but not to shade the stem.
Addition: I was asked, below, to discuss log-histograms. To avoid getting bogged down, I'd recommend first using a full featured data analysis software like R to see if this gets you what you want. Write out the pixels array to a text file with one number per line, then start R and run:
ct=scan('pixels_data.txt')
hist(log(ct))
If you see a a multimodal histogram (i.e. if it has clear peaks and valleys), that will suggest how to choose n1 and n2: put them in the valleys (i.e. if the valley on the plot is at y, set n1=exp(y)).
If you wind up plotting histograms in Java, it can apparently be done with the Jfreechart software. Just create an array with the logs of the values in the pixels array and create the histogram out of that.
At best I expect you to see only one valley in the histogram, if you use the standard 3-transform Barnsley fern, separating the really high stem values from the fronds. To color the fronds, if n is the cut between frond and stem, and pixels[W*Y+X] is less than n, you could color it using, say:
v=128.0*(log(n)-log(pixels[W*Y+X]))/log(n);
RGB=(v,255,v)
PS: Getting thick stems using the random iteration algorithm only is going to be a problem. If you change the 3rd transform to be less singular, your stems will wind up looking like thin ferns and not sticks. E.g.
{"title":"Thick Stem Fern","alist":[[
[0.11378443003074948,-0.005060836319767042,0.013131296101198788,0.21863066144310556,0.44540023470694723,0.01726296943557673],
[0.15415337683611596,-0.17449052243042712,0.23850452316465576,0.2090228040695959,0.3652068203134602,0.11052918709831461],
[-0.09216684947824424,0.20844742602316002,0.2262266208270773,0.22553569847678284,0.6389950926444947,-0.008256440681230735],
[0.8478159879190097,0.027115858923993468,-0.05918196850293869,0.8521840120809901,0.08189073762585078,0.1992198482087391]
]],"va":[1,0,0,1,0,0],"word_length":6,"level_max":40,"rect_size":1}
Is the json data to describe:

Categories