May 14, 2024, 07:55:44 AM

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


Cubic environment mapping

Started by Ionic Wind Support Team, July 19, 2006, 07:03:20 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Ionic Wind Support Team

July 19, 2006, 07:03:20 PM Last Edit: July 19, 2006, 07:05:11 PM by Paul Turley
An example of cubic environment mapping that I was working on for the old engine.  Uses the same multitexturing method that the landscape object uses, and a reflective sphere.

The rendering is vsynced to reduce tearing that shows up on certain video cards.  So the max FPS that will show is the same as your monitors refresh rate.




//structure used in our restore callback
struct RestObj
{
C3DMesh *pSphere;
C3DMesh *pRoom;
C3DScreen *pScreen;
}

//Arrow keys to move camera.
//PgUp/PgDn to pan up and down.
//Z and X to rotate on Z axis.

declare import,timeGetTime(),int;

global sub main()
{
C3DScreen s;
C3DCamera c;
C3DMesh *room;
C3DMesh sphere;
C3DObject scene;
CDirectInput di;
float fadjust,fTarget;
//target 60FPS for camera movement
fTarget = 1.0f / /*FPS*/60.0f * 1000.0f;
fAdjust = 1.0f;

//s.CreateFullScreen(800,600,32,true);
s.CreateWindowed(0,0,800,600,AWS_CAPTION|AWS_VISIBLE|AWS_SIZE|AWS_CENTERED,0,"3D Test - ESC exits",NULL,true);

di.Init(s);
c.Create(s);
c.Position(0,0,-8);
c.Orient(0,0,1,0,1,0);
c.SetBackPlane(500);

s.Clear(RGBA(0,0,0,255));
s.BeginScene(c);
s.RenderText(0,10,"Loading objects...",RGBA(255,255,0,255));
s.RenderScene();

room = CreateRoom(s,20,20,50,null);

sphere.CreateSphere(s,30f,2f,false);
sphere.EnableLighting(false);
sphere.CreateCubeTexture(0,256,"cubemap");
//render a static cubemap
for( x = 0; x < 6; x++)
{
sphere.BeginRenderCubeTexture(0,x,0,0,0);
s.Clear(RGBA(0,0,255,255));
room->Draw();
sphere.EndRenderCubeTexture();
}

//setup the restore callback
RestObj res;
res.pScreen = s;
res.pRoom = room;
res.pSphere = sphere;
s.SetRestoreCallback(&rebuild_room,res);

scene.CreateScene(s);
scene.AddChild(room);
scene.AddChild(sphere);

int fps = 0;
int startTime;
do
{
startTime = timeGetTime();
//check for keys and move camera accordingly
IF di.KeyDown(DIK_UP)
c.Move(0.0f,.25f * fAdjust);
IF di.KeyDown(DIK_DOWN)
c.Move(0.0f,-.25f * fAdjust);
IF di.KeyDown(DIK_RIGHT)
c.Rotate(1*.01745 * fAdjust,0,0);
IF di.KeyDown(DIK_LEFT)
c.Rotate(-1*.01745 * fAdjust,0,0);
IF di.KeyDown(DIK_Z)
c.Rotate(0,0,-1 *.01745 * fAdjust);
IF di.KeyDown(DIK_X)
c.Rotate(0,0,1 *.01745 * fAdjust);
IF di.KeyDown(DIK_PRIOR)
c.Rotate(0,-1 *.01745 * fAdjust,0);
IF di.KeyDown(DIK_NEXT)
c.Rotate(0,1 *.01745 * fAdjust,0);
IF di.KeyDown(DIK_R)
c.LookAt(0,0,0);

s.Clear(RGBA(0,0,0,255));
s.BeginScene(c);
scene.Draw();
s.RenderText(0,10,"FPS:"+NumToStr(fps),RGBA(255,255,0,255));
s.RenderText(0,30,"Use arrow keys to move around",RGBA(255,255,0,255));
fps = s.RenderScene();
fAdjust = (timeGetTime() - startTime) / fTarget;
}until di.KeyDown(DIK_ESCAPE);
Scene.Free();
}

