Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spheres falling through edge of Heightfield #301

Open
dcrosby42 opened this issue Sep 3, 2016 · 10 comments
Open

Spheres falling through edge of Heightfield #301

dcrosby42 opened this issue Sep 3, 2016 · 10 comments

Comments

@dcrosby42
Copy link

Doing some simple experiments rolling a ball around on a Heightfield, my sphere consistently falls through the surface as it approaches one particular edge of the hf shape. It seems like the sphere gets within roughly 1/2 the distance of one spacing unit then drops through. The other edges of the hf behave fine. (In my personal code the failing edge seems to be on the x+ side, but in my modified fork of demos/heightfield.html, it's the y+ edge, front-facing in the demo.)

Version of canon.js: master @ 569730f (v0.6.2-66-gff9364b)

I vaguely suspect a bug in Heightfield pillar construction, but I haven't seen any glaring numerical errors in the pillar vertices, though I admit to only a loose understanding of shape collision internals. I worry more that I'm using bad parameters/sizes which trigger unexpected collision behavior.

I noticed this other heightfield issue #149, but I'm not seeing any JS console errors.

Anybody else encounter this (or know how to fix/avoid)?

@dcrosby42
Copy link
Author

dcrosby42 commented Sep 3, 2016

(Possibly related)

Using a Heightfield shaped as a slightly convex mound, dropping Spheres of radius to 0.1... and noticed a decent number of the spheres dropping straight through the surface. I haven't pin-pointed the locations of the individual failures, but I wonder if they're dangerously close to the pillar vertices inside the hf Shape?

These spheres do not drop through if the Heightfield is perfectly flat, eg, height=1 for all values in matrix.

(testing on Chrome ~52 and Firefox ~48 on OS X)

@that-ben
Copy link

Been experiencing this issue for almost a year. To my understanding, this is a library bug and I never really found a proper workaround, except continuously ray tracing the object and forcing its Y position above the plane when it goes under the heightfield, which is obviously only a temporary quick fix until the library picks up the slack.

@msadev
Copy link

msadev commented Nov 24, 2016

You should do this instead of raytracing.

getTerrainHeightAt = function(xPos, yPos, heightmap, tilesize){
		
	var x = Math.floor(xPos / tilesize),
	y = Math.floor(yPos / tilesize),
			
	xPlusOne = x + 1,
	yPlusOne = y + 1,
			
	triY0 = heightmap[x, y],
	triY1 = heightmap[xPlusOne, y],
	triY2 = heightmap[x, yPlusOne],
	triY3 = heightmap[xPlusOne, yPlusOne],
			
	height = 0.0,
	sqX = (xPos / tilesize) - x,
	sqY = (yPos / tilesize) - y;
			
	if ((sqX + sqY) < 1) {
		height = triY0;
		height += (triY1 - triY0) * sqX;
		height += (triY2 - triY0) * sqY;
	} else {
		height = triY3;
		height += (triY1 - triY3) * (1.0 - sqY);
		height += (triY2 - triY3) * (1.0 - sqX);
	}
	return height;
}

With something like
if(body.position.z < height) body.position.z = height;

Credits go to this C version

@that-ben
Copy link

Looks legit, but do you have performance improvement stats against direct raytracing? I see the solution you posted also accounts for smoothing slopes which is good.

@msadev
Copy link

msadev commented Nov 25, 2016

I use it to place a lot of objects on my heightfield too, and there's no comparison in terms of performance.

@that-ben
Copy link

that-ben commented Nov 25, 2016

No yes OK, I understand, but I meant what's the performance gain in regards to raytracing from camera to heightfield a couple times per second. I was not refering to generating a terrain and raytracing 10000 times per heightfield chunk; I wouldn't use raytracing to place vegetation on the terrain, since I generate it in the same loop as the heightfield vertices themselves and therefore, there is absolutely NO calculation required, obviously, as opposed to the camera's location, which is dynamic.

But either way, I guess you're right, even if it saves 0.001% it's still better than nothing as an improvement.

@msadev
Copy link

msadev commented Nov 25, 2016

I'm sure it's way more than 0.001% because you dont need a built mesh to intersect with, and you dont need any matrix operations to do the calculation.

Unfortunatly, I don't have time to create a fiddle to compare right now... I'll try to create one during next days.

Of course, I still use raycasting for a lot of things like bullets or contextual actions.

there is absolutely NO calculation required

How do you get the exact height between 3 vertices ?

@that-ben
Copy link

that-ben commented Nov 25, 2016

In my app, the vegetation is always on a vertex, therefore, there's no average to calculate. By 0.001% (exageration of course) I was refering to the fps gain, not the actual gain per call, since we do not need to raytrace on every frame. I say raytracing maybe twice a second is enough in most typical cases, but it may vary obviously.

Also, the real question here is: if you can successfully reposition the camera when it falls through the floor by using a simple Math function, how come the physics engine fails at it? I don't understand that, which is also the OP question I think.

@msadev
Copy link

msadev commented Nov 25, 2016

If

we do not need to raytrace on every frame

Id say the fps gain is about zero.

Also, the real question here is: if you can successfully reposition the camera when it falls through the floor by using a simple Math function, how come the physics engine fails at it? I don't understand that, which is also the OP question I think.

I guess the engine use a different approach to handle contacts, which is partially broken on this specific CANNON.Heightfield

@that-ben
Copy link

that-ben commented May 6, 2017

I've had more time last week to fiddle around with this problem and I have found a perfectly working solution to this problem a lot of people are talking about. The library does something weird when creating pillars and for some reason @schteppe might be able to explain, on the X+ edge of the heightfield, the very last column (so say in a 10x10 matrix, 10x0, 10x1, 10x2, etc...) will be missing. It only does that for the X+ edge. X-, Z-, Z+ edges all are perfectly aligned and all pillars are there.

The solution I found that works PERFECTLY is to STITCH the last X+ column with whatever heightfield you have immediately following... or if you only have 1 heightfield, then just extend all along the X+ axis with the same value a second time. So basically if you have a matrix of heightfields, then the X+ column of the left heightfield has to be the same values of the X- column of the right heightfield. This makes a seam and I know there's a little bit of "Z-fighting" but it does not seem to reduce performance for me and everything works perfectly. The camera never ever bounces or falls through the floor anymore. This was super annoying and it took a while to find out, because even the body2mesh() function would draw it as the physics body was supposed to be BUT IT'S REALLY NOT, so it's clear to me that there's a bug. Also if it was not a bug, it would do that on the other axis (Z+), which it does not.

If you take a look at the shape array property of the body using the browser's console, you'll discover that the array is 1 index short, so in my example, for a 10x10 heightfield, the array only has 0 to 8 indices, clearly showing it's missing the last column, therefore pillars are missing all along that axis, I guess.

I have made a visual graph to explain how to solve this issue. I hope it can help future people coming here for the same reason as everybody else who has players falling off the edges of heightfields for no apparent reason.

stitch

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants