heres another one what this demo does is 3d rendering on both of the ds`s screens.on the ds it has 2 2d cores and one 3d core wich gives a problem as to how to render 3d on the other screen so i just software renderto the other screen through the 2d core.
now theres a much better way of doing 3d both screens but its complex it goes like this.
1 draw to the main screen through the 3d hardware
2 use the screen capture hardware to grad that image
3 flush the screen and draw your next object the lcd flip and blit your captured object
now theres two main problems with that method it will run at 30 fps and it takes a vram bank away which is 128k which is quite significant.
but with using the screen capture you can also put double the amount of vertices to the screen i think the vertice limit is about 5000 so by doing screen capture you get about 10000 ill post an example soon.
// arm 9 main.c
//----------------------------------------------------------------
//----------------------------------------------------------------
// TWO SCREEN 3D EXAMPLE MADE BY NINO FROM
// EZBOARD PS2 YABASIC PROGRAMING
//----------------------------------------------------------------
// heres a little demo i bashed together this afternoon cause i
// was board and though id see just how good the ds is at pixel
// pushing.and also ive seen a lot of people talking about how
// developers manage 3d on both screens in games so hopefully this
// will give some insight into the matter.
//----------------------------------------------------------------
// hope you guys like this the software rendered 3d was originaly
// created for the gba by jim from ezboard ps2 yabasic as to
// teach us a bit of texture mapping.ive just ported it to the ds
// and enhanced it a little to fully exploit the ds features for
// an example that runs very very fast and acutally only needs
// the call to wait for vblank to keep it locked at 60fps.
// also its all rendered in full screen 16 bit color.
//----------------------------------------------------------------
//----------------------------------------------------------------
#include <nds.h>
#include <math.h>
#include "ferrari_background.h"
#include "background2.h"
#include "texture.h"
#include "texture2.h"
#define TEX_X 128
#define TEX_Y 128
#define SHIFT 8
#define SCALE (1<<SHIFT)
#define TWOPOINTFIVE (0x280<<(SHIFT-8))
typedef struct
{
s32 x;
s32 u;
s32 v;
s32 z;
} EDGE;
s32 zin[360];
s32 coz[360];
typedef struct
{
s32 x,y,z;
} VECTOR;
typedef s32 MATRIX[3][3];
typedef struct
{
u16 face;
s32 z;
} SORTER;
// uv stuff
typedef struct
{
u8 point_index;
s16 u, v;
} VERTEX;
typedef struct
{
VERTEX pt[3];
} FACE;
#define N_FACES 12
#define N_POINTS 8
FACE faces[N_FACES]=
{
{
{{0,0,0},
{2,TEX_X-1,0},
{6,TEX_X-1,TEX_Y-1}},
},
{
{{0,0,0},
{6,TEX_X-1,TEX_Y-1},
{4,0,TEX_Y-1}}
},
{
{{0,0,0},
{1,TEX_X-1,0},
{3,TEX_X-1,TEX_Y-1}}
},
{
{{0,0,0},
{3,TEX_X-1,TEX_Y-1},
{2,0,TEX_Y-1}}
},
{
{{4,0,0},
{6,TEX_X-1,0},
{7,TEX_X-1,TEX_Y-1}}
},
{
{{4,0,0},
{7,TEX_X-1,TEX_Y-1},
{5,0,TEX_Y-1}}
},
{
{{1,0,0},
{0,TEX_X-1,0},
{4,TEX_X-1,TEX_Y-1}}
},
{
{{1,0,0},
{4,TEX_X-1,TEX_Y-1},
{5,0,TEX_Y-1}}
},
{
{{2,0,0},
{3,TEX_X-1,0},
{7,TEX_X-1,TEX_Y-1}}
},
{
{{2,0,0},
{7,TEX_X-1,TEX_Y-1},
{6,0,TEX_Y-1}}
},
{
{{5,0,0},
{1,TEX_X-1,0},
{3,TEX_X-1,TEX_Y-1}}
},
{
{{5,0,0},
{3,TEX_X-1,TEX_Y-1},
{7,0,TEX_Y-1}}
}
};
const VECTOR points[N_POINTS]=
{
{1<<SHIFT,1<<SHIFT,1<<SHIFT},
{1<<SHIFT,1<<SHIFT,-1<<SHIFT},
{1<<SHIFT,-1<<SHIFT,1<<SHIFT},
{1<<SHIFT,-1<<SHIFT,-1<<SHIFT},
{-1<<SHIFT,1<<SHIFT,1<<SHIFT},
{-1<<SHIFT,1<<SHIFT,-1<<SHIFT},
{-1<<SHIFT,-1<<SHIFT,1<<SHIFT},
{-1<<SHIFT,-1<<SHIFT,-1<<SHIFT},
};
VECTOR rotated[N_POINTS];
SORTER sorter[N_FACES];
MATRIX matrix;
u32 count,xbegin,xend;
s32 x_scale = 70<<SHIFT;
s32 y_scale = 70<<SHIFT;
s32 z_scale = 1<<SHIFT;
u16 tilt=0,turn=0,roll=0;
#define SCREENX 256
#define SCREENY 192
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
void plotbackground();
u16* sub_back;
void filltriangle(FACE *);
void setup();
void flip();
void drawQuad(int poly);
int main()
{
powerON(POWER_ALL);
irqInit();
irqSet(IRQ_VBLANK,0);
WAIT_CR=0xe800;
videoSetMode(MODE_5_2D | DISPLAY_BG2_ACTIVE | DISPLAY_BG0_ACTIVE | ENABLE_3D);
videoSetModeSub(MODE_5_2D | DISPLAY_BG2_ACTIVE );
vramSetBankA(VRAM_A_TEXTURE);
vramSetBankB(VRAM_B_MAIN_BG_0x6000000);
vramSetBankC(VRAM_C_SUB_BG);
//---------------------------------------
// D IS ACTUALY A BANK IVE SET UP FOR MY
// SUB SCREEN BACK BUFFER
//---------------------------------------
vramSetBankD(VRAM_D_MAIN_BG_0x6020000);
sub_back=(u16*)(0x6020000);
//---------------------------------------
BG2_CR = BG_BMP16_256x256;
BG2_XDX = 1 << 8;
BG2_XDY = 0;
BG2_YDX = 0;
BG2_YDY = 1 << 8;
BG2_CX = 0;
BG2_CY = 0 << 8;
SUB_BG2_CR = BG_BMP16_256x256;
SUB_BG2_XDX = 1 << 8;
SUB_BG2_XDY = 0;
SUB_BG2_YDX = 0;
SUB_BG2_YDY = 1 << 8;
SUB_BG2_CX = 0;
SUB_BG2_CY = 0 << 8;
int textureID;
int i;
float rotateX = 0.0;
float rotateY = 0.0;
u8 swap;
s32 z;
s32 A,B,C,D,E,F,AD,BD;
u16 p,f,j;
glViewPort(0,0,255,191);
glClearDepth(0x7FFF);
glGenTextures(1, &textureID);
glBindTexture(0, textureID);
glTexImage2D(0, 0, GL_RGB, TEXTURE_SIZE_128 , TEXTURE_SIZE_128, 0, TEXGEN_TEXCOORD, (u8*)texture2);
setup();
dmaCopy(background2,BG_GFX,256*192*2);
while(1)
{
//---------------------------------------------------------------------
// main_displays 3D
//---------------------------------------------------------------------
// THIS WILL ALL BE HARDWARE ACCELERATED USING
// THE DS`S CUSTOM 3D CHIP
//---------------------------------------------------------------------
glReset();
gluPerspective(35, 256.0 / 192.0, 0.1, 40);
gluLookAt(0.0, 0.0, 1.0,0.0,0.0,0.0,0.0, 1.0, 0.0);
glLight(0,RGB15(31,31,31),0,floatov10(-1.0),0);
glLight(1,RGB15(31,0,31),0,floatov10(1) - 1,0);
glLight(2,RGB15(0,31,0),floatov10(-1.0),0,0);
glLight(3,RGB15(0,0,31),floatov10(1.0) - 1,0,0);
glPushMatrix();
glTranslate3f32(0, floatof32(-1), floatof32(-1.5));
glRotateX(rotateX);
glRotateY(rotateY);
glMatrixMode(GL_TEXTURE);
glIdentity();
glMatrixMode(GL_MODELVIEW);
glMaterialf(GL_AMBIENT, RGB15(8,8,8));
glMaterialf(GL_DIFFUSE, RGB15(16,16,16));
glMaterialf(GL_SPECULAR, BIT(15) | RGB15(8,8,8));
glMaterialf(GL_EMISSION, RGB15(5,5,5));
glMaterialShinyness();
glPolyFmt(POLY_ALPHA(31) | POLY_CULL_BACK | POLY_FORMAT_LIGHT0 | POLY_FORMAT_LIGHT1 |
POLY_FORMAT_LIGHT2 | POLY_FORMAT_LIGHT3 ) ;
rotateX += 3;
rotateY -= 3;
glBindTexture(0, textureID);
glBegin(GL_QUAD);
for(i = 0; i < 6; i++)
drawQuad(i);
glEnd();
glPopMatrix(1);
glFlush();
//-------------------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
// sub_displays 3D
//-------------------------------------------------------------------------------------------------
// the code below renders our sub screen 3d in software mode as
// the ds has no 3d support on the sub screen also theres no
// double buffering available on the sub screen so i had to create my own
// by setting bank d to main screen but using it as a backbuffer
// for the sub screen cool ehh!!!
//-------------------------------------------------------------------------------------------------
plotbackground();
//rem prepare the rotation matrix
if (tilt > 359){tilt = 0;}
if (turn > 359){turn = 0;}
if (roll > 359){roll = 0;}
A=coz[tilt];B=zin[tilt];
C=coz[turn]; D=zin[turn];
E=coz[roll];F=zin[roll];
AD=(A*D)>>SHIFT;
BD=(B*D)>>SHIFT;
matrix[0][0]=(C*E)>>SHIFT;
matrix[1][0]=(-C*F)>>SHIFT;
matrix[2][0]=D;
matrix[0][1]=((BD*E)+(A*F))>>SHIFT;
matrix[1][1]=((-BD*F)+(A*E))>>SHIFT;
matrix[2][1]=(-B*C)>>SHIFT;
matrix[0][2]=((-AD*E)+(B*F))>>SHIFT;
matrix[1][2]=((AD*F)+(B*E))>>SHIFT;
matrix[2][2]=(A*C)>>SHIFT;
//rem rotate all the points using the matrix
for (p=0;p<N_POINTS; p++)
{
rotated[p].x = ((matrix[0][0] * points[p].x)>>SHIFT) + ((matrix[0][1] * points[p].y)>>SHIFT) + ((matrix[0][2] * points[p].z)>>SHIFT);
rotated[p].x = (rotated[p].x * x_scale)>>SHIFT;
rotated[p].y = ((matrix[1][0] * points[p].x)>>SHIFT) + ((matrix[1][1] * points[p].y)>>SHIFT) + ((matrix[1][2] * points[p].z)>>SHIFT);
rotated[p].y = (rotated[p].y * y_scale)>>SHIFT;
rotated[p].z = ((matrix[2][0] * points[p].x)>>SHIFT) + ((matrix[2][1] * points[p].y)>>SHIFT) + ((matrix[2][2] * points[p].z)>>SHIFT);
//rem now do the perspective calculation
z = ((1L<<SHIFT)<<SHIFT)/(rotated[p].z + TWOPOINTFIVE);
rotated[p].x = ((SCREENX/2)<<SHIFT) + ((rotated[p].x * z)>>SHIFT);
rotated[p].y = ((SCREENY/2)<<SHIFT) - ((rotated[p].y * z)>>SHIFT);
}
//rem set up the sorting array
for (f=0;f<N_FACES;f++)
{
s32 z0,z1,z2;
u8 p0,p1,p2;
p0 = faces[f].pt[0].point_index;
p1 = faces[f].pt[1].point_index;
p2 = faces[f].pt[2].point_index;
z0 = rotated[p0].z;
z1 = rotated[p1].z;
z2 = rotated[p2].z;
sorter[f].face = f;
sorter[f].z = (z0+z1+z2);
}
do
{
swap= 0;
for (j=0;j<N_FACES-1;j++)
{
if (sorter[j+1].z > sorter[j].z)
{
SORTER tmp;
tmp = sorter[j+1];
sorter[j+1]=sorter[j];
sorter[j]=tmp;
swap = 1;
}
}
} while (swap);
for (f=0;f<N_FACES;f++)
{
u16 face;
face = sorter[f].face;
filltriangle(&faces[face]);
}
tilt = tilt+3;
turn = turn+3;
roll = roll+3;
//rem flip and the screens
flip();
//--------------------------------------------------------------------------------------------
swiWaitForVBlank();
}
return 0;
}
void flip()
{
dmaCopy(sub_back,BG_GFX_SUB,256*192*2);
}
void setup()
{
s32 coza;
for(coza=0;coza<359;coza++)
{
zin[coza] =(s32)(sin(coza/180.0*3.14159)*SCALE);
coz[coza] =(s32)(cos(coza/180.0*3.14159)*SCALE);
}
}
void plotbackground()
{
dmaCopy(ferrari_background,sub_back,256*192*2);
}
#define FSHIFT 16
#define FSCALE (1L<<FSHIFT)
void scan(EDGE *L,EDGE *R, s32 y)
{
s32 z=0,dz,w,s,t;
s32 x0,x1,u,v,du,dv,dx;
u16 *screenptr16;
if (y<0 || y>=160) return;
if (L->x > R->x)
{
EDGE *t=L;
L=R;
R=t;
}
x0=L->x>>FSHIFT;
x1=R->x>>FSHIFT;
dx = x1-x0;
if (!dx) return;
if (x0>=SCREENY)
return;
else if (x0<0)
x0=0;
if (x1<0)
return;
else if (x1>=SCREENX)
x1=SCREENX;
u=L->u;
v=L->v;
du = (R->u - L->u) / dx;
dv = (R->v - L->v) / dx;
dz = (R->z - L->z) / dx;
screenptr16 = sub_back + x0 + y * SCREENX;
while (dx--)
{
dmaCopy(texture + (u>>FSHIFT) + (TEX_X*(v>>FSHIFT)),screenptr16++,2);
u+=du;
v+=dv;
}
}
void filltriangle(FACE *face)
{
s32 xx[3], yy[3], zz[3];
s32 dzL,dzT,dzB;
u8 i0,i1,i2;
s32 dyL, dyT, dyB;
s32 rdyL,rdyT,rdyB;
s32 Y;
s32 dxL, dxT, dxB;
s32 duL, duT, duB;
s32 dvL, dvT, dvB;
EDGE L,R;
yy[0]=rotated[face->pt[0].point_index].y>>SHIFT;
yy[1]=rotated[face->pt[1].point_index].y>>SHIFT;
yy[2]=rotated[face->pt[2].point_index].y>>SHIFT;
xx[0]=rotated[face->pt[0].point_index].x>>SHIFT;
xx[1]=rotated[face->pt[1].point_index].x>>SHIFT;
xx[2]=rotated[face->pt[2].point_index].x>>SHIFT;
zz[0]=rotated[face->pt[0].point_index].z>>SHIFT;
zz[1]=rotated[face->pt[1].point_index].z>>SHIFT;
zz[2]=rotated[face->pt[2].point_index].z>>SHIFT;
i0 = 0;
i1 = 1;
i2 = 2;
if (yy[0]<=yy[1] && yy[0]<=yy[2])
{
//y0 is smallest
if (yy[1]>yy[2])
{
//y1 is largest
i1 = 2;
i2 = 1;
}
else
{
//y2 is largest
}
}
else if (yy[1]<=yy[0] && yy[1]<=yy[2])
{
i0 = 1;
//y1 is smallest
if (yy[0]<yy[2])
{
//y2 is largest
i1 = 0;
}
else
{
//y0 is largest
i1 = 2;
i2 = 0;
}
}
else
{
i0 = 2;
//y2 is smallest
if (yy[1]<yy[0])
{
//y0 is largest
i2 = 0;
}
else
{
//y1 is largest
i2 = 1;
i1 = 0;
}
}
dyL = yy[i2]-yy[i0];
if (dyL==0) return;
rdyL = FSCALE / dyL;
dzL = (zz[i2]-zz[i0]) * rdyL;
dxL = (xx[i2]-xx[i0]) * rdyL;
duL = ( face->pt[i2].u - face->pt[i0].u ) * rdyL;
dvL = ( face->pt[i2].v - face->pt[i0].v ) * rdyL;
dyT = yy[i1]-yy[i0];
L.z=zz[i0]<<FSHIFT;
L.x=xx[i0]<<FSHIFT;
Y=yy[i0];
L.u=(face->pt[i0].u)<<FSHIFT;
L.v=(face->pt[i0].v)<<FSHIFT;
if (dyT!=0)
{
rdyT = FSCALE / dyT;
dxT = (xx[i1]-xx[i0]) * rdyT;
dzT = (zz[i1]-zz[i0]) * rdyT;
duT = (face->pt[i1].u-face->pt[i0].u) * rdyT;
dvT = (face->pt[i1].v-face->pt[i0].v) * rdyT;
R=L;
while (Y < yy[i1])
{
scan(&L,&R,Y);
Y++;
L.x+=dxL;
R.x+=dxT;
L.u+=duL;
L.v+=dvL;
R.u+=duT;
R.v+=dvT;
L.z+=dzL;
R.z+=dzT;
}
}
//bottom
R.z=zz[i1]<<FSHIFT;
R.x=xx[i1]<<FSHIFT;
R.u=face->pt[i1].u<<FSHIFT;
R.v=face->pt[i1].v<<FSHIFT;
dyB = yy[i2]-yy[i1];
if (dyB!=0)
{
rdyB = FSCALE / dyB;
dzB = (zz[i2]-zz[i1]) * rdyB;
dxB = (xx[i2]-xx[i1]) * rdyB;
duB = (face->pt[i2].u-face->pt[i1].u) * rdyB;
dvB = (face->pt[i2].v-face->pt[i1].v) * rdyB;
while (Y < yy[i2])
{
scan(&L,&R,Y);
Y++;
L.x+=dxL;
R.x+=dxB;
L.u+=duL;
L.v+=dvL;
R.u+=duB;
R.v+=dvB;
R.z+=dzB;
L.z+=dzL;
}
}
}
v16 CubeVectors[] = {
floatov16(-0.5), floatov16(-0.5), floatov16(0.5),
floatov16(0.5), floatov16(-0.5), floatov16(0.5),
floatov16(0.5), floatov16(-0.5), floatov16(-0.5),
floatov16(-0.5), floatov16(-0.5), floatov16(-0.5),
floatov16(-0.5), floatov16(0.5), floatov16(0.5),
floatov16(0.5), floatov16(0.5), floatov16(0.5),
floatov16(0.5), floatov16(0.5), floatov16(-0.5),
floatov16(-0.5), floatov16(0.5), floatov16(-0.5)
};
u8 CubeFaces[] = {
3,2,1,0,
0,1,5,4,
1,2,6,5,
2,3,7,6,
3,0,4,7,
5,6,7,4
};
u32 uv[] =
{
TEXTURE_PACK(intot16(128), 0),
TEXTURE_PACK(intot16(128),intot16(128)),
TEXTURE_PACK(0, intot16(128)),
TEXTURE_PACK(0,0)
};
u32 normals[] =
{
NORMAL_PACK(0,intov10(-1),0),
NORMAL_PACK(0,intov10(1),0),
NORMAL_PACK(intov10(1),0,0),
NORMAL_PACK(0,0,intov10(-1)),
NORMAL_PACK(intov10(-1),0,0),
NORMAL_PACK(0,intov10(1),0)
};
void drawQuad(int poly)
{
u32 f1 = CubeFaces[poly * 4] ;
u32 f2 = CubeFaces[poly * 4 + 1] ;
u32 f3 = CubeFaces[poly * 4 + 2] ;
u32 f4 = CubeFaces[poly * 4 + 3] ;
glNormal(normals[poly]);
glTexCoord1i(uv[0]);
glVertex3v16(CubeVectors[f1*3], CubeVectors[f1*3 + 1], CubeVectors[f1*3 + 2] );
glTexCoord1i(uv[1]);
glVertex3v16(CubeVectors[f2*3], CubeVectors[f2*3 + 1], CubeVectors[f2*3 + 2] );
glTexCoord1i(uv[2]);
glVertex3v16(CubeVectors[f3*3], CubeVectors[f3*3 + 1], CubeVectors[f3*3 + 2] );
glTexCoord1i(uv[3]);
glVertex3v16(CubeVectors[f4*3], CubeVectors[f4*3 + 1], CubeVectors[f4*3 + 2] );
}
//---------------------------------------------------------------------------------------