sub CreateRoom(C3DScreen *pScreen,float width, float height,float depth,C3DMesh *restore = NULL),C3DMesh *
{
C3DMesh *pRet,*pass2;
if(!restore)
pRet = new(C3DMesh,1)
else
pRet = restore;
pass2 = new(C3DMesh,1);
int i,j,k,index;
//create a box to copy.  Make it an 'inside' cube
C3DMesh temp;
temp.CreateBox(pScreen,width,height,depth,true);
numVertices = temp.GetVertexCount();
numIndices = temp.GetIndexCount();
if(restore)
pRet->Free();
//create the mesh with a vertex format that allows position, a diffuse color and a normal vector + two textures.
pRet->CreateMesh(pScreen,numVertices,numIndices,D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX2 );
//create the pass2 mesh. It only needs one texture and will be temporary
pass2->CreateMesh(pScreen,numVertices,numIndices,D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1 );
pRet->AddChild(pass2);
//lock the buffers and copy the data
VERTEX2TEXTURE *pVB;
VERTEX1TEXTURE *pVBPass2,*pVBOld;
word *pIB,*pIBOld,*pIBPass2;
pVB = pRet->LockVertexBuffer();
pVBOld = temp.LockVertexBuffer();
pVBPass2 = pass2->LockVertexBuffer();
pIB = pRet->LockIndexBuffer();
pIBOld = temp.LockIndexBuffer();
pIBPass2 = pass2->LockIndexBuffer();

//copy the vertices and 1st texture coordinates.  Duplicate the 2nd
for( j=0; j < numVertices; j++)
{
*pVB[j].position = *pVBOld[j].position;
*pVB[j].normal = *pVBOld[j].normal;
*pVB[j].diffuseColor = *pVBOld[j].diffuseColor;
*pVB[j].texCoords[0] = *pVBOld[j].texCoords[0];
*pVB[j].texCoords[1] = *pVBOld[j].texCoords[0];

*pVBPass2[j].position = *pVBOld[j].position;
*pVBPass2[j].normal = *pVBOld[j].normal;
*pVBPass2[j].diffuseColor = *pVBOld[j].diffuseColor;
*pVBPass2[j].texCoords[0] = *pVBOld[j].texCoords[0];
}

//copy the indices
FOR( k=0; k < numIndices; k++)
{
*pIB[k] = *pIBOld[k];
*pIBPass2[k] = *pIBOld[k];
}

//now rewrite the diffuse colors based on the side
for( i=0; i < 6; i++)//the sides
{
for( j = 0; j < 3; j++)//num of triangles per row
{
for( k =0; k < 3;k++)// num of triangles per column
{
index = i * 3 * 3 + j * 3 + k;
SELECT i
{
CASE 0:
//ceiling
*pVB[index].diffuseColor = RGBA(255,255,255,0);
*pVBPass2[index].diffuseColor = RGBA(0,0,0,255);
CASE 1:
//floor using pass2
*pVBPass2[index].diffuseColor = RGBA(255,255,255,255);
*pVB[index].diffuseColor = 0;
default:
//walls
*pVB[index].diffuseColor = RGBA(0,0,0,255);
*pVBPass2[index].diffuseColor = RGBA(0,0,0,255);
}
}
}
}

//unlock the buffers
pRet->UnlockIndexBuffer();
pRet->UnlockVertexBuffer();
temp.UnlockIndexBuffer();
temp.UnlockVertexBuffer();
pass2->UnlockIndexBuffer();
pass2->UnlockVertexBuffer();

temp.Free();

pRet->SetCulling(CULL_NONE);
pass2->SetCulling(CULL_NONE);

pRet->LoadTexture(0,GetStartPath() + "media\\tile3.tga",0);
pRet->LoadTexture(1,GetStartPath() + "media\\wall11.jpg",0);
pass2->LoadTexture(0,GetStartPath() + "media\\floor11.jpg",0);
//make it visible
pRet->SetVisible(TRUE);
pass2->SetVisible(TRUE);
pRet->RecalcBoundingBox();
pass2->RecalcBoundingBox();

//since we are using diffuse and alpha for texture blending turn of lighting for the objects
pRet->EnableLighting(FALSE);
pass2->EnableLighting(FALSE);

//setup the pipeline
//PASS 1
//Stage 0 - Color - Modulate the texture with diffuse
//This results in : stage0_color_result = rgb(diffuse)*t1
pRet->SetColorArg1(0,D3DTA_DIFFUSE);
pRet->SetColorArg2(0,D3DTA_TEXTURE);
pRet->SetColorOperation(0,D3DTOP_MODULATE);
//Stage 0 - Alpha - Use diffuse alpha
//This results in : stage0_alpha_result = a
pRet->SetAlphaArg1(0, D3DTA_DIFFUSE);
pRet->SetAlphaOperation(0, D3DTOP_SELECTARG1);
//Stage 1- Color - Modulate alpha add color
//This results in : pass1_color_result = stage0_color_result + stage0_alpha_result*t2
//which is : pass1_color_result = rgb(diffuse)*t1 + a(diffuse)*t2
pRet->SetColorArg1(1,D3DTA_CURRENT);
pRet->SetColorArg2(1,D3DTA_TEXTURE);
pRet->SetColorOperation(1,D3DTOP_MODULATEALPHA_ADDCOLOR);
//This results in : pass1_alpha_result = tile2_alpha
pRet->SetAlphaArg1(1, D3DTA_TEXTURE);
pRet->SetAlphaOperation(1, D3DTOP_SELECTARG1);

//PASS 2
pass2->SetColorArg1(0,D3DTA_DIFFUSE);
pass2->SetColorArg2(0,D3DTA_TEXTURE);
pass2->SetColorOperation(0,D3DTOP_MODULATE);

pass2->SetAlphaArg1(0, D3DTA_DIFFUSE);
pass2->SetAlphaOperation(0, D3DTOP_SELECTARG1);

pass2->EnableAlpha(TRUE);
pass2->SetAlphaOp(D3DBLENDOP_MAX);
pass2->SetAlphaSource(D3DBLEND_SRCALPHA);
pass2->SetAlphaDest(D3DBLEND_SRCALPHA);

//delete our local pass2 object.  The internal mesh used by the engine will
//still be there as a child of our room mesh. It will be freed when the parent mesh is freed.
delete pass2;
return pRet;
}

