Horde3D

Next-Generation Graphics Engine
It is currently 25.11.2024, 00:00

All times are UTC + 1 hour




Post new topic Reply to topic  [ 10 posts ] 
Author Message
PostPosted: 17.05.2008, 13:43 
Offline

Joined: 14.04.2008, 15:06
Posts: 183
Location: Germany
TerrainNode::checkIntersection does not work for rays perpendicular to the terrain. For rays with a direction nearly perpendicular to the surface it fails most of the time, too.


Top
 Profile  
Reply with quote  
PostPosted: 28.05.2008, 13:35 
Offline
Tool Developer

Joined: 13.11.2007, 11:07
Posts: 1150
Location: Germany
Although I could hardly reproduce the problem, it's true that there would be a problem for not only perpendicular rays but also for those which are parallel to the Z-Axis. So I think the following patch should solve this issue. Could anyone confirm this?

Code:
Index: terrain.cpp
===================================================================
--- terrain.cpp   (revision 20)
+++ terrain.cpp   (working copy)
@@ -676,8 +676,21 @@
       float height1 = _heightData[y * _hmapSize + x] / 65535.0f, height2;
 
       Vec3f pos;
-      Vec3f prevPos( startX, (dir.y * (startY - orig.z) + dir.z * orig.y) / dir.z, startY );
-
+      Vec3f prevPos;
+      
+      // Check for perpendicular ray
+      if( abs(dir.z) < 0.00001f && abs(dir.x) < 0.00001f )
+      {
+         if( (height1 < orig.y && height1 > dir.y) || (height1 > orig.y && height1 < dir.y) )
+            return true;
+         else
+            return false;
+      }
+      else if( abs(dir.z) < 0.00001f)
+         prevPos = Vec3f( startX, (dir.y * (startX - orig.x) + dir.x * orig.y) / dir.x, startY );
+      else
+         prevPos = Vec3f( startX, (dir.y * (startY - orig.z) + dir.z * orig.y) / dir.z, startY );
+            
       for( t=0; t < err_step_slow; ++t ) // error_step_slow is equal to the number of pixels to be checked
       {
          // Update error
@@ -699,7 +712,11 @@
 
          pos.x = x / (float)_hmapSize;
          pos.z = y / (float)_hmapSize;
-         pos.y = (dir.y * (pos.z - orig.z) + dir.z * orig.y) / dir.z;
+         // Calculate y value based on the fraction of the current position on the direction vector                  
+         if( abs(dir.z) < 0.00001f)
+            pos.y = (dir.y * (pos.x - orig.x) + dir.x * orig.y) / dir.x;
+         else
+            pos.y = (dir.y * (pos.z - orig.z) + dir.z * orig.y) / dir.z;
 
          if( prevPos.y >= pos.y && prevPos.y >= height1 && pos.y <= height2 )
          {


Top
 Profile  
Reply with quote  
PostPosted: 29.05.2008, 09:58 
Offline

Joined: 16.04.2008, 04:44
Posts: 2
Location: Taiwan
In my case when abs(dir.z) below something like 0.01f error would occur, so I need to calculate pos.y along longer axis. Codes like:

Code:
if (abs(dir.z) < abs(dir.x))
    pos.y = (dir.y * (pos.x - orig.x) + dir.x * orig.y) / dir.x;
else
    pos.y = (dir.y * (pos.z - orig.z) + dir.z * orig.y) / dir.z;


Above codes work fine with rays parallel to the x-axis or z-axis but not with rays perpendicular to the terrain. Did anyone solve the problem?


Top
 Profile  
Reply with quote  
PostPosted: 29.05.2008, 17:40 
Offline
Tool Developer

Joined: 13.11.2007, 11:07
Posts: 1150
Location: Germany
It should work fine with perpendicular rays too, since this case is handled with the
Code:
if( abs(dir.z) < 0.00001f && abs(dir.x) < 0.00001f )

statement. Maybe the threshold of 0.00001f is to low. You may try 0.01 but this seems to me a little bit high. Does anyone have a better solution?


Top
 Profile  
Reply with quote  
PostPosted: 29.05.2008, 17:44 
Offline

Joined: 14.04.2008, 15:06
Posts: 183
Location: Germany
I'm currently refactoring my own code and can't test it. After that I'll do some tests.


Top
 Profile  
Reply with quote  
PostPosted: 30.05.2008, 21:54 
Offline

Joined: 14.04.2008, 15:06
Posts: 183
Location: Germany
Edit: Ignore post, contains bad ideas.

Volker wrote:
Although I could hardly reproduce the problem, it's true that there would be a problem for not only perpendicular rays but also for those which are parallel to the Z-Axis. So I think the following patch should solve this issue. Could anyone confirm this?

So, refactoring is sufficiently completed :)
Test results:
I had to change all abs calls with fabs calls for gcc otherwise it would not compile (abs is only defined for int and long long).
Further I had to comment out the Liang-Barsky algorithm and use t1 = 0, t2 = 1. That's bad for performance but shouldn't be any problem, or am I missing something?

Then it worked even for test vectors like (0, -10000, 0). :)
Direction vectors like (10000, 0, 0) or (0, 0, 10000) work, too.

Another change in "check for perpendicular ray": the intersection Position is not returned. I added the line
Code:
intsPos = _absTrans * Vec3f(orig.x, height1, orig.z);


Last edited by Codepoet on 30.05.2008, 22:47, edited 1 time in total.

Top
 Profile  
Reply with quote  
PostPosted: 30.05.2008, 22:27 
Offline
Tool Developer

Joined: 13.11.2007, 11:07
Posts: 1150
Location: Germany
Sorry I can't follow you :-)

How do you get the start and end point for the bresenham algorithm if you comment out the Liang Barsky algorithm?


Top
 Profile  
Reply with quote  
PostPosted: 30.05.2008, 22:46 
Offline

Joined: 14.04.2008, 15:06
Posts: 183
Location: Germany
Maybe I'm completely wrong.
I thought that I could omit the line clipping, but now that you mention it and thinking a bit more about the code I don't think that it works.


Top
 Profile  
Reply with quote  
PostPosted: 31.05.2008, 18:24 
Offline

Joined: 14.04.2008, 15:06
Posts: 183
Location: Germany
I've tested your latest fix in svn - for the test vector (0, -10000, 0) it does not work :(
Setting the x and z component to small values like 0.0001 makes it work. Maybe that's still a problem with Liang-Barsky / the t1 > t2 check?


Top
 Profile  
Reply with quote  
PostPosted: 06.06.2008, 16:12 
Offline
Tool Developer

Joined: 13.11.2007, 11:07
Posts: 1150
Location: Germany
You were right, it was a problem with Liang Barsky. I changed the
Code:
if( orig.x < orig.x + dir.x )
...
if (orig.z < orig.z + dir.z)

to
Code:
if( orig.x <= orig.x + dir.x )
...
if (orig.z <= orig.z + dir.z)

and it seems to be fixed

I also integrated the patch for the castRay and fixed the parallel projection in Horde3DUtils::pickNode.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 10 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 9 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group