Here is something that i found related to this…WITH A PATCH!
http://www.zenohm.com/ode.html#dTerrainZ
It also solves the -z coordinate problem too i believe (didn’t read too much of it yet)
Here is something that i found related to this…WITH A PATCH!
http://www.zenohm.com/ode.html#dTerrainZ
It also solves the -z coordinate problem too i believe (didn’t read too much of it yet)
Two questions about terrain:
kevglass: what is your maximum tolerance for the size of your trimesh triangles. My triangles are quite large (10m sides). Subdividing them once seems to help, subdividing them twice seem to make the problem worse. Also, is your height map restricted to +z or -z values?
I see that odejava has a GeomTerrain class that doesn’t seem to do anything. Would it be possible to support the dTerrainY and dTerrainZ patches for ode? I think that would help many of our terrain problems.
what is the status of those patches?
If we can integrate them into our automatic build system then yes, they can go in. I’m not accepting anything in unless the patching agains the ODE CVS is automated, it is time consuming generating a new odejava build with uptodate sources, and I don’t want to make it more so.
The last time I looked at ODE terrain support, it was terrible. Just a patch that someone had done, with no documentation and no source code comments!
But, I agree, this would be most handy if it is supported.
Will.
Nope, no documentation or source code comments
It requres modification of the ODE source:
http://cvs.sourceforge.net/viewcvs.py/opende/ode/contrib/TerrainAndCone/readme.txt?view=markup
Has anyone gotten a TriMesh to work well as a terrain? I’m having all kinds of problems. Any pointers?
I’ve got it working, the tri-mesh is created from a randomly generated height map. One of the Odejava demos has it working with an ASE model.
What’s happening with your attempts?
Will.
The main problem is objects passing through the trimesh. This is understandable for high-velocity objects, but objects with no vertical velocity will pass through in certain places. I am using fairly big triangles (10m sides), so this might be the issue. How big are your triangles? Is there a way to add “padding” to the trimesh? Also, where is this Odejava demo?
Hi!
Just a quick note: I have exactly the same problem - my car in my game passes through some of my trimeshes, and stay on top of others. I’ve no idea what makes it pass through some trimeshes and not others, as the trimeshes are very alike, they are only turned a little compared to each other (i.e. the lengths of the sides of the trimeshes are identical).
I could strip down my “wannabe-game” to a simple example showing the problem, if that could be of any use. (If somebody already has a simple example program showing the problem, I won’t spend my time on that, but otherwise I’ll do it in the weekend!) I don’t know where to upload my source files in that case, though, as I don’t have a home page of my own
Ole
So, nobody interested? Anyway, I’ve done my work and made a little demonstration of my problems. Unfortunately, I cannot post it to this forum, since it would make my post too long (I already tried, yes
). If anybody has an idea about where I can put my code, please send a note.
(The rest of this posting assumes you have my code…)
Take the code and compile it. I’ve put it all in one class, for your convenience. Run it, and feel puzzled
I guess this demo clearly shows that Ode or Odejava has problems with Trimesh collisions, unless I made a basic bummer somewhere in my code.
BTW, I’m using the latest Odejava files available at the Odejava homepage, and I’m running on Linux. If anybody running other versions or using other OS’es don’t see a problem when running my demo, please let me know
Enjoy!
Ole
package collisionproblem;
import javax.vecmath.*;
import org.odejava.*;
import org.odejava.collision.JavaCollision;
import org.odejava.display.DisplayBin;
import org.odejava.xith3d.OdejavaToXith3D;
import org.odejava.xith3d.Xith3DDisplayObject;
import com.xith3d.render.CanvasPeer;
import com.xith3d.render.RenderPeer;
import com.xith3d.render.jogl.RenderPeerImpl;
import com.xith3d.scenegraph.*;
import com.xith3d.scenegraph.Locale;
public class CollisionProblem {
// Number of pieces in the ramp
private int rampPieces = 8;
// Radius of the middle of the ramp
private double circleRadius = 20;
// Width of the ramp
private double rampWidth = 20;
// View
Vector3f viewLocation = new Vector3f(-40f, -40f, 70f);
Vector3f viewCenter = new Vector3f(0f, 0f, 0f);
// Variables that are used as in the Odejava-Xith3d examples
View view;
Locale locale;
BranchGroup scene;
OdejavaToXith3D odejavaToXith;
DisplayBin boundObjects = new DisplayBin();
HashSpace space;
JavaCollision collision;
World world;
private static int rampPartNumber;
public static void main(String[] args) throws Exception {
CollisionProblem problem = new CollisionProblem();
problem.render();
}
public CollisionProblem() {
initXith();
initExample();
initLights();
initXithFromOdejava();
}
private void initXith() {
VirtualUniverse universe = new VirtualUniverse();
view = new View();
universe.addView(view);
locale = new Locale();
universe.addLocale(locale);
scene = new BranchGroup();
locale.addBranchGraph(scene);
// create canvas for our graphics
RenderPeer rp = new RenderPeerImpl();
CanvasPeer cp = rp.makeCanvas(null, 1024, 768, 32, false);
Canvas3D canvas = new Canvas3D();
canvas.set3DPeer(cp);
// Set view
view.addCanvas3D(canvas);
view.getTransform().lookAt(viewLocation, viewCenter,
new Vector3f(0, 0, 1));
}
private void initExample() {
Odejava.getInstance();
world = new World();
world.setGravity(0f, 0f, -9.82f);
space = new HashSpace();
collision = new JavaCollision(world);
createRamps();
}
private void initXithFromOdejava() {
odejavaToXith = new OdejavaToXith3D(boundObjects);
Appearance[] apps = new Appearance[] { createAppearance(1f, 0f, 0f),
createAppearance(0f, 1f, 0f) };
for (int i = 0; i < 200; i++) {
odejavaToXith.addUserAppearance("RampPart" + i, apps[i%2]);
}
odejavaToXith.createTransformGroups(space.getGeoms());
Xith3DDisplayObject.addToScene(boundObjects, scene);
}
private Appearance createAppearance(float r, float g, float b) {
Appearance app = new Appearance();
ColoringAttributes coloring1 = new ColoringAttributes();
coloring1.setColor(r, g, b);
app.setColoringAttributes(coloring1);
return app;
}
private void render() {
while (true) {
// Collide objects in given space
collision.collide(space);
collision.applyContacts();
// Step simulation
world.quickStep(.01f);
boundObjects.updateAll();
view.renderOnce();
// Make sure our CPU's don't need to go in 100% usage :-)
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void initLights() {
Color3f col1 = new Color3f(0.5f, 0.5f, 0.5f);
Transform3D t = new Transform3D();
Vector3f pos1 = new Vector3f(0.0f, 0.0f, 30.0f);
t.set(pos1);
Vector3f dir1 = new Vector3f(pos1);
dir1.negate();
dir1.normalize();
DirectionalLight light1 = new DirectionalLight(col1, dir1);
scene.addChild(light1);
light1.setEnable(true);
}
/**
* Creates Geoms for all the ramp pieces in the world.
*/
private void createRamps() {
for (int i = 0; i < rampPieces; i++) {
createRampGeom(i);
}
}
/**
* Creates Geom for a single ramp piece in the world.
*/
private void createRampGeom(int i) {
Point3f beforeLeft = getInnerPoint(i - 1);
Point3f beforeRight = getOuterPoint(i - 1);
Point3f afterLeft = getInnerPoint(i);
Point3f afterRight = getOuterPoint(i);
int vertexCount = 4;
int indexCount = 2;
float[] vertices = new float[vertexCount * 3];
int[] indices = new int[indexCount * 3];
int beforeLeftIndex = 0;
int beforeRightIndex = 1;
int afterLeftIndex = 2;
int afterRightIndex = 3;
fillVertex(vertices, beforeLeftIndex, beforeLeft);
fillVertex(vertices, beforeRightIndex, beforeRight);
fillVertex(vertices, afterLeftIndex, afterLeft);
fillVertex(vertices, afterRightIndex, afterRight);
fillIndex(indices, 0, beforeLeftIndex, afterRightIndex, afterLeftIndex);
fillIndex(indices, 1, beforeRightIndex, afterRightIndex,
beforeLeftIndex);
String name = "RampPart" + rampPartNumber++;
GeomTriMesh rampGeom = new GeomTriMesh(name, vertices, indices);
space.addGeom(rampGeom);
// Create a couple of spheres, to demonstrate the collision problems
createSphere(beforeLeft, beforeRight, afterRight);
createSphere(beforeLeft, beforeRight, afterLeft);
}
/**
* Creates a sphere in the middle of the 3 given points
*/
private void createSphere(Point3f p1, Point3f p2, Point3f p3) {
GeomSphere sphere = new GeomSphere(1);
Body b = new Body(null, world, sphere);
b.setSphereMass(1, 1);
b.adjustMass(80);
b.setPosition((p1.x + p2.x + p3.x) / 3, (p1.y + p2.y + p3.y) / 3, 7);
space.addBodyGeoms(b);
}
private Point3f getInnerPoint(int i) {
return new Point3f(getInnerX(i), getInnerY(i), 3);
}
private Point3f getOuterPoint(int i) {
return new Point3f(getOuterX(i), getOuterY(i), 3);
}
private float getInnerX(int i) {
return (float) (Math.cos(getAngle(i)) * (circleRadius - (rampWidth / 2)));
}
private float getOuterX(int i) {
return (float) (Math.cos(getAngle(i)) * (circleRadius + (rampWidth / 2)));
}
private float getInnerY(int i) {
return (float) (Math.sin(getAngle(i)) * (circleRadius - (rampWidth / 2)));
}
private float getOuterY(int i) {
return (float) (Math.sin(getAngle(i)) * (circleRadius + (rampWidth / 2)));
}
private double getAngle(int i) {
return (double) i / (double) rampPieces * (double) 2 * Math.PI;
}
private void fillVertex(float[] vertices, int index, Point3f point) {
vertices[index * 3 + 0] = point.x;
vertices[index * 3 + 1] = point.y;
vertices[index * 3 + 2] = point.z;
}
private void fillIndex(int[] indices, int index, int p1, int p2, int p3) {
indices[3 * index + 0] = p1;
indices[3 * index + 1] = p2;
indices[3 * index + 2] = p3;
}
}
Yuippey, I managed to squeeze the demo into a posting small enough for the forum system, hopefully without letting go of too much readability. Please try and compile the above class and just invoke the main method. On my system, the spheres interact with only 2 of the 8 trimeshes, and fall through the rest as if they weren’t there.
It’s pretty easy for you guys to try and alter various parameters in the system. I’ve tried everything I could think of (number of contact points per interaction, surface mode, surface bounce, time steps, etc. etc.), but nothing seems to help.
Anyway, now you have something to play with this weekend. Have fun
Ole
Umm…even more puzzeling…
I have a demo (from the jme site), a box doesn’t pass through it, while a sphere does…It seems that if you have a flat trimesh (i.e a quad), OPCODE cannot detect the depth of intersection with spheres and so they just straight through…
I have also seen some better reliability from collisions if you pass onto the GeomTriMesh the normals of each of the triangles…
Just a little experimentation here and there…
DP
Hi DP!
Thanks for the suggestions. However…
I tried creating boxes instead of spheres, in order to see how they interact with the trimeshes when they fall down. (You can do the same, just alter the createSphere method in my demo.) They interact in exactly the same way with the trimes as the spheres do. And even fall through exactly the same trimeshes.
Setting the normals when creating the trimeshes makes no difference either. Exactly the same behaviour.
A posting on the ODE list looks exactly like this problem:
http://q12.org/pipermail/ode/2005-March/015300.html
However, it’s hard to convince people that it’s an ODE problem, as opposed to wrong usage of ODE:
http://q12.org/pipermail/ode/2005-March/015302.html
So perhaps there’s an obvious mistake somewhere in my code, but I cannot find it. And I cannot find a way to make it even simpler than it is now
Anyway, DP, thanks for your ideas and thoughts. Keep them coming, please
Ole
In the Odejava CarDemo, spheres used to be fine while the boxes would go straight though :-/
Have you tried reversing the winding on the triangles? Make sure that your height (normally Y) is positive.
I managed to get my terrain working just by moving the whole lot up 100 units on the Y axis, and by trying different triangle windings.
I plan to update the Odejava natives soon with the latest from ODE CVS, perhaps we might see an improvement? We can only hope.
Will.
Hi William!
I’ve tried different windings of the triangles, and reversing the direction of the normals. Nothing changes the behaviour. I’ve also tried to translate all of my scenery to various other places to see if that made any change, but I haven’t done that systematically, so there may be a chance there.
I tried to boil down my example to just a single static triangle and a single sphere falling down. The sphere falls down nicely, until it hits the triangle, and then my JVM crashes (a HotSpot error, referring to the native ODE trimesh collision function).
Anyway, before spending too much time on that, I think I’ll just wait for the new release of the ODEJava natives. Thanks for taking your time to compile a new release of those!!
BTW, William, while compiling the new ODEJava natives, do you think you could spend a little time updating the Wiki page on how to compile them? I still haven’t found the Makefile patch (probably because it has moved from the “contrib” folder to the real makefile?), and applying the dCylinder2 patch is not just a matter of following the instructions in the readme file in the “contrib/dCylinder2” folder, I found out. Just a thought, and something I would really appreciate
Kind regards,
Ole
Hi, I didn’t end up recompiling the natves as it turned out nothing had changed
I did however update the docs.
Will.
Weird trimesh troubles indeed. These are my findings regarding this matter. My settings:
ODE v0.2.4.
I’ve tried both trimesh-sphere as well as trimesh-box.
Trimesh being a geom and sphere/box being a body falling towards the trimesh.
Gravity = -9.82y.
HashSpaces don’t like trimeshes with a lot of triangles. I have a mesh with about 2900 triangles and collisions are not detected. However, if I reduce the number of triangles to about 600-700, the collisions are detected fine if vertex coordinates are positive. If coords are negative (especially y-coords), collisions are detected some times.
Simple spaces and quad spaces works with my 2900 triangle mesh, but only if vertex coordinates are positive. In that case, collisions are detected fine.
Anyone else experienced different results for different types of spaces? Could there be a partitioning error of some sort?
I’d like to try the same mesh in ODE to see if I get the same result as with odejava but I haven’t got that running yet since I haven’t got a .obj loader and I dont want to write one. Setting up the mesh in the source isn’t really an option since it will take some 10 thousand lines of vertex and face data to set up the mesh
Hi!
Fancy. Sounds a bit difficult to reproduce for the rest of us, though. I posted a simple example to this thread some time ago, which demonstrates severe problems in sphere-trimesh collision detection. Perhaps my problems are related to my OS (Fedora Core 3), my processor (an AMD Athlon), the version of Java (5.0, but I’ve also tried 1.4.2 which has the same behaviour), or the OdeJava version (newest from the archive, with newest natives, but the behavious is similar with newest OdeJava from the CVS, and also some older OdeJava and native versions from the archive). Or a programming error on my side, though nobody has been able to point it out.
I’ve tried to move the whole scene various combinations of 100 units along the X, Y, and Z axes. The result is weird: In no combination do all the spheres collide correctly, but each sphere changes collision behaviour in various positions.
Since I posted the sample program, I have not had the impression that anybody has tried to compile and run it, although this is a very quick excercise. This could be interesting. Therefore: Is everybody else seeing the same problem as I am, or is it just on my OS, processor, and Java version?
Ole
I haven’t tried your code since I’m not using Xith3d, but perhaps I’ll give it a shot tomorrow. I’d really like to get trimesh-collision working reliable.
Stepsize is also a factor I think, as well as how fast the sphere or box is travelling towards the trimesh.
Lots of variables to play with to get this working
Yes! My terrain works just fine with SimpleSpace and QuadTreeSpace. I guess HashSpace was my problem. I’m using positive and negative x, y, and z coordinates with no problems (yet).
Edit:
It actually seems that I can use all-positive or all-negative z coordinates but not mixed positive and negative z coordinates. Interesting but consistent with what other people are seeing…
Ole, I tried your code now, and yes, only 4 spheres manage to collide properly. I tried moving the trimesh around and doing all sorts of things to it and eventually it did collide but the tuning seems really arbitrary. This is what I did in createRampGeom(…) to get them colliding (dont laugh).
float moveX = 20f;
float moveY = 0f;
beforeLeft.add( new Point3f( moveX, moveY, 0f ));
beforeRight.add( new Point3f(moveX, moveY, 0f ));
afterLeft.add( new Point3f( moveX, moveY, 0f ));
afterRight.add( new Point3f( moveX, moveY, 0f ));
int scaleFactor = 2;
beforeLeft.x = (int) beforeLeft.x *scaleFactor;
beforeLeft.y = (int) beforeLeft.y *scaleFactor;
beforeLeft.z = (int) beforeLeft.z *scaleFactor;
afterLeft.x = (int) afterLeft.x *scaleFactor;
afterLeft.y = (int) afterLeft.y *scaleFactor;
afterLeft.z = (int) afterLeft.z *scaleFactor;
beforeRight.x = (int) beforeRight.x *scaleFactor;
beforeRight.y = (int) beforeRight.y *scaleFactor;
beforeRight.z = (int) beforeRight.z *scaleFactor;
afterRight.x = (int) afterRight.x *scaleFactor;
afterRight.y = (int) afterRight.y *scaleFactor;
afterRight.z = (int) afterRight.z *scaleFactor;
It didn’t work with just vector.scale(scaleFactor) but it did work when I typecasted to int. Pretty obvious huh?
I dont feel like I’m seeing a pattern here when the collision fails, rather it seems very arbitrary.