Random Character Texture Generator / Implementing Symmetry operation

Hi, i am thinking of creating character’s textures procedually from a base texture.

The model is fully symmetrical along Y axis. When you change the U-V texture coordinates of each face, the base texture is displayed differently.

Here is some generated textures

Basically what i intent to do is to allow each race of enemies e.g golems to have unique appearance/skin so that the user doesnt get so bored when he fights the same enemy type.

Ok here is now my question :

  1. how do i change u-v texture coordinates of a face/Vertex in Jme ?

In the mesh object you have to mofify the texcoord buffer.

hello, when i load the model it is returned as a spatial.



I need the following :

  1. method to get texcoords from spatial.
  2. method to get vertex buffer from spatial.
  3. method to get all normals from spatial.



    Thank you,

Its all in the mesh of each geometry.

i load the model from OgreXml, but it returns “spatial” objects. Which dont have any method for getting their vertex/texcoord/normal data.

And i havent found a method to convert spatial to geometry.

geometry extends spatial, so you can cast it, its probably a node you have after loading so do something like this:

[snippet id=“13”]

1 Like

Nice !!! didnt know you could cast spatial to node !!! i was afraid it would throw a classCastException.



Thank you.

Actualy it can, a mdoel usualy eitehr consists directly of a Geometry or it consits of a Node with 1-x Geometrys, .

I am stuck for 6 hours on how to summetry my mesh. I do the following:

  1. clone the mesh.
  2. model.scale(-1,1,1);
  3. Flip Normals by multiplying each normal by -1 :



    [java]

    VertexBuffer normals = summetryMesh.getBuffer(Type.Normal);

    float[] normalArray = BufferUtils.getFloatArray((FloatBuffer) normals.getData());



    for (int i = 0; i < normalArray.length; i += 3)

    {

    normalArray *= -1;

    normalArray *= -1;

    normalArray *= -1;

    }



    summetryMesh.setBuffer(Type.Normal, 3, normalArray);[/java]



    Result :

    Another identical mesh is created that looks like being rotated 180 degrees along X axis. But its not symmetric because you see its back instead of its chest. I tried rotating afterwords but it didn’t help.



    Questions :
  4. Mirroring operation is done just by scaling by (-1,1,1) right ?
  5. flipping normals is done by multiplying by -1 ?
  6. Can i apply a Matrix transformation to a node ? i looked at the classes that use matrix4f but there are no methods that use it for that reason in Scene package.

lol, the original code was correct. It was the texture coordinates that weren’t flipped and that’s why it looked like being rotated 180 degrees.



And i wasn’t able to understand that the texture was wrong. I only realised it when i used a white material.

i cant flip the uv coordinates. I tried rotating 180 degrees but it didn’t work.



[java]

public void flipUV(Mesh mesh)

{

VertexBuffer uv = mesh.getBuffer(Type.TexCoord);



float[] uvArray = BufferUtils.getFloatArray((FloatBuffer) uv.getData());

for (int i = 0; i < uvArray.length; i += 2)

{

float u = uvArray;

float v = uvArray;

float theta = FastMath.PI;

uvArray = u * FastMath.cos(theta) - v * FastMath.sin(theta);

uvArray[i+1] = u * FastMath.sin(theta) + v * FastMath.cos(theta);

}

mesh.setBuffer(Type.TexCoord, 2, uvArray);

}[/java]

[java]public void flipUV(Mesh mesh)

{

VertexBuffer uv = mesh.getBuffer(Type.TexCoord);

float[] uvArray = BufferUtils.getFloatArray((FloatBuffer) uv.getData());

for (int i = 0; i < uvArray.length; i ++)

{

float u = uvArray[i*2];

float v = uvArray[i*2 + 1];

float theta = FastMath.PI;

uvArray[i*2] = u * FastMath.cos(theta) - v * FastMath.sin(theta);

uvArray[i*2+1] = u * FastMath.sin(theta) + v * FastMath.cos(theta);

}

mesh.setBuffer(Type.TexCoord, 2, uvArray);

}[/java]

It would not loop through all if you do +2 on i.

Instead do i*2 on the places that uses i.

