gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS development > [RESOLVED!] Odd polygon clipping behavior...

#103553 - Izhido - Fri Sep 22, 2006 8:08 pm

Hi! Me, again :)

First, I'd like to apologize in advance if this was already asked before. You see, English is not my native language, and I'm just a newbie on the DS scene, so no matter how hard I try, sometimes I can't seem to find previously posted answers to issues I'm having with my programs. And, sometimes, looking at how quick you answer my posts, I feel like I should have tried harder to find the answer by myself :).

Now, on to the issue:

This program:

Code:

#include <nds.h>

extern "C"
int main()
{
   bool IsRunning;
   float i;
   float j;

   powerON(POWER_ALL);
   videoSetMode(MODE_0_3D);
   glViewPort(0,0,255,191);
   glClearColor(0,0,0);
   glClearDepth(0x7FFF);
   IsRunning = true;
   while(IsRunning)
   {
      glReset();
      glPolyFmt(POLY_ALPHA(31) | POLY_CULL_NONE);
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      gluPerspective(36.0, 256.0 / 192.0, 0.01, 6.4);
      glMatrixMode(GL_MODELVIEW);
      glPushMatrix();
      glLoadIdentity();
      glTranslatef(0,-1,0);
      glBegin(GL_TRIANGLES);
      for(i = -4; i < 4; i++)
      {
         for(j = -4; j < 4; j++)
         {
            glColor3f(0.8,0.1,0.1);
            glVertex3f(i, 0, j);
            glVertex3f(i + 1, 0, j);
            glVertex3f(i + 1, 0, j + 1);
            glColor3f(0.1,0.1,0.8);
            glVertex3f(i + 1, 0, j + 1);
            glVertex3f(i, 0, j + 1);
            glVertex3f(i, 0, j);
         };
      };
      glEnd();
      glPopMatrix(1);
      glFlush();
      swiWaitForVBlank();
   };
}


was compiled with the latest devkitPro as of today (Sep. 12, 2006). And this is what my DS shows at the top screen:

(Link to where the image's posted:)
http://img217.imageshack.us/my.php?image=onhardwaremk5.png

The image was actually taken from emulation, but it shows exactly what is seen in current hardware.

Any idea what could be happening here? The program (if I did it correctly) should draw a 8x8 "floor", of which I should see a 4x8 zone, since the camera's at center of it, at 1 unit above the "floor". However, many of the tiles at the left of the screen are not there... like they were clipped away from the scene. Why's that?

This program was meant to illustrate an issue on a project I'm currently working on, where this odd clipping behavior also occurs. I have two versions of the code, one for Windows, one for DS. The GL code for both versions is the same, save for one line:

DS:
Code:
gluPerspective(36.0, 256.0 / 192.0, 0.01, 6.4);


Windows:
Code:
gluPerspective(72.0, 256.0 / 192.0, 0.01, 6.4);


Would this change have any impact on what I'm seeing at my DS? Actually, I was forced into doing the change because, if I used the Windows version on the DS, the perspective of the scene would appear way too distorted. Would this affect somehow the way polygon clipping works?

I'm stuck at this point. I can't think of any workarounds for this. Any help will be greatly appreciated!

EDIT: Changed the URL of the image. Thanks, Lick.


Last edited by Izhido on Tue Sep 26, 2006 12:08 am; edited 2 times in total

#103554 - Lick - Fri Sep 22, 2006 8:15 pm

"Sorry, but you do not have permission to use this feature. If you are not logged in, you may do so using the form below if available."

Could you upload the image to ImageShack.us or something?
_________________
http://licklick.wordpress.com

#103561 - Izhido - Fri Sep 22, 2006 8:52 pm

Yep! Done.

http://img217.imageshack.us/my.php?image=onhardwaremk5.png

Apologies for the inconvenience.

#103590 - john_ward - Fri Sep 22, 2006 10:32 pm

Hi Izhido,

I've played about with your code - if you change the 3rd parameter (distance from viewer to near clipping plane) of your gluPerspective call to 0.025 (instead of 0.01), I think you get the desired result:

gluPerspective(36.0, 256.0 / 192.0, 0.025, 6.4);

Why? Sorry, don't know - maybe somebody else can help with the explanation...
_________________
Michael, I've got the pistols

#103600 - Izhido - Fri Sep 22, 2006 11:18 pm

Yep. Verified... almost. The last tile at the left was still missing... so I changed the 0.025 to 0.04, and guess what? All tiles were shown... by now :) Thanks a lot, john!

Hmm... I'm conscious that DS's 3D hardware is not very flexible, what with 16-bit fixed-point vertex coords, colors, 32-bit matrix component values, and so on. However, I'm not really convinced the hardware is to blame for this... um... let's call it "extreme clipping" :) After all, emulation showed that too... Can someone here illustrate us about that?

#103707 - HyperHacker - Sat Sep 23, 2006 11:44 pm

A good emulator will show exactly what the hardware does.
_________________
I'm a PSP hacker now, but I still <3 DS.

#103804 - tepples - Sun Sep 24, 2006 7:19 pm

True, but a good emulator is not available to the public.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#104014 - Izhido - Tue Sep 26, 2006 12:26 am

Hey! I think I finally found an answer for this issue. libnds's gluPerspective(), it seems, has a bug. And, to be honest, it's not the author's fault. I think it has to do with the calculations behind the gluPerspective() function, that when done in fixed point, probably using hardware's sin() & cos() functions (not sure, I'm just theorizing here...), they give us a not very appropiate projection matrix.

How do I know that's what happened? Easy... I discarded the gluPerspective() call, and implemented all the calculations myself, with my own trigonometric functions. And it worked!!! :)

So, here it is the new (and... improved???) program with the issue corrected, for your coding pleasure (hehe). Beware... it growed a little bit :)

Code:

#include <nds.h>

#define Pi 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679

extern "C"
double Sin(double Angle)
{
   bool Positive;
   double Degree;
   double Numerator;
   double Denominator;
   double Result;

   while(Angle < (-Pi))
   {
      Angle = Angle + Pi;
   };
   while(Angle > Pi)
   {
      Angle = Angle - Pi;
   };
   Positive = true;
   Degree = 1;
   Numerator = Angle;
   Denominator = 1;
   Result = Angle;
   while(Degree < 9)
   {
      Positive = !Positive;
      Degree = Degree + 1;
      Numerator = Numerator * Angle;
      Denominator = Denominator * Degree;
      Degree = Degree + 1;
      Numerator = Numerator * Angle;
      Denominator = Denominator * Degree;
      if(Positive)
      {
         Result = Result + (Numerator / Denominator);
      } else
      {
         Result = Result - (Numerator / Denominator);
      };
   };
   return Result;
}

extern "C"
double Cos(double Angle)
{
   bool Positive;
   double Degree;
   double Numerator;
   double Denominator;
   double Result;

   while(Angle < (-Pi))
   {
      Angle = Angle + Pi;
   };
   while(Angle > Pi)
   {
      Angle = Angle - Pi;
   };
   Positive = true;
   Degree = 0;
   Numerator = 1;
   Denominator = 1;
   Result = 1;
   while(Degree < 10)
   {
      Positive = !Positive;
      Degree = Degree + 1;
      Numerator = Numerator * Angle;
      Denominator = Denominator * Degree;
      Degree = Degree + 1;
      Numerator = Numerator * Angle;
      Denominator = Denominator * Degree;
      if(Positive)
      {
         Result = Result + (Numerator / Denominator);
      } else
      {
         Result = Result - (Numerator / Denominator);
      };
   };
   return Result;
}

extern "C"
int main()
{
   bool IsRunning;
   float i;
   float j;
   float f;
   m4x4 m;
   float near;
   float far;

   powerON(POWER_ALL);
   videoSetMode(MODE_0_3D);
   glViewPort(0,0,255,191);
   glClearColor(0,0,0);
   glClearDepth(0x7FFF);
   IsRunning = true;
   while(IsRunning)
   {
      glReset();
      glPolyFmt(POLY_ALPHA(31) | POLY_CULL_NONE);
      glMatrixMode(GL_PROJECTION);
      f = Cos(( 72.0 * Pi)/360) / Sin(( 72.0 * Pi)/360);
      near = 0.01;
      far = 6.4;
      m.m[0] = floattof32(f / (256.0 / 192.0));
      m.m[1] = floattof32(0);
      m.m[2] = floattof32(0);
      m.m[3] = floattof32(0);
      m.m[4] = floattof32(0);
      m.m[5] = floattof32(f);
      m.m[6] = floattof32(0);
      m.m[7] = floattof32(0);
      m.m[8] = floattof32(0);
      m.m[9] = floattof32(0);
      m.m[10] = floattof32((near + far) / (near - far));
      m.m[11] = floattof32(-1);
      m.m[12] = floattof32(0);
      m.m[13] = floattof32(0);
      m.m[14] = floattof32((2 * near * far) / (near - far));
      m.m[15] = floattof32(0);
      glLoadMatrix4x4(&m);
      glMatrixMode(GL_MODELVIEW);
      glPushMatrix();
      glLoadIdentity();
      glTranslatef(0,-1,0);
      glBegin(GL_TRIANGLES);
      for(i = -4; i < 4; i++)
      {
         for(j = -4; j < 4; j++)
         {
            glColor3f(0.8,0.1,0.1);
            glVertex3f(i, 0, j);
            glVertex3f(i + 1, 0, j);
            glVertex3f(i + 1, 0, j + 1);
            glColor3f(0.1,0.1,0.8);
            glVertex3f(i + 1, 0, j + 1);
            glVertex3f(i, 0, j + 1);
            glVertex3f(i, 0, j);
         };
      };
      glEnd();
      glPopMatrix(1);
      glFlush();
      swiWaitForVBlank();
   };
}


As for the final screenshot, well, I think you'll have to build it and see it for yourselves... :)

Thanks everyone for your patience!