#105133 - Dan Forever - Fri Oct 06, 2006 9:50 am
Does anyone have some source code I could look at or a link to a tutorial explaining how do 3D on both screens of the DS? I know it can be done but my searches aren't having any luck :(
Code: |
// ------ LumiDS --------
// Written by Christopher 'FireSlash' Kadar // <GPL goes here> //Needed for the second screen #define REG_CAPTURE (*(vu32*)0x04000064) // General includes #include <nds.h> // Needed for dual screen 3D void SetRegCapture(bool enable, uint8 srcBlend, uint8 destBlend, uint8 bank, uint8 offset, uint8 size, uint8 source, uint8 srcOffset); bool busy; float xrot; float yrot; float zrot; //a global copy of sprite attribute memory SpriteEntry sprites[128]; //turn off all the sprites void InitSprites() { for(int i = 0; i < 128; i++) { sprites[i].attribute[0] = ATTR0_DISABLED; sprites[i].attribute[1] = 0; sprites[i].attribute[2] = 0; sprites[i].attribute[3] = 0; } } //copy our sprite to object attribute memory void UpdateOAM() { dmaCopy(sprites, OAM_SUB, 128 * sizeof(SpriteEntry)); } int main() { touchPosition touch; // Turn on everything powerON(POWER_ALL); FAT_InitFiles(); // Get our GBAMP/M3/Whatever all warmed up ^^ // Setup the Main screen for 3D videoSetMode(MODE_0_3D); //vramSetBankA(VRAM_A_TEXTURE); videoSetModeSub(MODE_5_2D | DISPLAY_BG2_ACTIVE | DISPLAY_SPR_ACTIVE | DISPLAY_SPR_2D_BMP_256); SUB_BG2_CR = BG_BMP16_256x256; SUB_BG2_XDX = 256; SUB_BG2_XDY = 0; SUB_BG2_YDX = 0; SUB_BG2_YDY = 256; SUB_BG2_CY = 0; SUB_BG2_CX = 0; vramSetMainBanks(VRAM_A_TEXTURE, VRAM_B_TEXTURE, VRAM_C_SUB_BG, VRAM_D_SUB_SPRITE); memset(commandControl, 0, sizeof(CommandControl)); int y = 0; int x = 0; for (y = 0; y < SCREEN_HEIGHT; y++) for (x = 0; x < SCREEN_WIDTH; x++) { BG_GFX_SUB[y * SCREEN_WIDTH + x] = RGB15(31, x % 32, y % 32) | BIT(15); } // IRQ basic setup irqInit(); irqSet(IRQ_VBLANK, 0); //irqEnable(IRQ_VBLANK); glViewPort(0,0,255,191); // Specify the Clear Color and Depth glClearColor(0,0,0); glClearDepth(0x7FFF); InitSprites(); int i = 0; for (y = 0; y < 3; y++) for (x = 0; x < 4; x++) { sprites[i].attribute[0] = ATTR0_BMP | ATTR0_SQUARE | (64 * y); sprites[i].attribute[1] = ATTR1_SIZE_64 | (64 * x); sprites[i].attribute[2] = ATTR2_ALPHA(1) | (8 * 32 * y) | (8 * x); i++; } // framecount won't really work here... needs to be replaced // with a more useful variable for deltas. try IPC->heartbeat. uint32 frameCount = 0; while (1) { glReset(); glOrtho(0,1,0,1,0,12); glColor3f(1,1,1); glLight(0, RGB15(31,31,31) , 0, floattov10(-1.0), 0); glLight(1, RGB15(31,31,31) , 0, 0, floattov10(-1.0)); glLight(2, RGB15(31,31,31) , 0, 0, floattov10(1.0)); glPushMatrix(); glMatrixMode(GL_TEXTURE); glIdentity(); glMatrixMode(GL_MODELVIEW); //need to set up some material properties since DS does not have them set by default glMaterialf(GL_AMBIENT, RGB15(16,16,16)); glMaterialf(GL_DIFFUSE, RGB15(16,16,16)); glMaterialf(GL_SPECULAR, BIT(15) | RGB15(8,8,8)); glMaterialf(GL_EMISSION, RGB15(16,16,16)); //ds uses a table for shinyness..this generates a half-ass one glMaterialShinyness(); glEnable(GL_BLEND); glEnable(GL_ALPHA_TEST); glMatrixMode(GL_MODELVIEW); //Push our original Matrix onto the stack (save state) glPushMatrix(); // This is where the magic happens if (frameCount & 0x1) { vramSetBankC(VRAM_C_SUB_BG); vramSetBankD(VRAM_D_LCD); SetRegCapture(true, 0, 15, 3, 0, 3, 0, 0); scene->draw_bottom(frameCount); } else { vramSetBankC(VRAM_C_LCD); vramSetBankD(VRAM_D_SUB_SPRITE); SetRegCapture(true, 0, 15, 2, 0, 3, 0, 0); scene->draw_top(frameCount); } // Pop our Matrix from the stack (restore state) glPopMatrix(1); frameCount++; // flush to screen glFlush(); lcdSwap(); UpdateOAM(); //swiWaitForVBlank(); } return 0; } // Capture code from ecurtz from gbadev.org forums // Sets the DS to render straight to a VRAM bank instead of to the screen's bank. void SetRegCapture(bool enable, uint8 srcBlend, uint8 destBlend, uint8 bank, uint8 offset, uint8 size, uint8 source, uint8 srcOffset) { uint32 value = 0; if (enable) value |= 1 << 31; // 31 is enable value |= 3 << 29; // 29-30 seems to have something to do with the blending value |= (srcOffset & 0x3) << 26; // capture source offset is 26-27 value |= (source & 0x3) << 24; // capture source is 24-25 value |= (size & 0x3) << 20; // capture data write size is 20-21 value |= (offset & 0x3) << 18; // write offset is 18-19 value |= (bank & 0x3) << 16; // vram bank select is 16-17 value |= (srcBlend & 0xF) << 8; // graphics blend evb is 8..12 value |= (destBlend & 0xF) << 0; // ram blend EVA is bits 0..4 REG_CAPTURE = value; } |
djmcbell wrote: |
By the way, the game is a puzzle game. Top screen is a view you can move, just to rotate around the board, and the bottom is a static view that never moves. |
Quote: |
I know it can be done in 2D but I just want to cheat, save resources and make things look more consistent. |
Code: |
void initVideo3DAll()
{ //set mode 0, enable BG0 and set it to 3D videoSetMode(MODE_0_3D); //this should work the same as the normal gl call glViewPort(0,0,255,191); glClearColor(0,0,0); glClearDepth(0x7FFF); //set sub-screen videoSetModeSub(MODE_5_2D | DISPLAY_BG2_ACTIVE | DISPLAY_SPR_ACTIVE | DISPLAY_SPR_2D_BMP_256); SUB_BG2_CR = BG_BMP16_256x256; SUB_BG2_XDX = 256; SUB_BG2_XDY = 0; SUB_BG2_YDX = 0; SUB_BG2_YDY = 256; SUB_BG2_CY = 0; SUB_BG2_CX = 0; //set out banks vramSetMainBanks(VRAM_A_TEXTURE, VRAM_B_TEXTURE, VRAM_C_SUB_BG, VRAM_D_SUB_SPRITE); } int main() { //turn on to all cores powerON(POWER_ALL); //touch stuff int min_x = 4096 , min_y = 4096, max_x = 0, max_y = 0; int min_px = 4096 , min_py = 4096, max_px = 0 , max_py = 0; touchPosition touch; //set up our video banks initVideo3DAll(); //set up IRQs irqInit(); irqSet(IRQ_VBLANK,0); //set up rotates float rotateX = 45; float rotateY = 225; //load our texture from pcx file int textureID[10]; //ten textures, hopefully sImage pcx; loadPCX((u8*)board1_pcx, &pcx); image8to16(&pcx); glGenTextures(1, &textureID[0]); glBindTexture(0, textureID[0]); glTexImage2D(0, 0, GL_RGB, TEXTURE_SIZE_128, TEXTURE_SIZE_128, 0, TEXGEN_TEXCOORD, pcx.data8); imageDestroy(&pcx); loadPCX((u8*)board2_pcx, &pcx); image8to16(&pcx); glGenTextures(1, &textureID[1]); glBindTexture(0, textureID[1]); glTexImage2D(0, 0, GL_RGB, TEXTURE_SIZE_8, TEXTURE_SIZE_8, 0, TEXGEN_TEXCOORD, pcx.data8); imageDestroy(&pcx); //main stuff uint32 frameCount=0; while(1) { touch=touchReadXY(); //binding our touch coordinates into the screen //iprintf("\x1b[12;12H(%d,%d) ",touch.px,touch.py); - prints coords to the screen if ( touch.x > max_x) max_x = touch.x; if ( touch.y > max_y) max_y = touch.y; if ( touch.px > max_px) max_px = touch.px; if ( touch.py > max_py) max_py = touch.py; if ( touch.x < min_x) min_x = touch.x; if ( touch.y < min_y) min_y = touch.y; if ( touch.px < min_px) min_px = touch.px; if ( touch.py < min_py) min_py = touch.py; //if(touch.px>0){barx=touch.px-16;} //3D stuff glReset(); glOrtho(0,1,0,1,0,12); //any floating point gl call is being converted to fixed prior to being implemented gluPerspective(35, 256.0 / 192.0, 0.1, 40); gluLookAt( 0.0, 0.0, 1.0, //camera possition 0.0, 0.0, 0.0, //look at 0.0, 1.0, 0.0); //up glLight(0, RGB15(31,31,31),0,floattov10(-1.0),0); glLight(1, RGB15(31,0,31),0,floattov10(1) - 1,0); glLight(2, RGB15(0,31,0),floattov10(-1.0),0,0); glLight(3, RGB15(0,0,31),floattov10(1.0) - 1,0,0); glPushMatrix(); //move it away from the camera glTranslate3f32(0, 0, floattof32(-1)); 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)); //ds uses a table for shinyness..this generates a half-ass one glMaterialShinyness(); //not a real gl function and will likely change glPolyFmt(POLY_ALPHA(31) | POLY_CULL_BACK | POLY_FORMAT_LIGHT0 | POLY_FORMAT_LIGHT1 | POLY_FORMAT_LIGHT2 | POLY_FORMAT_LIGHT3 ) ; scanKeys(); u16 keys = keysHeld(); if((keys & KEY_UP)) rotateX += 3; if((keys & KEY_DOWN)) rotateX -= 3; if((keys & KEY_LEFT)) rotateY += 3; if((keys & KEY_RIGHT)) rotateY -= 3; if(rotateX<0)rotateX=0; if(rotateX>90)rotateX=90; glPushMatrix(); // This is where the magic happens if (frameCount & 0x1) { vramSetBankC(VRAM_C_SUB_BG); vramSetBankD(VRAM_D_LCD); SetRegCapture(true, 0, 15, 3, 0, 3, 0, 0); //draw the board base glBindTexture(0, textureID[0]); //change texture glBegin(GL_QUAD); for(int i = 0; i < 6; i++) drawBoardBase(i); glEnd(); //draw the board pieces glBindTexture(0, textureID[1]); //change texture glBegin(GL_QUAD); for(int i = 0; i < 6; i++) drawBoardPieces(i); glEnd(); } else { vramSetBankC(VRAM_C_LCD); vramSetBankD(VRAM_D_SUB_SPRITE); SetRegCapture(true, 0, 15, 2, 0, 3, 0, 0); //draw the board base glBindTexture(0, textureID[0]); //change texture glBegin(GL_QUAD); for(int i = 0; i < 6; i++) drawBoardBase(i); glEnd(); //draw the board pieces glBindTexture(0, textureID[1]); //change texture glBegin(GL_QUAD); for(int i = 0; i < 6; i++) drawBoardPieces(i); glEnd(); } glPopMatrix(1); frameCount++; glFlush(); lcdSwap(); //end 3D stuff //update screens // swiWaitForVBlank(); } //loop back in main proc return 0; } |
Dan Forever wrote: |
Does anyone have some source code I could look at or a link to a tutorial explaining how do 3D on both screens of the DS? I know it can be done but my searches aren't having any luck :( |