Position in world-space

Started by Kaiidyn, November 24, 2010, 01:43:28 PM

Previous topic - Next topic

Kaiidyn

I need to get the position of my object in world space.
and with that I need to get the terrain height (terrain generated with this script: http://www.jpct.net/forum2/index.php/topic,1343.0.html )

Something like


SimpleVector playerPosition = new SimpleVector();
playerPosition.set(player.getPositionInWorldSpace());
ground.getHeight(playerPosition.x, playerPosition.z);


Is this possible?

Kind regards,
Kaiidyn.
Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer's intent but rather is full of crisp abstractions and straightforward lines of control. - Grady Booch

EgonOlsen

There are two ways to get the position in world space. For simple cases, Object3D.getTranslation() will do. If that doesn't work (i.e. center way off from 0,0,0 in object space, object is a child of some other etc), Object3D.getTransformedCenter() will do the trick. It's more expensive though. About the height...you can cast a ray from above down to the ground and use the lenght as an inverted height. Object3D.calcMinDistance(...) does this. However, this isn't cheap when used on complex geometry on Android. Another option would be to store the average height in a simplified data structure (for example a grid with one cell for each 10 units or something) and query that based on the position in world space. Much faster, but you have to create this structure yourself and it won't be as accurate as the other solution.

Kaiidyn

Okay,

I got this working:
terrHeight = ground.calcMinDistance(playerPos, new SimpleVector(0,1,0));

But I get a framerate drop like.... INSANE.
Could you explain the other method a bit more?
As I don't really understand what it is supposed to do (or how to make it)

Kind regards,
Kaiidyn.
Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer's intent but rather is full of crisp abstractions and straightforward lines of control. - Grady Booch

EgonOlsen

You can try to use the calcMinDistance-variant with the additional float value, where you can set a threshold for the distance that actually triggers a complete check. Maybe that helps with frame rate. If not, maybe using an OcTree (for collision detection only) is worth a try.

The other idea goes like this:

Sub-divide the terrain into uniform cells, let's say 10 units per cell. Take the y-value of all vertices in one cell and divide it by the number of vertices, which will give you an average height. Store the results in an array or something. Now determine in which cell the player is located, read the value of that cell from your array and use that as height. As said, it's bloody fast but not that accurate.

   

Kaiidyn

Ah yes, setting the ignoreIfLarger fixes the framerate indeed :D

Thanks for the help (again =p) =]
Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer's intent but rather is full of crisp abstractions and straightforward lines of control. - Grady Booch

Kaiidyn

I placed a SimpleVector at the x and z position of my player, and the y will always be 0,
I did this to get the actual height of the terrain at x,z.
So that when the SimpleVector is above the terrain, it should return 25 and below the terrain a -25 or whatever
then negativating (as far as thats a word) would return the actual terrain height.
The calcMinDistance does not work when 'looking at' the bottom of a vertex (eg, not dualsided)

terrHeightUp = ground.calcMinDistance(heightCalcPos, new SimpleVector(0,-1,0), 100); // always 2147483647
terrHeightDown = ground.calcMinDistance(heightCalcPos, new SimpleVector(0,1,0), 100);


The terrHeightUp should be when the SimpleVector (heightCalcPos) is below the terrain and return the terrein height in negative value.
but as the terrain is not dual sided it looks straight through it and always returning 2147483647.

Is there a (simple) solution for this?
Or should I make the terrain dualsided (cpu and memory eating process), if so, how?

Current terrain generating script:
public class Terrain {

//private static float[][] terrain = new float[128][128];
//private static Object3D ground = null;

public static Object3D Generate(int X_SIZE, int Z_SIZE, TextureManager tm, String TextureID){
/** Generate ground **/
//int X_SIZE = 128;
//int Z_SIZE = 128;
float[][] terrain = new float[X_SIZE][Z_SIZE];

for (int x = 0; x < X_SIZE; x++) {
for (int z = 0; z < Z_SIZE; z++) {

terrain[x][z] = -20 + (float) Math.random() * 40f; // Very simple....
}
}
for (int x = 0; x < X_SIZE - 1; x++) {
for (int z = 0; z < Z_SIZE - 1; z++) {
terrain[x][z] = (terrain[x][z] + terrain[x + 1][z] + terrain[x][z + 1] + terrain[x + 1][z + 1]) / 4;
}
}
Object3D ground = new Object3D(X_SIZE * Z_SIZE * 2);

float xSizeF = (float) X_SIZE;
float zSizeF = (float) Z_SIZE;

int id = tm.getTextureID(TextureID);

for (int x = 0; x < X_SIZE - 1; x++) {
for (int z = 0; z < Z_SIZE - 1; z++) {
/**
* We are now taking the heights calculated above and build the
* actual triangles using this data. The terrain's grid is fixed
* in x and z direction and so are the texture coordinates. The
* only part that varies is the height, represented by the data
* in terrain[][]. jPCT automatically takes care of vertex
* sharing and mesh optimizations (this is why building objects
* this way isn't blazing fast...but it pays out in the
* end...:-)) The Mesh is build with triangle strips in mind
* here. The format for these strips is equal to that of
* OpenGL's triangle strips.
*/

TextureInfo ti = new TextureInfo(id, (x / xSizeF), (z / zSizeF), ((x + 1) / xSizeF), (z / zSizeF), (x / xSizeF), ((z + 1) / zSizeF));
ground.addTriangle(new SimpleVector(x * 10, terrain[x][z], z * 10), new SimpleVector((x + 1) * 10, terrain[x + 1][z], z * 10),
new SimpleVector(x * 10, terrain[x][z + 1], (z + 1) * 10), ti);

ti = new TextureInfo(id, (x / xSizeF), ((z + 1) / zSizeF), ((x + 1) / xSizeF), (z / zSizeF), ((x + 1) / xSizeF), ((z + 1) / zSizeF));
ground.addTriangle(new SimpleVector(x * 10, terrain[x][z + 1], (z + 1) * 10), new SimpleVector((x + 1) * 10, terrain[x + 1][z], z * 10), new SimpleVector((x + 1) * 10,
terrain[x + 1][z + 1], (z + 1) * 10), ti);
}
}

return ground;
}
}


Optional:
I would like to use height-maps instead of randomly generated terrain.
How would I go on about that?

Kind regards,
Kaiidyn.
Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer's intent but rather is full of crisp abstractions and straightforward lines of control. - Grady Booch

EgonOlsen

Why not move the starting point of the calculation above the highest possible terrain height and calculate the min. distance from there?

Kaiidyn

Ah yes ofcourse, why didn't I come up with that lol.
That's working now. :)

About the heightmap, I managed to import a raw image but white is 0 and black is -1 and grayscales are between 1 and 255 or something.
How can I convert that to usable values for height?

Kind regards,
Kaiidyn.
Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer's intent but rather is full of crisp abstractions and straightforward lines of control. - Grady Booch

EgonOlsen

I've never used a height map, but i think that simply iterating over the pixel data and creating a uniform mesh grid with the height based on the pixel's color should do the trick. Maybe with some damping applied...