0
\$\begingroup\$

I've seen this many times, but I have no idea what's the best way to achieve it. I am looking for something close to, for example, this: Lonely Tree Live Wallpaper

I have two approaches in mind: one would be to make an animation in, say, Blender and then export the resulting images & create a spritesheet animation out of it. This is very straightforward, but creating a 120-frame spritesheet out of 512 x 512 or 1024 x 1024 images (for larger screens) seems overkill.

The second approach would be to cut my tree into a few separate textures and then move them simultaneously in such a manner that it gives the impression they form a single image of a tree swaying in the wind.

Any other approaches?

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Maybe use skinning? Create a mesh in blender, make an armature for it. Assign each vertex weights to different bones in the armature.

When you're rendering the tree, send in one matrix (or quaternion) for every bone in the trees armature. In the vertex shader, lookup the current vertex's weights for the provided matrixes, and transform it accordingly.

Eg

#define numberOfBones 24
in vec3 vertex;
in vec3 weights;
in vec3 bones;

uniform mat4[numberOfBones] matrixes;
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;

void main() {

  Matrix compositeMatrix = (matrixes[bones.x] * weights.x) * (matrixes[bones.y] * weights.y) * (matrixes[bones.z] * weights.z);
  glPosition = projectionMatrix * viewMatrix * compositeMatrix * vec4(vertex, 1); 
}

Note that this example would only allow a vertex to be influenced by 3 different bones, but due to the limitations of GLSL in OpenGL ES 2.0 this will do.

Maybe you would not need to create an animation for it, maybe you could do it procedurally. You could start off with the bone closets to the ground, and represent wind sway through it's matrix by an rotation with some strength (eg, if the wind blows dead on along the x axis, rotate the matrix along the z axis). Then for the next bone(s) immediately connected to that bone, take the matrix you just calculated and rotate it further. Don't forget that the strength of the wind sway need to vary, sin or cos is good for this, but maybe you'd like and more logarithmic type vary.

void uploadBoneMatrix(Node node, float parentStrength, Matrix parentMatrix, Vector displacement) {
    Matrix nodeMatrix = parentMatrix.copy(); //deep copy
    nodeMatrix.translate(displacement);
    float strength = parentStrength + Math.sin(some fucking intervall);  

    Matrix additionalRotation = new Matrix().rotateAroundZAxis(strength);
    nodeMatrix = nodeMatrix * additionalRotation; //don't forget that matrix multiplication is not commutative

    GLES20.glUniform4fv(shader.getBoneIndex(node.boneIndex), nodeMatrix);

    for every Node child of node {
        Vector displacement = node.endPoint.copy()/* deep copy */ * nodeMatrix ;
        uploadBoneMatrix(child, strength, nodeMatrix.copy() /* deep copy */, displacement );
    }

}

And call uploadBoneMatrix on the root node.

I think that could look really cool.

Edit:

Also, out of your two approaches I liked the second one best. Maybe it would look a bit rigid, but I'm sure you could make it entirely believable.

Edit2:

I assume that you're using Android or something, GLES20 is just any arbitrary handle to an OpenGL context. Also, naturally you do uploadBoneMatrix before you render the tree.

Edit3:

I realized that you also must displace every child

\$\endgroup\$
1
  • \$\begingroup\$ Cheers for all those details. I had a look into skinning, never heard of it before. Do you reckon I could integrate skinning into my second approach? So instead of trying to figure out how to move each of those independent textures, maybe add a bone "structure" that connects all of them and work from there? BTW, I'm using Android, yes. \$\endgroup\$
    – async
    Nov 21, 2013 at 20:36

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .