Horde3D

Next-Generation Graphics Engine
It is currently 23.11.2024, 00:25

All times are UTC + 1 hour




Post new topic Reply to topic  [ 8 posts ] 
Author Message
PostPosted: 05.08.2008, 22:02 
Offline

Joined: 15.06.2008, 11:21
Posts: 166
Location: Germany
The last days I tried to get horde working with my engine and so far only one direct blocker showed: I couldn't get the terrain to work with my physics.

After some time I notices an irregularity (well, however you call that) in the height data:
http://img145.imageshack.us/my.php?image=stepgb7.png
(look at the flat area where one pixel on the heightmap gets repeated)

I quickly replaced this hack with a better solution (imho):
I just changed it so that only the last pixel now gets repeated, therefore easily allowing to use the terrain because now the error isn't visible any more (and imho this is the best solution unless you allow 2^n+1-Heightmaps.

Patch:
Code:
Index: Source/terrain.cpp                                                   
===================================================================         
--- Source/terrain.cpp  (Revision 31)                                       
+++ Source/terrain.cpp  (Arbeitskopie)                                     
@@ -177,9 +177,9 @@                                                         
                                        if( u == 0 ) s = 0.0f; else if( u == size - 1 ) s = 1.0f;       // Skirt
 
                                        float *vertHeight = &terrain->_heightArray[v * size + u];               
-                                       const float newU = (s * scale + minU) * (terrain->_hmapSize - 1) + 0.5f;
-                                       const float newV = (t * scale + minV) * (terrain->_hmapSize - 1) + 0.5f;
-                                       uint32 index = ((int)newV * terrain->_hmapSize + (int)newU );           
+                                       const float newU = (s * scale + minU) * (terrain->_hmapSize) + 0.5f;   
+                                       const float newV = (t * scale + minV) * (terrain->_hmapSize) + 0.5f;   
+                                       uint32 index = ((int)newV * (terrain->_hmapSize + 1) + (int)newU );     
 
                                        *vertHeight = terrain->_heightData[index] / 65535.0f;                   
 
@@ -312,7 +312,7 @@                                                                                             
                        hmap.getWidth() == 2048 || hmap.getWidth() == 4096 || hmap.getWidth() == 8192) )       
                {                                                                                               
                        _hmapSize = hmap.getWidth();                                                           
-                       _heightData = new unsigned short[_hmapSize * _hmapSize];                               
+                       _heightData = new unsigned short[(_hmapSize + 1) * (_hmapSize + 1)];                   
 
                        float *pixels = hmap.downloadImageData();                                               
 
@@ -326,10 +326,25 @@                                                                                           
                                        height = (unsigned short)(clamp( pixels[(i * _hmapSize + j) * 4], 0, 1 ) * 255 * 256 +
                                                clamp( pixels[(i * _hmapSize + j) * 4 + 1], 0, 1 ) * 255);                   
 
-                                       _heightData[i * _hmapSize + j] = height;                                             
+                                       _heightData[i * (_hmapSize + 1) + j] = height;                                       
                                }                                                                                             
+                       }                                                                                                     
+                       // Fill in last rows (just repeat last texture pixels)                                               
+                       for( uint32 i = 0; i < _hmapSize; ++i )                                                               
+                       {                                                                                                     
+                               unsigned short height;                                                                       
+                                                                                                                             
+                               // Decode 16 bit data from red and green channels                                             
+                               height = (unsigned short)(clamp( pixels[(i * _hmapSize + _hmapSize - 1) * 4], 0, 1 ) * 255 * 256 +
+                                       clamp( pixels[(i * _hmapSize + _hmapSize - 1) * 4 + 1], 0, 1 ) * 255);                   
+                                                                                                                                 
+                               _heightData[i * (_hmapSize + 1) + _hmapSize] = height;                                           
                        }                                                                                                         
-                                                                                                                                 
+                       for( uint32 i = 0; i < _hmapSize + 1; ++i )                                                               
+                       {                                                                                                         
+                               _heightData[_hmapSize * (_hmapSize + 1) + i] = _heightData[(_hmapSize - 1) * (_hmapSize + 1) + i];
+                       }                                                                                                         
+                                                                                                                                 
                        delete[] pixels;                                                                                         
                        return true;                                                                                             
                }                                                                                                                 
@@ -337,8 +352,8 @@                                                                                                               
                {                                                                                                                 
                        // Init default data                                                                                     
                        _hmapSize = 32;                                                                                           
-                       _heightData = new unsigned short[_hmapSize * _hmapSize];                                                 
-                       memset( _heightData, 0, _hmapSize * _hmapSize );                                                         
+                       _heightData = new unsigned short[(_hmapSize + 1) * (_hmapSize + 1)];                                     
+                       memset( _heightData, 0, (_hmapSize + 1) * (_hmapSize + 1) );                                             
                        Modules::log().writeDebugInfo( "Invalid heightmap data in Terrain node %i", _handle );                   
                        return false;                                                                                             
                }                                                                                                                 
@@ -641,15 +656,15 @@                                                                                                             
 
                dir /= dir.length();                                                                                             
 
-               int x = (int)(startX * _hmapSize);                                                                               
-               int y = (int)(startZ * _hmapSize);                                                                               
+               int x = (int)(startX * (_hmapSize + 1));                                                                         
+               int y = (int)(startZ * (_hmapSize + 1));                                                                         
 
                // Check heightmap with Bresenham algorithm (code based on http://de.wikipedia.org/wiki/Bresenham-Algorithmus)
                int t, dx, dy, incX, incY, pdx, pdy, ddx, ddy, err_step_fast, err_step_slow, err;
 
                // Get deltas in image space
-               dx = (int)((endX - startX) * _hmapSize);
-               dy = (int)((endZ - startZ) * _hmapSize);
+               dx = (int)((endX - startX) * (_hmapSize + 1));
+               dy = (int)((endZ - startZ) * (_hmapSize + 1));
 
                // Check directions
                incX = (dx > 0) ? 1 : (dx < 0) ? -1 : 0;
@@ -673,7 +688,7 @@
                // Init error
                err = err_step_slow / 2;
 
-               float height1 = _heightData[y * _hmapSize + x] / 65535.0f, height2;
+               float height1 = _heightData[y * (_hmapSize + 1) + x] / 65535.0f, height2;
 
                Vec3f pos;
                Vec3f prevPos;
@@ -711,7 +726,7 @@
                                x += pdx;
                                y += pdy;
                        }
-                       height2 = _heightData[y * _hmapSize + x] / 65535.0f;
+                       height2 = _heightData[y * (_hmapSize + 1) + x] / 65535.0f;
 
                        pos.x = x / (float)_hmapSize;
                        pos.z = y / (float)_hmapSize;
@@ -810,9 +825,9 @@
                                        float s = (u - 1) * invScale;
                                        if( u == 0 ) s = 0.0f; else if( u == size - 1 ) s = 1.0f;       // Skirt
 
-                                       const float newU = (s * scale + minU) * (_hmapSize - 1) + 0.4f;
-                                       const float newV = (t * scale + minV) * (_hmapSize - 1) + 0.4f;
-                                       uint32 index = (int)newV * _hmapSize + (int)newU;
+                                       const float newU = (s * scale + minU) * _hmapSize + 0.5f;
+                                       const float newV = (t * scale + minV) * _hmapSize + 0.5f;
+                                       uint32 index = (int)newV * (_hmapSize + 1) + (int)newU;
 
                                        *vertData++ = (s * scale + minU);
 
Index: Source/terrain.h
===================================================================
--- Source/terrain.h    (Revision 31)
+++ Source/terrain.h    (Arbeitskopie)
@@ -141,7 +141,7 @@
 
                BoundingBox *getLocalBBox() { return &_localBBox; }
                float getHeight( float x, float y )
-                       { return _heightData[(int)(y * (_hmapSize - 1) + 0.5f) * _hmapSize + (int)(x * (_hmapSize - 1) + 0.5f) ] / 65535.0f; }
+                       { return _heightData[(int)(y * _hmapSize + 0.5f) * (_hmapSize + 1) + (int)(x * _hmapSize + 0.5f) ] / 65535.0f; }
        };
 }


Last edited by phoenix64 on 05.08.2008, 22:14, edited 2 times in total.

Top
 Profile  
Reply with quote  
PostPosted: 05.08.2008, 22:09 
Offline
Tool Developer

Joined: 13.11.2007, 11:07
Posts: 1150
Location: Germany
I didn't get it yet,... where is the screenshot and why do you have to add 1 row and column to the heightmap?


Top
 Profile  
Reply with quote  
PostPosted: 05.08.2008, 22:13 
Offline

Joined: 15.06.2008, 11:21
Posts: 166
Location: Germany
Sry, Copy+Paste-fail -.-

The screenshot is there now, this problem has been already seen by someone on irc

EDIT: ARGH!
EDIT2: NOW it works -.-


Top
 Profile  
Reply with quote  
PostPosted: 05.08.2008, 23:44 
Offline

Joined: 22.11.2007, 17:05
Posts: 707
Location: Boston, MA
phoenix64 wrote:
The screenshot is there now, this problem has been already seen by someone on irc
I had noticed that problem before, but thought it was something wrong with the heightmap in the samples. I am generating my own power-of-2 heightmaps (directly in engine), and this problem never shows up. Can we confirm that it is a problem in engine, and not in the exporter?

_________________
Tristam MacDonald - [swiftcoding]


Top
 Profile  
Reply with quote  
PostPosted: 06.08.2008, 00:02 
Offline

Joined: 15.06.2008, 11:21
Posts: 166
Location: Germany
For me this also happens with the terrain demo (=with heightmaps not generated by me), which most probably don't have exporter errors. Also I load the same heightmap as an ODE trimesh, there I don't get that problem (=the heights begin to differ at the place where Horde3D duplicates a row of pixels).


Top
 Profile  
Reply with quote  
PostPosted: 06.08.2008, 07:01 
Offline
Tool Developer

Joined: 13.11.2007, 11:07
Posts: 1150
Location: Germany
I submitted the patch to the SVN. I can confirm that this solves gap problems within the terrain sample. But I must admit that I didn't understand in detail why this solves the problem. Currently I don't have time to take a more detailed look at it.
I hope it is indeed a problem in the code and not only in the sample's heightmap data. Nevertheless thanks to phoenix for investigating the problem.


Top
 Profile  
Reply with quote  
PostPosted: 06.08.2008, 11:19 
Offline

Joined: 15.06.2008, 11:21
Posts: 166
Location: Germany
The problem is because of rounding errors, it tries to apply 2^n values to 2^n+1 vertices:
Image
(At least that's my understanding of it. Sry for the crappy image, but I hope it makes it more clear)


Top
 Profile  
Reply with quote  
PostPosted: 06.08.2008, 12:07 
Offline
Tool Developer

Joined: 13.11.2007, 11:07
Posts: 1150
Location: Germany
That makes sence, although I though we replicated the original border pixels already. Seems like this was not the case, or we missed something. If I have some time in the future, I will have a further look at it. But thanks again for the patch and the illustrative image ( it is absolutely not crappy :-) )


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

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 22 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