/*
this function is called by the engine when the d3d device has been reset and restored
Usually during an ALT_TAB switch from fullscreen to the desktop. At this point our vertex
and index buffer were released and need to be recreated.

*/
sub rebuild_room(void *pParam)
{
IF pParam
{
CreateRoom(*(RestObj)pParam.pScreen,20,20,50,*(RestObj)pParam.pRoom);
//cubemaps are not automatically restored like normal textures.  So we need to recreate it also.
*(RestObj)pParam.pSphere->CreateCubeTexture(0,256,"cubemap");
for( x = 0;x <6;x++)
{
*(RestObj)pParam.pSphere->BeginRenderCubeTexture(0,x,0,0,0);
*(RestObj)pParam.pScreen->Clear(RGBA(0,0,255,255));
*(RestObj)pParam.pRoom->Draw();
*(RestObj)pParam.pSphere->EndRenderCubeTexture();
}
}
return;
}
Ionic Wind Support Team

Zen

Paul, this runs verry slow on my system, when moving around in the environment its verry stuttery. I am running and AMD X2 3800 with 1GB RAM and a Radeon X800 XT graphics card (256bm) with the latest drivers.

Lewis

Protected

Nice example, works nicely here. I'm not having any problems with my geforce fx 5200 with or without vsync.

I didn't have time to look into it well yet (and sorry about the apparently unrelated question), but can you attach a camera to an object via the engine or do you have to do it manually (by keeping the locations synchronized)?

Zen

Ok, i just noticed you updated the code, re-compiled and all is working fine ;)

Lewis

kryton9

Thanks enjoyed it very much. On my cheapo video card I Can go to 1024x768 pretty well in a window. At lesser resolutions it is running nicely. Anything above 1024x768 windowed or full screen I do see some stepping rotating around, but that must be from the video card as the frame rate drops below 60fps.

THanks for all the new examples lots to look at and play with.

I was wondering in Darkbasic Pro, I would break up my models into parts and bring them in as limbs, I guess the equivalent of a child in aurora. So let's say i had a rocket, I would have the body, a canopy and a flame. I could control the opacity and effects and animations separately for each object, but move all three objects by moving the parent object. So would I bring in another x file and then once loaded use the child method for 3d objects?

Once I get all that figured out in a couple of weeks once I learn more of aurora I will write a nice object viewer using aurora with lots of controls.

Barney

Actually it works better than in the old engine. Remember the texture tearing on the floor? Not a trace of it now. I get 1231 FPS windowed and 1345 full screen. Everything is working perfectly and code is very easy to understand and follow.

I am already playing with the HUD creation... :)

Barney

Protected

Holy crap, that's a lot of frames :-S I need a new gfx card....

Zen

Barney, what are your computers specs? I can only get upto 172 with my machine, thats a prety awesome FPS you have.

Let us know when you have the HUD stuff examples to show us, thats something i am interested in too.

Lewis

Barney

Gentlemen, your wishes are my commands  ;)

My computer specs: AMD X2 4400+, 2GB RAM, ATI X1900XL graphics card

Latest ATI Catalyst drivers (v6.6)

Hopefully, I'll have some HUD stuff next week. I'm on holidays so I'm taking things easy at the moment...  ;D

Barney

Zen

Well i guess you deserve everyone of those FPS with a system like that. I just got my X2 3800+ about a month ago but the rest i have had for 2 years almost now. I paid ÂÃ,£300 for my graphics card when it came out.

Lewis

Ionic Wind Support Team

My AMD 800 only gets 130 FPS  ;D

Ionic Wind Support Team

kryton9

Ok, I am perplexed. I have an x2 4600 with 2 gigs ram, an asus motherboard and it came with the weak link nvidia 7300le card with 256mb. It does support all the directx9 stuff and all my games as long as I run them at either 640x480 or 800x600 I am fine with the highest settings so far.

But on this cube map, I only get 60fps at best. But could that be because I am on a LCD monitor that runs at a 60 Hertz refresh rate?

Barney

In order to get higher frame rates one needs to change the last parameter in the function that creates the 3D screen. Just change it from true to false and the FPS rate will literary take off... :)

Here are the four possible ways one can setup the open 3D screen code:

s.CreateFullScreen(800,600,32,true); // Full screen - Desktop FPS rate

s.CreateFullScreen(800,600,32,false); // Full screen - Maximal FPS rate

s.CreateWindowed(0,0,800,600,AWS_CAPTION|AWS_VISIBLE|AWS_SIZE|AWS_CENTERED,0,"3D Test - ESC exits",NULL,true); // Window - Desktop rate

s.CreateWindowed(0,0,800,600,AWS_CAPTION|AWS_VISIBLE|AWS_SIZE|AWS_CENTERED,0,"3D Test - ESC exits",NULL,false); // Window - Maximal rate

Barney

kryton9

THanks Barney, Using the windowed 800x600 as it was posted but changing the true to false I went from 60 to about an average of 125. No where near your mega fps though :)

I am looking to buy a nvidia  7900gt with 512mb but since the 7300le card is serving me right now, waiting for the prices to drop another $100 as they just sort of recently came out.
Will be a lot of bang for the buck when the prices drop in the $200's.

John S

I got an exception error when the example ran after it compiled:

Unhandled exception in 3d_cubic.exe (DX3D9R.DLL): 0xC0000005: Access Violation.
John Siino, Advanced Engineering Services and Software

Ionic Wind Support Team

John,
The example doesn't check to make sure the screen was created.  Perhaps you need a DX update.
Ionic Wind Support Team

Zen

Well well, Take off i guess was a bit of an understatement lol...

Barney

July 20, 2006, 05:15:58 PM #17 Last Edit: July 20, 2006, 07:33:28 PM by Barney
Hmm... blast off comes to mind...  ;D

Now move your camera all the way through the object until the screen is full black. Note the FPS rate then... Ballistic, perhaps? ;)

Barney

John S

yeah! got it to work.  Fantastic work Paul!
John Siino, Advanced Engineering Services and Software

Zen

Yeah once i went through the wall my FPS was over 2500 lol

Lewis

Steven Picard

Paul, the 3D is great and it runs faster and smoother than IBPro's version!  Great work!   ;D

Ionic Wind Support Team

Thanks.  I've learned a lot since then ;)
Ionic Wind Support Team

kryton9

July 20, 2006, 10:30:51 PM #22 Last Edit: July 20, 2006, 10:58:12 PM by Paul Turley
I am posting this reluctantly not to cause any trouble but to make sure Aurora becomes as great as we know it will be. I know we are in early alpha versions and we just got 3d. But we should test it and make it be better than stuff out there and so I decided to post this here.

I wrote the same program as best as I could to match what Paul wrote and I am getting better performance and smoother movement when rotating around with the version I wrote in DarkBasicPro. This is not using their SDK version for C++. but the main BASIC version they have. Not to mention how much easier it was to code in DarkBasicPro. Now DBP is not an all purpose language so maybe this isn't a fair comparison and of course development in both languages is not a fair comparison at the moment either, like I said, I am only writing this to help better future development of Aurora.

I will attach the exectueable and source files and a screenshot in a zip file. Just put the exectueable in the same folder as the d3d source file that Paul wrote. MY program uses the same textures as Paul's from the media folder.  In both versions I do not see tearing as I did in the other demos, but in the Aurora version there is still this slight step in rotating even with fps over 100. Ok for now I can't attach the zip file as it is a little too big. When I get my WebSite up I will host it there. I will see about inserting the screenshot.

Maybe Paul and other developers can figure out where the hiccups are down the road and that is why I am posting this.


Ionic Wind Support Team

July 20, 2006, 10:57:41 PM #23 Last Edit: July 20, 2006, 11:03:12 PM by Paul Turley
Numebr one it's an alpha.

Number two the programs are not identical.  Aurora's version shows usage of the fixed function pipline using a single cube object to do multi-texturing by controlling the texturing stage with the diffuse color.

You've created six objects and placed a simple texture on each, which is faster for rendering.  You could also do the same in Aurora if you wanted.

So your not comparing identical methods here.  I don't know anything about DB and if it can directly control the textureing stage, but it is an advanced usage.  The only thing I know about DB is what users have posted on other forums, and those posts were not very positive.

I've edited your post since we don't want to confuse new users with foreign code.  Also this isn't a BASIC language ;)

Ionic Wind Support Team

Ionic Wind Support Team

As for steps in rotating that is due to how I calculate the throttled FPS for the camera.  Which is just a simple division and multiply to adjust how far the camera is moved.  Targeted at 60 FPS but it will hiccup once in a while due to rounding errors since timeGetTime returns an integer millesecond value, and it's not very accurate as it is based on how much the last frame took to render, so the adjustment value can be off if the next frame renders slower or faster by a large difference.

Run it in full screen and you'll see that the steps in rotation are slightly better due to the screen being exclusive. 

I'll show a better method using multimedia timers in a future example.
Ionic Wind Support Team