just move all u +0.5 then it will move the texture a half size sideway.

  1. i perform addez suggestion but it has the exact same result.
  2. instead of i < uvArray.length; , i used i*2+1 < uvArray.length; so it doesnt throw exception.
  3. i tried moving the u by 0.5f as empire phoenix suggested. But it also didnt work, its like a random texture was generated.

    U-V when not changed.

    rotate180

    move0.5.

    unshaded

    The texture i use

    [java]

    public void flipUV(Mesh mesh)

    {

    Vector2f uvMoveOffset = new Vector2f(0f,0f);

    float uvRotateAngle = FastMath.PI;

    Vector2f uvScaleAmount = new Vector2f(1f,1f);

    VertexBuffer uv = mesh.getBuffer(Type.TexCoord);

    float[] uvArray = BufferUtils.getFloatArray((FloatBuffer) uv.getData());

    for (int i = 0; i*2+1 < uvArray.length; i++)

    {

    float u = uvArray[i*2];

    float v = uvArray[i*2 + 1];

    //Translation by uvMoveOffset

    u = u + uvMoveOffset.x ;

    v = v + uvMoveOffset.y ;

    //Rotation by uvRotateAngle

    u = u * FastMath.cos(uvRotateAngle) - v * FastMath.sin(uvRotateAngle);

    v = u * FastMath.sin(uvRotateAngle) + v * FastMath.cos(uvRotateAngle);

    //Scale by uvScaleAmount

    u = u * uvScaleAmount.x ;

    v = v * uvScaleAmount.y ;

    uvArray[i*2] = u ;

    uvArray[i*2+1] = v ;

    }

    mesh.setBuffer(Type.TexCoord, 2, uvArray);

    }[/java]

Try this one:

[java]public void flipUV(Mesh mesh)

{

VertexBuffer uv = mesh.getBuffer(Type.TexCoord);

float[] uvArray = BufferUtils.getFloatArray((FloatBuffer) uv.getData());

float[] uvArrayNew = new float[uvArray.length];

for (int i = 0; i < uvArray.length; i ++)

{

float u = uvArray[uvArray.length-i2];

float v = uvArray[uvArray.length-i
2 + 1];

float theta = FastMath.PI;

uvArrayNew[i*2] = u;

uvArrayNew[i*2+1] = v;

}

mesh.setBuffer(Type.TexCoord, 2, uvArrayNew);

}[/java]

Im not sure, But I think this one should mirror the array…



But if thats not what you want, then I suggest that you still make a new uvArray for storing the data. Do not edit the same ur using as source, it will give unexpected results i think…

@tralala Just by looking at the pictures you posted it seems you are still looking at normals that need to be inverted, the first pic of the three you posted shows this: Left side probably correct, right side inversed normals. I think your way of flipping normals is incorrect, judging the shading of the model in that picture. Look at the bright and dark parts of the left and right arm, left has dark under, right has dark up. That indicates the faces on the other end of the arm are used, you are looking through the front and see the inner side of the back instead. As a result, you see the textures from the other side of the model, which appears a 180 degree turn. I think you should not touch the texture coordinates, try flipping those normals in another way or skip it and check for changes.



By the way, that black tear in the middel is supposed to be there? Could be an anomaly from the same problem, looking through the model and at the other end end up having the back side of another face, thus getting through again, but that’s hard to spot on this pic.

Hello,

  1. when i exported the model i didnt cap the holes in the middle, because i though jme will automatically fix them, like 3d studio max does. Do i have to weld them in Jme?
  2. it could be the normals, but from the picture with white material we can see they are ok.
  3. i will refresh my maths so that i can flip the uvs, i expect today to fix it.



    Original front 643000 polys

    Original back 643000 polys

    Optimized front 500 polys

    Optimized back 500 polys

When i press the ‘z’ button it is supposed to rotate the uv texture coordinates by 0.01. I tried this to find the correct uv rotation/translation/scale for my model.



i try to change the uv’s in simpleUpdate. However it throws this exception:



SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]

java.lang.UnsupportedOperationException: Data has already been sent. Cannot setupData again.

at com.jme3.scene.VertexBuffer.setupData(VertexBuffer.java:465)

at com.jme3.scene.Mesh.setBuffer(Mesh.java:873)

at com.jme3.scene.Mesh.setBuffer(Mesh.java:879)

at max.TestSymmetry.flipUV(TestSymmetry.java:146)

at max.TestSymmetry.simpleUpdate(TestSymmetry.java:411)

at com.jme3.app.SimpleApplication.update(SimpleApplication.java:248)

at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:144)

at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:173)

at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:218)

at java.lang.Thread.run(Thread.java:662)



I dont understand why this happen. SimpleUpdate is called only once per update so why does it throw an exception

Seems very odd since its in simpleUpdate :confused:

Does SimpleApplication offer another simpleUpdate() method that happens before the rendering ? So that it doesnt crash when changing the uvs ?