Sign in to follow this  

Directx 9 Hardware Instancing

This topic is 2538 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have searched the internet and looked at the sample with the SDK on instancing. I have a very good idea of what I need to do. I understand how it works. I need shader model 3.0. I know you have to set the vertex declaration for both the original mesh and the postion data in the second declaration. Then in the HLSL shader you reconstruct this from the IN data something like this: float4x4 instanceMatrix = float4x4(mx, my, mz, mw);

However I am having a hard time just getting it to work.

Right now I can render say 100 meshes and display them easily enough. But that is not really what I need to do. I need the benefit of instancing. I want to make a forest and I can't really use the traditional load/position/dispaly method. I start to max out very fast, leaving no other time for processing anything else besides trees.

What I really need is just a bare bones example in C++ that shows how to send a single mesh and the position data/matrix for say 100 copies to a very simple HLSL shader. If anyone can help me with this I would really appreciate it.

I really need to learn this and the directx SDK sample is too complicated for me to follow.

Thanks.

Share this post


Link to post
Share on other sites
Here is mine (used for grass rendering but u cant use it for anything else),
i've putted vertex elements in single declaration, you can easely modified it to be in two if you like that way:

// in some init function
...
DWORD numTrees = 300;
...
D3DVERTEXELEMENT9 VertexElementsGeom[] =
{
{0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
{0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
{0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
{1, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
{1, 16, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2},
{1, 32, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3},
{1, 48, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4},
D3DDECL_END()
};
gvSizegeom = D3DXGetDeclVertexSize(VertexElementsGeom, 0);
gvSizeInst = D3DXGetDeclVertexSize(VertexElementsGeom, 1);
dev->CreateVertexDeclaration(VertexElementsGeom, &gVDeclaration);
//meshx is your tree model (make sure it contains only position, normal & texcoord
meshx->GetVertexBuffer(&gVBufferGeom);
meshx->GetIndexBuffer(&gIBuffer);
dev->CreateVertexBuffer(gvSizeInst * numTrees, D3DUSAGE_WRITEONLY, NULL, D3DPOOL_MANAGED, &gVBufferInst, NULL);
Vector3 ppos, prot;
for(int k = 0; k < numTrees; k++)
{
//put at some random position & rotation
ppos = Vector3(Math::Random(1000.0f) - 1000.0f, -90.0f, Math::Random(1000.0f) - 1000.0f);
prot = Vector3(0.0f, Math::Random(PI * 2.0f), 0.0f);
wrld[k].Identity();
wrld[k].SetRotation(prot);
wrld[k].SetTranslation(ppos);
}
Matrix4* pData = 0;
gVBufferInst->Lock(0, 0, (LPVOID*)&pData, 0);
memcpy(pData, wrld, gvSizeInst * numTrees);
gVBufferInst->Unlock();

numVert = meshx->GetMesh()->GetNumVertices();
numInd = meshx->GetMesh()->GetNumFaces();

...
//in some render function

dev->SetVertexDeclaration(gVDeclaration);
dev->SetIndices(gIBuffer);
dev->SetStreamSourceFreq(0, (D3DSTREAMSOURCE_INDEXEDDATA | numTrees));
dev->SetStreamSource(0, gVBufferGeom, 0, gvSizegeom);
dev->SetStreamSourceFreq(1, (D3DSTREAMSOURCE_INSTANCEDATA | 1));
dev->SetStreamSource(1, gVBufferInst, 0, gvSizeInst);
...
gEffect->SetTechnique(...);
gEffect->SetMatrix(...);
...//and so on
gEffect->Begin(0, 0);
gEffect->BeginPass(0);
dev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, numVert, 0, numInd);
gEffect->EndPass();
gEffect->End();


shader

float4x4 world;
float4x4 view;
float4x4 proj;
...//and other
struct A2V
{
float3 Position : POSITION;
float3 Normal : NORMAL;
float2 TexCoord0 : TEXCOORD0;
float4 W0 : TEXCOORD1;
float4 W1 : TEXCOORD2;
float4 W2 : TEXCOORD3;
float4 W3 : TEXCOORD4;
};

struct V2P
{
float4 Position : POSITION;
float2 TexCoord0 : TEXCOORD0;
...//and other attributes u need
};

void VS(in A2V IN, out V2P OUT)
{
float4x4 object = float4x4(IN.W0, IN.W1, IN.W2, float4(IN.W3.xyz, 1.0f));
float4x4 objectworld = mul(object, world);
float4x4 WVP = mul(objectworld, mul(view, proj));
OUT.Position = mul(float4(IN.Position, 1.0f), WVP);
OUT.TexCoord0 = IN.TexCoord0;
}


I have chopped this from 2 different projects of mine so it might contain some mistakes but you should be able to set it correctly for your needs.

Share this post


Link to post
Share on other sites
Thank you, I think I can get it working. I'm going to make a new very basic simple project, and try to get it working. I'll post back with success and the project so anyone else who has this issue can look at a very basic sample. Sometimes it seems like the samples are written and they are overly complex or confusing. But then again, it could just be me. lol.

Yes I did look at that page and I seen the code (thanks for the link though), however it is not a complete sample (however it does explain what needs to be done) and lacks many details on the actual implementation. There are many different partial examples like that out there and some disscussions on various forums, and most are lacking in the implemention details, or are in C# XNA/managed style.

Share this post


Link to post
Share on other sites
Here, I'll give you a brief overview with no code so you can make sure you're on the right path:

1. Load any mesh the way you normally would, into a vertex + index buffer. Geometry has to be indexed to work with instancing

2. Create a vertex buffer for your instance data. Usually you just have some max instances you support, and you make the buffer that big. Make sure it's created in D3DPOOL_DEFAULT, with D3DUSAGE_DYNAMIC and D3DUSAGE_WRITEONLY. This will make it a dynamic vertex buffer optimized for being overwritten every frame.

3. Create a vertex declaration that's the combination of both your mesh vertex data, and your instance data. So if your instance data is just a 4x4 world matrix, you'll need 4 additional elements in the vertex declaration. Usually you use an uncommon semantic + semantic index, such as POSITION1 - POSITION4. Make sure your instance elements are in stream 1, and not stream 0.

4. When you're ready to render a bunch of instances, fill your second vertex buffer with instance data. A common way to handle this is to have a std::vector or an array that you add instance data to as you traverse your scene graph and perform culling, so that afterwards you have an array full of only the instances you need to draw. Then you can just lock the vertex buffer, memcpy the instances, and unlock it.

5. Set the mesh vertex buffer and index buffer, and then set the instance data vertex buffer to stream 1. Then you need to call SetStreamSourceFreq to indicate the number of instances you need to draw. It looks something like this:

device->SetStreamSourceFreq(0, (D3DSTREAMSOURCE_INDEXEDDATA | numInstances));
device->SetStreamSourceFreq(1, (D3DSTREAMSOURCE_INSTANCEDATA | 1));


6. Draw your mesh

7. Set the stream source freq back to 1 for each stream

device->SetStreamSourceFreq(0, 1);
device->SetStreamSourceFreq(1, 1);


Then in your vertex shader, you just need to take the instance data as an input using the semantics you used in your vertex declaration. Be careful though with matrices...by default the HLSL compiler will expect column-major matrices, and D3DXMATRIX is row-major. So if you just copy matrices into your instance data vertex buffer, you'll need to call transpose in your vertex shader or use the "row_major" modifier when declaring the float4x4 variable. Or of course you can just transpose the matrix before copying it into the vertex buffer.

Share this post


Link to post
Share on other sites
OK, I've been working on this for awhile now and this is what I have come up with. It was compiling and displaying before I tried to instance with the shader. Now it won't compile, and I wonder how close I am. I just modified and example that I had laying around that creates a simple camera to move with.

here is the cpp code


/************************************************************
* APRON TUTORIALS PRESENTED BY MORROWLAND *
*************************************************************
* Project Name : Camera2 *
* Project Description : Move and Rotate Camera *
* Project Type : DirectX 3D *
* Author : Ronny André Reierstad *
* Web Page : www.morrowland.com *
* E-Mail : apron@morrowland.com *
* Version : English (UK) *
* Date : 18.12.2003 *
************************************************************/



#include "main.h"


HDC hDC = NULL; // Private GDI Device Context
HWND hWnd = NULL; // Holds Our Window Handle
HINSTANCE hInstance; // Holds The Instance Of The Application
LPDIRECT3D9 pD3D = NULL; // DirectX 3D Version 9
LPDIRECT3DDEVICE9 pD3DDevice = NULL; // DirectX 3D Rendering Device

bool keys[256]; // Array Used For The Keyboard Routine
bool active=TRUE; // Window Active Flag Set To TRUE By Default
bool fullscreen=TRUE; // Fullscreen Flag Set To Fullscreen Mode By Default


ID3DXEffect* effectShader = NULL;

ID3DXMesh* CubeMesh;

IDirect3DIndexBuffer9 *IB = NULL;
IDirect3DVertexBuffer9 *VB = NULL;
IDirect3DVertexBuffer9 * gVBufferInst;

DWORD gvSizegeom = NULL;
DWORD gvSizeInst = NULL;

D3DXMATRIX wrld[300];


// Textures.
LPDIRECT3DTEXTURE9 Texture = NULL;


UINT uPasses; //used for render passes

D3DXMATRIX matTrans;
D3DXMATRIX matView;
D3DXMATRIX worldViewProjection;
D3DXMATRIX projection_matrix;
D3DXMATRIX IdentityMatrix;
D3DXMATRIX translation_matrix;
D3DXMATRIX rotation_matrix;
D3DXMATRIX modelViewProj;


//control the rotation of the cube
float g_fSpinX;
float g_fSpinY;
float g_fSpinZ;
float b;



int f2 = sizeof(FLOAT)*2;
int f3 = sizeof(FLOAT)*3;
int f4 = sizeof(FLOAT)*4;


D3DVERTEXELEMENT9 SDec[] =
{
{ 0, 0 ,D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, // pos
{ 1, f4 ,D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, // tex0
{ 2, f4 + f2 ,D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 }, // normal
{ 3, f4 + f2 + f3 ,D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0 }, // tangent
{ 4, f4 + f2 + f3 +f3 ,D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL, 0 }, // binormal

D3DDECL_END()
};



IDirect3DVertexDeclaration9* ShaderDeclaration;




//NEW//////////////////NEW//////////////////NEW//////////////////NEW////////////////

CCamera objCamera;



LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration For WndProc




///////////////////////////////////////////////////////
// Load a .X file
///////////////////////////////////////////////////////
void LoadXFile_NoTexture( char* MeshFilename, ID3DXMesh* &Mesh)
{
//Zero Mesh and create buffer
Mesh = 0;
ID3DXBuffer* MeshBuffer = 0;

//Load and optimize the mesh
D3DXLoadMeshFromX( MeshFilename, D3DXMESH_MANAGED, pD3DDevice, &MeshBuffer, 0, 0, 0, &Mesh);


Mesh->OptimizeInplace(D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_COMPACT | D3DXMESHOPT_VERTEXCACHE, (DWORD*)MeshBuffer->GetBufferPointer(), 0, 0, 0);
Mesh->CloneMesh(D3DXMESH_MANAGED, SDec, pD3DDevice, &Mesh);

//compute tangets and binormals
D3DXComputeTangentFrame( Mesh, NULL );
D3DXComputeNormals(Mesh, NULL);

//Release and zero the buffer
MeshBuffer->Release();

//end of Function
}


// create effect from specified file and output errors if any
void LoadEffect(char* EffectFilename, ID3DXEffect* &d3dEffect)
{
ID3DXBuffer* d3dErrors = NULL;

D3DXCreateEffectFromFile(pD3DDevice, EffectFilename,NULL, NULL,
D3DXSHADER_OPTIMIZATION_LEVEL3 ,
NULL, &d3dEffect, &d3dErrors);

if(d3dErrors)
{
MessageBox(NULL, "Failed to load FX File", "CRITICAL ERROR!", MB_OK|MB_ICONEXCLAMATION);
d3dErrors->Release();
exit(-1);
}


HRESULT hr = d3dEffect->ValidateTechnique(d3dEffect->GetTechnique(0));

//End of Function
}



/////////////////////////////////////////////////////////////////////////////////////////////////
// THE RESIZE D3D SCENE
/////////////////////////////////////////////////////////////////////////////////////////////////
void ReSizeD3DScene(int width, int height) // Resize And Initialize The DX Window
{
if (height==0) // Prevent A Divide By Zero By
{
height=1; // Making Height Equal One
}


D3DXMatrixPerspectiveFovLH(&projection_matrix, 45.0f, (float)640/(float)480, 1.0f, 1000.0f );

pD3DDevice->SetTransform( D3DTS_PROJECTION, &(D3DMATRIX)projection_matrix );

}


/////////////////////////////////////////////////////////////////////////////////////////////////
// THE DIRECT3D INIT
/////////////////////////////////////////////////////////////////////////////////////////////////
int InitD3D()
{

D3DXMatrixIdentity( &projection_matrix );
D3DXMatrixPerspectiveFovLH(&projection_matrix, 45.0f, (float)640/(float)480, 0.1f, 1000.0f );

pD3DDevice->SetTransform( D3DTS_PROJECTION, &(D3DMATRIX)projection_matrix );


pD3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE ); // Z-Buffer (Depth Buffer)
pD3DDevice->SetRenderState(D3DRS_CULLMODE, TRUE); // Disable Backface Culling
pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE); // Disable Light



//NEW//////////////////NEW//////////////////NEW//////////////////NEW////////////////
// Position View Up(vector)
objCamera.Position_Camera(-15, 0.5f, -15, 0, 0.5f, 0, 0, 1, 0);

//NEW//////////////////NEW//////////////////NEW//////////////////NEW////////////////

LoadEffect("Instance.fx", effectShader);

LoadXFile_NoTexture("Sphere.x",CubeMesh);




DWORD numTrees = 300;

D3DVERTEXELEMENT9 VertexElementsGeom[] =
{
{0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
{0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
{0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
{1, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
{1, 16, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2},
{1, 32, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3},
{1, 48, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4},
D3DDECL_END()
};
gvSizegeom = D3DXGetDeclVertexSize(VertexElementsGeom, 0);
gvSizeInst = D3DXGetDeclVertexSize(VertexElementsGeom, 1);
pD3DDevice->CreateVertexDeclaration(VertexElementsGeom, &ShaderDeclaration);
//meshx is your tree model (make sure it contains only position, normal & texcoord

CubeMesh->GetVertexBuffer( &VB );
CubeMesh->GetIndexBuffer( &IB );


pD3DDevice->CreateVertexBuffer(gvSizeInst * numTrees, D3DUSAGE_WRITEONLY, NULL, D3DPOOL_MANAGED, &gVBufferInst, NULL);

D3DXVECTOR3 ppos, prot;

for(int k = 0; k < numTrees; k++)
{
//put at some random position & rotation
ppos.x = rand() % 1000;
ppos.y = 0;
ppos.z = rand() % 1000;

D3DXMatrixIdentity( &wrld[k] );
D3DXMatrixTranslation( &translation_matrix, ppos.x, ppos.y,ppos.z );


}

D3DXMATRIX* pData = 0;
gVBufferInst->Lock(0, 0, (LPVOID*)&pData, 0);
memcpy(pData, wrld, gvSizeInst * numTrees);
gVBufferInst->Unlock();

DWORD numVert = CubeMesh->GetNumVertices();
DWORD numInd = CubeMesh->GetNumFaces();
















// Load the decal image.
if(D3DXCreateTextureFromFile(pD3DDevice, "gothic.png", &Texture) != D3D_OK)
return false;


// Create the vertex declaration.
//if(pD3DDevice->CreateVertexDeclaration(SDec, &ShaderDeclaration) != D3D_OK)
// return false;

//CubeMesh->CloneMesh(D3DXMESH_MANAGED, SDec, pD3DDevice, &CubeMesh);



//image stage 1
pD3DDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
pD3DDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
pD3DDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
pD3DDevice->SetSamplerState(0, D3DSAMP_MAXANISOTROPY, 16);
// Specify that the texture tiles.
pD3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
pD3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);


return TRUE;
}



/////////////////////////////////////////////////////////////////////////////////////////////////
// THE DIRECT3D RENDER
/////////////////////////////////////////////////////////////////////////////////////////////////
int DrawD3DScene()
{


//NEW//////////////////NEW//////////////////NEW//////////////////NEW////////////////

// use this function for direct3d target camera
// View Matrix
D3DXMatrixLookAtLH(&matView, // Update View Matrix
&D3DXVECTOR3(objCamera.mPos.x, objCamera.mPos.y, objCamera.mPos.z),
&D3DXVECTOR3(objCamera.mView.x, objCamera.mView.y, objCamera.mView.z),
&D3DXVECTOR3(objCamera.mUp.x, objCamera.mUp.y, objCamera.mUp.z) );
pD3DDevice->SetTransform(D3DTS_VIEW,&matView);// Apply Changes To The View



pD3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
D3DCOLOR_COLORVALUE(0.0f,0.0f,0.0f,0.0f), 1.0f, 0 );

pD3DDevice->BeginScene(); // Begin Scene



D3DXMATRIX matWorld;
D3DXMatrixIdentity(&matWorld);


//control the rotation of the cube
g_fSpinX = g_fSpinX + 0.5;
g_fSpinY = g_fSpinY + 0.5;
g_fSpinZ = g_fSpinZ + 0.5;

D3DXMatrixTranslation( &translation_matrix, 0, 0.0f,0 );
//set as x,y,z rotation
D3DXMatrixRotationYawPitchRoll( &rotation_matrix,
D3DXToRadian(g_fSpinX),
D3DXToRadian(g_fSpinY),
D3DXToRadian(g_fSpinZ));

D3DXMatrixMultiply(&matWorld,&rotation_matrix,&translation_matrix);


// Apply the textures.
effectShader->SetTechnique("Draw");



// Set the vertex shader variables.

// Set the model view projection matrix.
D3DXMATRIX WVP = matWorld * matView * projection_matrix;


// Set the shader parameters.


//effectShader->SetMatrix("world", &matWorld);
//effectShader->SetMatrix("view", &matView);
// effectShader->SetMatrix("proj", &projection_matrix);

//wrld
pD3DDevice->SetVertexDeclaration(ShaderDeclaration);





LPDIRECT3DVERTEXBUFFER9 VBBuffer;
CubeMesh->GetVertexBuffer(&VBBuffer);

unsigned int uiVertices = CubeMesh->GetNumVertices();
unsigned int uiFaces = CubeMesh->GetNumFaces();

unsigned int uiSizeofFVF = D3DXGetFVFVertexSize(CubeMesh->GetFVF());




pD3DDevice->SetFVF(CubeMesh->GetFVF());

LPDIRECT3DINDEXBUFFER9 IBBuffer;
CubeMesh->GetIndexBuffer(&IBBuffer);
pD3DDevice->SetIndices( IBBuffer);


pD3DDevice->SetVertexDeclaration(ShaderDeclaration);
pD3DDevice->SetIndices(IB);
pD3DDevice->SetStreamSourceFreq(0, (D3DSTREAMSOURCE_INDEXEDDATA | 300));
pD3DDevice->SetStreamSource(0, VB, 0, gvSizegeom);

pD3DDevice->SetStreamSourceFreq(1, (D3DSTREAMSOURCE_INSTANCEDATA | 1));
pD3DDevice->SetStreamSource(1, VB, 0, gvSizeInst);





effectShader->Begin( &uPasses, 0 );
for(DWORD iPass = 0; iPass < uPasses; iPass++ )
{
effectShader->BeginPass( iPass );

//CubeMesh->DrawSubset(0);
//here we draw with indexedPrimitive instead of DrawSubset
pD3DDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0,0, CubeMesh->GetNumVertices(),0, CubeMesh->GetNumFaces());



effectShader->EndPass();
}
effectShader->End();


pD3DDevice->SetStreamSourceFreq(0, 1);
pD3DDevice->SetStreamSourceFreq(1, 1);








/*
int vcount = (CubeMesh)->GetNumVertices();
int pcount = (CubeMesh)->GetNumFaces();

IDirect3DIndexBuffer9 *g_pIBMeshData = NULL;
IDirect3DVertexBuffer9 *pVB = NULL;

CubeMesh->GetIndexBuffer(&g_pIBMeshData);
CubeMesh->GetVertexBuffer( &pVB );
DWORD vertSize = CubeMesh->GetNumVertices() * 3 ;


DWORD fvf = CubeMesh->GetFVF();



UINT cPasses;
effectShader->Begin(&cPasses, 0);
for (DWORD iPass = 0; iPass < cPasses; iPass++)
{
effectShader->BeginPass(iPass) ;

pD3DDevice->SetFVF( fvf );
pD3DDevice->SetStreamSource(0, pVB, 0, vertSize );
pD3DDevice->SetIndices(g_pIBMeshData);

//CubeMesh->DrawSubset(iPass) ;
pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,vcount,0,pcount);
effectShader->EndPass() ;
}
effectShader->End() ;

*/



/*
effectShader->Begin( &uPasses, 0 );
for(DWORD iPass = 0; iPass < uPasses; iPass++ )
{
effectShader->BeginPass( iPass );

//CubeMesh->DrawSubset(0);






effectShader->EndPass();
}
effectShader->End();
*/





pD3DDevice->EndScene(); // End Scene

//NEW//////////////////NEW//////////////////NEW//////////////////NEW////////////////

pD3DDevice->Present( NULL, NULL, NULL, NULL );// Display The Result

return TRUE;
}



/////////////////////////////////////////////////////////////////////////////////////////////////
// THE KILL D3D SCENE
/////////////////////////////////////////////////////////////////////////////////////////////////
void KillD3DScene()
{
//NEW//////////////////NEW//////////////////NEW//////////////////NEW////////////////

//NEW//////////////////NEW//////////////////NEW//////////////////NEW////////////////
}



/////////////////////////////////////////////////////////////////////////////////////////////////
// THE KILL D3D WINDOW
/////////////////////////////////////////////////////////////////////////////////////////////////
void KillD3DWindow() // Properly Kill The Window
{

KillD3DScene(); // Release D3D Scene

if (pD3DDevice != NULL) pD3DDevice->Release(); // Release D3D Device

if (pD3D != NULL) pD3D->Release(); // Release D3D Interface

if (fullscreen) // Are We In Fullscreen Mode?
{
ChangeDisplaySettings(NULL,0); // If So Switch Back To The Desktop
ShowCursor(TRUE); // Show Mouse Pointer
}

if (hDC && !ReleaseDC(hWnd,hDC)) // Are We Able To Release The DC
{
MessageBox(NULL,"Release Device Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hDC=NULL; // Set DC To NULL
}

if (hWnd && !DestroyWindow(hWnd)) // Are We Able To Destroy The Window?
{
MessageBox(NULL,"Could Not Release hWnd.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hWnd=NULL; // Set hWnd To NULL
}

if (!UnregisterClass("Direct3D",hInstance)) // Are We Able To Unregister Class
{
MessageBox(NULL,"Could Not Unregister Class.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hInstance=NULL; // Set hInstance To NULL
}
}

/* This Code Creates Our DirectX 3D Window. Parameters Are: *
* title - Title To Appear At The Top Of The Window *
* width - Width Of The D3D Window Or Fullscreen Mode *
* height - Height Of The D3D Window Or Fullscreen Mode *
* fullscreenflag - Use Fullscreen Mode (TRUE) Or Windowed Mode (FALSE) */




/////////////////////////////////////////////////////////////////////////////////////////////////
// THE CREATE D3D WINDOW
/////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CreateD3DWindow(char* title, int width, int height, bool fullscreenflag)
{
WNDCLASS wc;
DWORD dwExstyle; // Window Extended style
DWORD dwstyle; // Window style
RECT WindowRect; // Grabs Rectangle Upper Left / Lower Right Values
WindowRect.left=(long)0; // Set Left Value To 0
WindowRect.right=(long)width; // Set Right Value To Requested Width
WindowRect.top=(long)0; // Set Top Value To 0
WindowRect.bottom=(long)height; // Set Bottom Value To Requested Height

fullscreen=fullscreenflag; // Set The Global Fullscreen Flag

hInstance = GetModuleHandle(NULL); // Grab An Instance For Our Window
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Size, And Own DC For Window.
wc.lpfnWndProc = (WNDPROC) WndProc; // WndProc Handles Messages
wc.cbClsExtra = 0; // No Extra Window Data
wc.cbWndExtra = 0; // No Extra Window Data
wc.hInstance = hInstance; // Set The Instance
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Load The Default Icon
wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Load The Arrow Pointer
wc.hbrBackground = NULL; // No Background Required For D3D
wc.lpszMenuName = NULL; // We Don't Want A Menu
wc.lpszClassName = "Direct3D"; // Set The Class Name


if (!RegisterClass(&wc)) // Attempt To Register The Window Class
{
MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

if (fullscreen) // Fullscreen Mode?
{
dwExstyle=WS_EX_APPWINDOW; // Window Extended style
dwstyle=WS_POPUP; // Windows style
ShowCursor(FALSE); // Hide Mouse Pointer
}
else
{
dwExstyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window Extended style
dwstyle=WS_OVERLAPPEDWINDOW; // Windows style
}


AdjustWindowRectEx(&WindowRect, dwstyle, FALSE, dwExstyle); // Adjust Window To True Requested Size


// Create The Window
if (!(hWnd=CreateWindowEx( dwExstyle, // Extended style For The Window
"Direct3D", // Class Name
title, // Window Title
dwstyle | // Defined Window style
WS_CLIPSIBLINGS | // Required Window style
WS_CLIPCHILDREN, // Required Window style
0, 0, // Window Position
WindowRect.right-WindowRect.left, // Calculate Window Width
WindowRect.bottom-WindowRect.top, // Calculate Window Height
NULL, // No Parent Window
NULL, // No Menu
hInstance, // Instance
NULL))) // Dont Pass Anything To WM_CREATE
{
KillD3DWindow(); // Reset The Display
MessageBox(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}


if (!(hDC=GetDC(hWnd))) // Did We Get A Device Context?
{
KillD3DWindow(); // Reset The Display
MessageBox(NULL,"Can't Create A Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}


pD3D = Direct3DCreate9( D3D_SDK_VERSION ); // Check for correct DirectX 3D version
if ( pD3D == NULL )
{
KillD3DWindow(); // Reset The Display
MessageBox(NULL,"Can't find D3D SDK Version 9.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}


D3DPRESENT_PARAMETERS d3dpp= // d3dpp Tells Windows How We Want Things To Be
{
width, // Back Buffer Width
height, // Back Buffer Height
D3DFMT_R5G6B5, // Back Buffer Format (Color Depth)
1, // Back Buffer Count (Double Buffer)
D3DMULTISAMPLE_NONE, // Multi Sample Type
0, // Multi Sample Quality
D3DSWAPEFFECT_DISCARD, // Swap Effect (Fast)
hWnd, // The Window Handle
!fullscreen, // Windowed or Fullscreen
TRUE, // Enable Auto Depth Stencil
D3DFMT_D16, // 16Bit Z-Buffer (Depth Buffer)
0, // No Flags
D3DPRESENT_RATE_DEFAULT, // Default Refresh Rate
D3DPRESENT_INTERVAL_DEFAULT // Default Presentation Interval (vertical sync)
};


// Check The Wanted Surface Format.
if ( FAILED( pD3D->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
d3dpp.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL,
D3DRTYPE_SURFACE, d3dpp.AutoDepthStencilFormat ) ) )
{
KillD3DWindow(); // Reset The Display
MessageBox(NULL,"Can't Find Surface Format.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}


// Create The DirectX 3D Device
if(FAILED( pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pD3DDevice ) ) )
{
KillD3DWindow(); // Reset The Display
MessageBox(NULL,"Can't Create DirectX 3D Device.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}


ShowWindow(hWnd,SW_SHOW); // Show The Window
SetForegroundWindow(hWnd); // Slightly Higher Priority
SetFocus(hWnd); // Sets Keyboard Focus To The Window
ReSizeD3DScene(width, height); // Set Up Our Perspective D3D Screen


if (!InitD3D()) // Initialize Our Newly Created D3D Window
{
KillD3DWindow(); // Reset The Display
MessageBox(NULL,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

return TRUE;
}



/////////////////////////////////////////////////////////////////////////////////////////////////
// THE WINDOW PROCEDURE
/////////////////////////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK WndProc( HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam )
{
switch( uMsg )
{
case WM_ACTIVATE: // Watch For Window Activate Message
{
if (!HIWORD(wParam)) // Check Minimization State
{
active=TRUE; // Program Is Active
}
else
{
active=FALSE; // Program Is No Longer Active
}

return 0; // Return To The Message Loop
}

case WM_SYSCOMMAND: // Intercept System Commands
{
switch (wParam) // Check System Calls
{
case SC_SCREENSAVE: // Screensaver Trying To Start?
case SC_MONITORPOWER: // Monitor Trying To Enter Powersave?
return 0; // Prevent From Happening
}
break; // Exit
}

case WM_CLOSE: // Did We Receive A Close Message?
{
PostQuitMessage(0); // Send A Quit Message
return 0; // Jump Back
}

case WM_KEYDOWN: // Is A Key Being Held Down?
{
keys[wParam] = TRUE; // If So, Mark It As TRUE
return 0; // Jump Back
}

case WM_KEYUP: // Has A Key Been Released?
{
keys[wParam] = FALSE; // If So, Mark It As FALSE
return 0; // Jump Back
}

case WM_SIZE: // Resize The Direct3D Window
{
if(!fullscreen)
ReSizeD3DScene(LOWORD(lParam), HIWORD(lParam)); // LoWord=Width, HiWord=Height
return 0; // Jump Back
}
}

// Pass All Unhandled Messages To DefWindowProc
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}



/////////////////////////////////////////////////////////////////////////////////////////////////
// THE WINMAIN
/////////////////////////////////////////////////////////////////////////////////////////////////
int WINAPI WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow )
{

MSG msg;
BOOL done=FALSE; // Bool Variable To Exit Loop

// Ask The User Which Screen Mode They Prefer
//if (MessageBox(NULL,"Would You Like To Run In Fullscreen Mode?", "Start FullScreen?",MB_YESNO|MB_ICONQUESTION)==IDNO)
//{
fullscreen=FALSE; // Windowed Mode
//}

// Create Our DirectX 3D Window
if (!CreateD3DWindow("APRON TUTORIALS",640,480,fullscreen))
{
return 0; // Quit If Window Was Not Created
}


while(!done) // Loop That Runs While done=FALSE
{
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) // Is There A Message Waiting?
{
if (msg.message==WM_QUIT) // Have We Received A Quit Message?
{
done=TRUE; // If So done=TRUE
}
else // If Not, Deal With Window Messages
{
TranslateMessage(&msg); // Translate The Message
DispatchMessage(&msg); // Dispatch The Message
}
}
else // If There Are No Messages
{

//NEW//////////////////NEW//////////////////NEW//////////////////NEW////////////////

Keyboard_Input();

//NEW//////////////////NEW//////////////////NEW//////////////////NEW////////////////

// Draw The Scene. Watch For ESC Key And Quit Messages From DrawD3DScene()
if ((active && !DrawD3DScene()) || keys[VK_ESCAPE]) // Active? Was There A Quit Received?
{
done=TRUE; // ESC or DrawD3DScene Signalled A Quit
}

if (keys[VK_F1]) // Is F1 Being Pressed?
{
keys[VK_F1]=FALSE; // If So Make Key FALSE
KillD3DWindow(); // Kill Our Current Window
fullscreen=!fullscreen; // Toggle Fullscreen / Windowed Mode
// Recreate Our DirectX 3D Window
if (!CreateD3DWindow("APRON TUTORIALS",640,480,fullscreen))
{
return 0; // Quit If Window Was Not Created
}
}
}
}

// Shutdown
KillD3DWindow();
return (msg.wParam); // Exit The Program
}


/////////////////////////////////////////////////////////////////////////////////////////////////
// THE KEYBOARD INPUT
/////////////////////////////////////////////////////////////////////////////////////////////////
void Keyboard_Input()
{
if(GetKeyState(VK_UP) & 0x80)
{
objCamera.Move_Camera( CAMERASPEED);
}

if(GetKeyState(VK_DOWN) & 0x80)
{
objCamera.Move_Camera(-CAMERASPEED);
}

//NEW//////////////////NEW//////////////////NEW//////////////////NEW////////////////

if(GetKeyState(VK_LEFT) & 0x80)
{
objCamera.Rotate_View( CAMERASPEED);
}

if(GetKeyState(VK_RIGHT) & 0x80)
{
objCamera.Rotate_View(-CAMERASPEED);
}

//NEW//////////////////NEW//////////////////NEW//////////////////NEW////////////////

}


/*
*****************************************************************************
NOTES:
*****************************************************************************

It’s impossible for people to move around physically in a "virtual 3D world",
we therefore use a "camera" to get orientated. When setting up a basic
camera in Direct3D there are two main subjects to be taken into consideration,
the camera handling and the perspective.


The standard Direct3D camera consists of three vectors: position, view and up.
The "position", is the actual point where the camera is located,
while the "view" is the target point that the camera is looking at.
If you're standing in a room looking at a picture on the wall,
then your eyes are the position and the picture is the view.
You can say that the position point and the target point form a
view-vector.The "up" or "tilt" decides if the camera is tilting
(used in flight simulators).


You can set up your "camera lens" in Direct3D by altering the perspective values.
The perspective of an Direct3D camera consists of four elements: fovy, aspect,
near and far. "Fovy" specifies the field of view angle, in degrees,
in the y-direction. "Aspect" specifies the aspect ratio that determines the
field of view in the x-direction. The aspect ratio is the ratio of x (width)
to y (height). "Near" specifies the distance from the viewer to the nearest
clipping plane (always positive). "Far" specifies the disistance from the viewer
to the far clipping plane (always positive).


This is the first camera tutorial it lets you move forward and backward.

The Move_Camera function moves the camera in the direction of our view vector.
This means that it moves along the view vector by the camera speed that is passed in.

The Position_Camera function positions the camera.

In this tutorial the view vector is parallel to the the z-axis,
so the camera is only able move forwards and backwards.

Use the arrow keys to move.

-----------------------------------------------------------------------------
*/

//Regards
//Ronny André Reierstad
//www.morrowland.com
//apron@morrowland.com









the hlsl is pretty much the same as posted

//-----------------
// un-tweaks
//-----------------
matrix WorldVP:WorldViewProjection;
matrix World:World;

float4x4 world;
float4x4 view;
float4x4 proj;



struct A2V
{
float3 Position : POSITION;
float3 Normal : NORMAL;
float2 TexCoord0 : TEXCOORD0;
float4 W0 : TEXCOORD1;
float4 W1 : TEXCOORD2;
float4 W2 : TEXCOORD3;
float4 W3 : TEXCOORD4;
};

struct V2P
{
float4 Position : POSITION;
float2 TexCoord0 : TEXCOORD0;

};

void VS(in A2V IN, out V2P OUT)
{
float4x4 object = float4x4(IN.W0, IN.W1, IN.W2, float4(IN.W3.xyz, 1.0f));
float4x4 objectworld = mul(object, world);
float4x4 WVP = mul(objectworld, mul(view, proj));
OUT.Position = mul(float4(IN.Position, 1.0f), WVP);
OUT.TexCoord0 = IN.TexCoord0;
}


//-----------------
// techniques
//-----------------
technique Draw
{
pass p1
{


vertexShader = compile vs_3_0 VS();
//pixelShader = compile ps_3_0 PS();
}
}








and the main header file


#ifndef _MAIN_H
#define _MAIN_H


#pragma comment(lib, "d3dx9.lib")
#pragma comment(lib, "d3d9.lib")

#include <windows.h> // Header File For Windows
#include <d3dx9.h> // Header File For DirectX 3D
#include <d3d9.h> // Header File For DirectX 3D


//NEW//////////////////NEW//////////////////NEW//////////////////NEW////////////////

#define CAMERASPEED 0.01f // The Camera Speed


//////////////////////////////////////
//The tVector3 Struct
//////////////////////////////////////
typedef struct tVector3 // expanded 3D vector struct
{
tVector3() {} // constructor
tVector3 (float new_x, float new_y, float new_z) // initialize constructor
{x = new_x; y = new_y; z = new_z;}
// overload + operator so that we easier can add vectors
tVector3 operator+(tVector3 vVector) {return tVector3(vVector.x+x, vVector.y+y, vVector.z+z);}
// overload - operator that we easier can subtract vectors
tVector3 operator-(tVector3 vVector) {return tVector3(x-vVector.x, y-vVector.y, z-vVector.z);}
// overload * operator that we easier can multiply by scalars
tVector3 operator*(float number) {return tVector3(x*number, y*number, z*number);}
// overload / operator that we easier can divide by a scalar
tVector3 operator/(float number) {return tVector3(x/number, y/number, z/number);}

float x, y, z; // 3D vector coordinates
}tVector3;


//////////////////////////////////////
//The CCamera Class
//////////////////////////////////////

class CCamera
{
public:

tVector3 mPos;
tVector3 mView;
tVector3 mUp;

//NEW//////////////////NEW//////////////////NEW//////////////////NEW////////////////

// This function rotates the camera view around the camera position
void Rotate_View(float speed);

//NEW//////////////////NEW//////////////////NEW//////////////////NEW////////////////

void Move_Camera(float speed);
void Position_Camera(float pos_x, float pos_y,float pos_z,
float view_x, float view_y, float view_z,
float up_x, float up_y, float up_z);
};



//////////////////////////////////////
// Global Variables
//////////////////////////////////////
extern HDC hDC; // Device context
extern HWND hWnd; // Holds our window handle
extern HINSTANCE hInstance; // Holds the instance of the application
extern LPDIRECT3D9 pD3D; // DirectX 3D Version 9
extern LPDIRECT3DDEVICE9 pD3DDevice; // DirectX 3D Rendering Device




//NEW//////////////////NEW//////////////////NEW//////////////////NEW////////////////

void Keyboard_Input();

//NEW//////////////////NEW//////////////////NEW//////////////////NEW////////////////




#endif

//Ronny André Reierstad
//www.morrowland.com
//apron@morrowland.com




and the camera header




#include "main.h"


/////////////////////////////////////////////////////////////////////////////////////////////////
// THE CCAMERA POSITION CAMERA
/////////////////////////////////////////////////////////////////////////////////////////////////
void CCamera::Position_Camera(float pos_x, float pos_y, float pos_z,
float view_x, float view_y, float view_z,
float up_x, float up_y, float up_z)
{
mPos = tVector3(pos_x, pos_y, pos_z ); // set position
mView = tVector3(view_x, view_y, view_z); // set view
mUp = tVector3(up_x, up_y, up_z ); // set the up vector
}


/////////////////////////////////////////////////////////////////////////////////////////////////
// THE CCAMERA MOVE CAMERA
/////////////////////////////////////////////////////////////////////////////////////////////////
void CCamera::Move_Camera(float speed)
{
tVector3 vVector = mView - mPos; // Get the view vector

// forward positive camera speed and backward negative camera speed.
mPos.x = mPos.x + vVector.x * speed;
mPos.z = mPos.z + vVector.z * speed;
mView.x = mView.x + vVector.x * speed;
mView.z = mView.z + vVector.z * speed;
}


//NEW//////////////////NEW//////////////////NEW//////////////////NEW////////////////

/////////////////////////////////////////////////////////////////////////////////////////////////
// THE CCAMERA ROTATE VIEW
/////////////////////////////////////////////////////////////////////////////////////////////////
void CCamera::Rotate_View(float speed)
{
tVector3 vVector = mView - mPos;

mView.z = (float)(mPos.z + sin(speed)*vVector.x + cos(speed)*vVector.z);
mView.x = (float)(mPos.x + cos(speed)*vVector.x - sin(speed)*vVector.z);
}

//NEW//////////////////NEW//////////////////NEW//////////////////NEW////////////////



//Ronny André Reierstad
//www.morrowland.com
//apron@morrowland.com





Share this post


Link to post
Share on other sites
Hey I think I got it working here is the code. Might be somewhat buggy at this point but I can definatly expand on this. If someone could go over this that would be sweet. Thanks all for the great help.


[source lang=cpp]

/************************************************************
* APRON TUTORIALS PRESENTED BY MORROWLAND *
*************************************************************
* Project Name : Camera2 *
* Project Description : Move and Rotate Camera *
* Project Type : DirectX 3D *
* Author : Ronny André Reierstad *
* Web Page : www.morrowland.com *
* E-Mail : apron@morrowland.com *
* Version : English (UK) *
* Date : 18.12.2003 *
************************************************************/



#include "main.h"


HDC hDC = NULL; // Private GDI Device Context
HWND hWnd = NULL; // Holds Our Window Handle
HINSTANCE hInstance; // Holds The Instance Of The Application
LPDIRECT3D9 pD3D = NULL; // DirectX 3D Version 9
LPDIRECT3DDEVICE9 pD3DDevice = NULL; // DirectX 3D Rendering Device

bool keys[256]; // Array Used For The Keyboard Routine
bool active=TRUE; // Window Active Flag Set To TRUE By Default
bool fullscreen=TRUE; // Fullscreen Flag Set To Fullscreen Mode By Default


ID3DXEffect* effectShader = NULL;

ID3DXMesh* CubeMesh;

IDirect3DIndexBuffer9 *IB = NULL;
IDirect3DVertexBuffer9 *VB = NULL;
IDirect3DVertexBuffer9 * gVBufferInst;

DWORD numVert;
DWORD numInd;


DWORD gvSizegeom = NULL;
DWORD gvSizeInst = NULL;

// Textures.
LPDIRECT3DTEXTURE9 Texture = NULL;


UINT uPasses; //used for render passes
D3DXMATRIX wrld[300];
D3DXMATRIX matTrans;
D3DXMATRIX matView;
D3DXMATRIX worldViewProjection;
D3DXMATRIX projection_matrix;
D3DXMATRIX IdentityMatrix;
D3DXMATRIX translation_matrix;
D3DXMATRIX rotation_matrix;
D3DXMATRIX modelViewProj;


//control the rotation of the cube
float g_fSpinX;
float g_fSpinY;
float g_fSpinZ;
float b;



int f2 = sizeof(FLOAT)*2;
int f3 = sizeof(FLOAT)*3;
int f4 = sizeof(FLOAT)*4;


D3DVERTEXELEMENT9 SDec[] =
{
{ 0, 0 ,D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, // pos
{ 1, f4 ,D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, // tex0
{ 2, f4 + f2 ,D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 }, // normal
{ 3, f4 + f2 + f3 ,D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0 }, // tangent
{ 4, f4 + f2 + f3 +f3 ,D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL, 0 }, // binormal

D3DDECL_END()
};



D3DVERTEXELEMENT9 VertexElementsGeom[] =
{
{0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
{0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
{0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
{1, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
{1, 16, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2},
{1, 32, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3},
{1, 48, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4},
D3DDECL_END()
};



IDirect3DVertexDeclaration9* ShaderDeclaration;




//NEW//////////////////NEW//////////////////NEW//////////////////NEW////////////////

CCamera objCamera;



LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration For WndProc




///////////////////////////////////////////////////////
// Load a .X file
///////////////////////////////////////////////////////
void LoadXFile_NoTexture( char* MeshFilename, ID3DXMesh* &Mesh)
{
//Zero Mesh and create buffer
Mesh = 0;
ID3DXBuffer* MeshBuffer = 0;

//Load and optimize the mesh
D3DXLoadMeshFromX( MeshFilename, D3DXMESH_MANAGED, pD3DDevice, &MeshBuffer, 0, 0, 0, &Mesh);


Mesh->OptimizeInplace(D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_COMPACT | D3DXMESHOPT_VERTEXCACHE, (DWORD*)MeshBuffer->GetBufferPointer(), 0, 0, 0);
Mesh->CloneMesh(D3DXMESH_MANAGED, SDec, pD3DDevice, &Mesh);

//compute tangets and binormals
D3DXComputeTangentFrame( Mesh, NULL );
D3DXComputeNormals(Mesh, NULL);

//Release and zero the buffer
MeshBuffer->Release();

//end of Function
}


// create effect from specified file and output errors if any
void LoadEffect(char* EffectFilename, ID3DXEffect* &d3dEffect)
{
ID3DXBuffer* d3dErrors = NULL;

D3DXCreateEffectFromFile(pD3DDevice, EffectFilename,NULL, NULL,
D3DXSHADER_OPTIMIZATION_LEVEL3 ,
NULL, &d3dEffect, &d3dErrors);

if(d3dErrors)
{
MessageBox(NULL, "Failed to load FX File", "CRITICAL ERROR!", MB_OK|MB_ICONEXCLAMATION);
d3dErrors->Release();
exit(-1);
}


HRESULT hr = d3dEffect->ValidateTechnique(d3dEffect->GetTechnique(0));

//End of Function
}



/////////////////////////////////////////////////////////////////////////////////////////////////
// THE RESIZE D3D SCENE
/////////////////////////////////////////////////////////////////////////////////////////////////
void ReSizeD3DScene(int width, int height) // Resize And Initialize The DX Window
{
if (height==0) // Prevent A Divide By Zero By
{
height=1; // Making Height Equal One
}


D3DXMatrixPerspectiveFovLH(&projection_matrix, 45.0f, (float)640/(float)480, 1.0f, 1000.0f );

pD3DDevice->SetTransform( D3DTS_PROJECTION, &(D3DMATRIX)projection_matrix );

}


/////////////////////////////////////////////////////////////////////////////////////////////////
// THE DIRECT3D INIT
/////////////////////////////////////////////////////////////////////////////////////////////////
int InitD3D()
{

D3DXMatrixIdentity( &projection_matrix );
D3DXMatrixPerspectiveFovLH(&projection_matrix, 45.0f, (float)640/(float)480, 0.1f, 1000.0f );

pD3DDevice->SetTransform( D3DTS_PROJECTION, &(D3DMATRIX)projection_matrix );


pD3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE ); // Z-Buffer (Depth Buffer)
pD3DDevice->SetRenderState(D3DRS_CULLMODE, TRUE); // Disable Backface Culling
pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE); // Disable Light



//NEW//////////////////NEW//////////////////NEW//////////////////NEW////////////////
// Position View Up(vector)
objCamera.Position_Camera(-15, 0.5f, -15, 0, 0.5f, 0, 0, 1, 0);

//NEW//////////////////NEW//////////////////NEW//////////////////NEW////////////////

LoadEffect("Instance.fx", effectShader);

LoadXFile_NoTexture("Sphere.x",CubeMesh);




DWORD numTrees = 300;


gvSizegeom = D3DXGetDeclVertexSize(VertexElementsGeom, 0);
gvSizeInst = D3DXGetDeclVertexSize(VertexElementsGeom, 1);
pD3DDevice->CreateVertexDeclaration(VertexElementsGeom, &ShaderDeclaration);
//meshx is your tree model (make sure it contains only position, normal & texcoord

CubeMesh->GetVertexBuffer( &VB );
CubeMesh->GetIndexBuffer( &IB );


pD3DDevice->CreateVertexBuffer(gvSizeInst * numTrees, D3DUSAGE_WRITEONLY, NULL, D3DPOOL_MANAGED, &gVBufferInst, NULL);

D3DXVECTOR3 ppos, prot;

for(int k = 0; k < numTrees; k++)
{
//put at some random position & rotation
ppos.x = rand() % 1000;
ppos.y = 0;
ppos.z = rand() % 1000;

D3DXMatrixIdentity( &wrld[k] );
D3DXMatrixTranslation( &wrld[k], ppos.x, ppos.y,ppos.z );


}

D3DXMATRIX* pData = 0;
gVBufferInst->Lock(0, 0, (LPVOID*)&pData, 0);
memcpy(pData, wrld, gvSizeInst * numTrees);
gVBufferInst->Unlock();

numVert = CubeMesh->GetNumVertices();
numInd = CubeMesh->GetNumFaces();
















// Load the decal image.
if(D3DXCreateTextureFromFile(pD3DDevice, "gothic.png", &Texture) != D3D_OK)
return false;


// Create the vertex declaration.
//if(pD3DDevice->CreateVertexDeclaration(SDec, &ShaderDeclaration) != D3D_OK)
// return false;

//CubeMesh->CloneMesh(D3DXMESH_MANAGED, SDec, pD3DDevice, &CubeMesh);



//image stage 1
pD3DDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
pD3DDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
pD3DDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
pD3DDevice->SetSamplerState(0, D3DSAMP_MAXANISOTROPY, 16);
// Specify that the texture tiles.
pD3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
pD3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);


return TRUE;
}



/////////////////////////////////////////////////////////////////////////////////////////////////
// THE DIRECT3D RENDER
/////////////////////////////////////////////////////////////////////////////////////////////////
int DrawD3DScene()
{


//NEW//////////////////NEW//////////////////NEW//////////////////NEW////////////////

// use this function for direct3d target camera
// View Matrix
D3DXMatrixLookAtLH(&matView, // Update View Matrix
&D3DXVECTOR3(objCamera.mPos.x, objCamera.mPos.y, objCamera.mPos.z),
&D3DXVECTOR3(objCamera.mView.x, objCamera.mView.y, objCamera.mView.z),
&D3DXVECTOR3(objCamera.mUp.x, objCamera.mUp.y, objCamera.mUp.z) );
pD3DDevice->SetTransform(D3DTS_VIEW,&matView);// Apply Changes To The View



pD3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
D3DCOLOR_COLORVALUE(0.0f,0.0f,0.0f,0.0f), 1.0f, 0 );

pD3DDevice->BeginScene(); // Begin Scene



D3DXMATRIX matWorld;
D3DXMatrixIdentity(&matWorld);


//control the rotation of the cube
g_fSpinX = g_fSpinX + 0.5;
g_fSpinY = g_fSpinY + 0.5;
g_fSpinZ = g_fSpinZ + 0.5;

D3DXMatrixTranslation( &translation_matrix, 0, 0.0f,0 );
//set as x,y,z rotation
D3DXMatrixRotationYawPitchRoll( &rotation_matrix,
D3DXToRadian(g_fSpinX),
D3DXToRadian(g_fSpinY),
D3DXToRadian(g_fSpinZ));

D3DXMatrixMultiply(&matWorld,&rotation_matrix,&translation_matrix);










LPDIRECT3DVERTEXBUFFER9 VBBuffer;
CubeMesh->GetVertexBuffer(&VBBuffer);

unsigned int uiVertices = CubeMesh->GetNumVertices();
unsigned int uiFaces = CubeMesh->GetNumFaces();

unsigned int uiSizeofFVF = D3DXGetFVFVertexSize(CubeMesh->GetFVF());


//pD3DDevice->SetStreamSource( 0, VBBuffer, 0, uiSizeofFVF) ;

pD3DDevice->SetFVF(CubeMesh->GetFVF());

LPDIRECT3DINDEXBUFFER9 IBBuffer;
CubeMesh->GetIndexBuffer(&IBBuffer);
//pD3DDevice->SetIndices( IBBuffer);



//pD3DDevice->SetIndices(IB);

//LPDIRECT3DVERTEXBUFFER9 tempVertexBuffer;
//mMesh->GetVertexBuffer(&tempVertexBuffer);
//mDevice->SetStreamSource( 0, tempVertexBuffer, 0, mMesh->GetNumBytesPerVertex() );
//mDevice->SetStreamSourceFreq( 0, D3DSTREAMSOURCE_INDEXEDDATA | 10 );


pD3DDevice->SetVertexDeclaration(ShaderDeclaration);
pD3DDevice->SetIndices( IB );

pD3DDevice->SetStreamSourceFreq(0, (D3DSTREAMSOURCE_INDEXEDDATA | 300));

pD3DDevice->SetStreamSource(0, VB, 0, gvSizegeom);


//pD3DDevice->SetStreamSource(0, VB, 0, gvSizegeom);
//pD3DDevice->SetStreamSource( 0, VBBuffer, 0, CubeMesh->GetNumBytesPerVertex()) ;

//pD3DDevice->SetStreamSourceFreq(1, (D3DSTREAMSOURCE_INSTANCEDATA | 1));
//pD3DDevice->SetStreamSource(1, VB, 0, 1);

pD3DDevice->SetStreamSourceFreq(1,(D3DSTREAMSOURCE_INSTANCEDATA | 1));
pD3DDevice->SetStreamSource(1,gVBufferInst , 0, gvSizeInst );



//DWORD numVert;
//DWORD numInd;


//pD3DDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0,0, CubeMesh->GetNumVertices(),0, CubeMesh->GetNumFaces());
DWORD fvf = CubeMesh->GetFVF();

effectShader->SetTechnique("Draw");

// Set the shader parameters.


effectShader->SetMatrix("world", wrld);
effectShader->SetMatrix("view", &matView);
effectShader->SetMatrix("proj", &projection_matrix);


UINT cPasses;
effectShader->Begin(&cPasses, 0);
for (DWORD iPass = 0; iPass < cPasses; iPass++)
{
effectShader->BeginPass(iPass) ;

// pD3DDevice->SetFVF( fvf );

//CubeMesh->DrawSubset(iPass) ;
pD3DDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0,0, numVert,0, numInd);
effectShader->EndPass() ;
}
effectShader->End() ;









/*
int vcount = (CubeMesh)->GetNumVertices();
int pcount = (CubeMesh)->GetNumFaces();

IDirect3DIndexBuffer9 *g_pIBMeshData = NULL;
IDirect3DVertexBuffer9 *pVB = NULL;

CubeMesh->GetIndexBuffer(&g_pIBMeshData);
CubeMesh->GetVertexBuffer( &pVB );
DWORD vertSize = CubeMesh->GetNumVertices() * 3 ;


DWORD fvf = CubeMesh->GetFVF();



UINT cPasses;
effectShader->Begin(&cPasses, 0);
for (DWORD iPass = 0; iPass < cPasses; iPass++)
{
effectShader->BeginPass(iPass) ;

pD3DDevice->SetFVF( fvf );
pD3DDevice->SetStreamSource(0, pVB, 0, vertSize );
pD3DDevice->SetIndices(g_pIBMeshData);

//CubeMesh->DrawSubset(iPass) ;
pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,vcount,0,pcount);
effectShader->EndPass() ;
}
effectShader->End() ;

*/



/*
effectShader->Begin( &uPasses, 0 );
for(DWORD iPass = 0; iPass < uPasses; iPass++ )
{
effectShader->BeginPass( iPass );

//CubeMesh->DrawSubset(0);






effectShader->EndPass();
}
effectShader->End();
*/





pD3DDevice->EndScene(); // End Scene

//NEW//////////////////NEW//////////////////NEW//////////////////NEW////////////////

pD3DDevice->Present( NULL, NULL, NULL, NULL );// Display The Result

return TRUE;
}



/////////////////////////////////////////////////////////////////////////////////////////////////
// THE KILL D3D SCENE
/////////////////////////////////////////////////////////////////////////////////////////////////
void KillD3DScene()
{
//NEW//////////////////NEW//////////////////NEW//////////////////NEW////////////////

//NEW//////////////////NEW//////////////////NEW//////////////////NEW////////////////
}



/////////////////////////////////////////////////////////////////////////////////////////////////
// THE KILL D3D WINDOW
/////////////////////////////////////////////////////////////////////////////////////////////////
void KillD3DWindow() // Properly Kill The Window
{

KillD3DScene(); // Release D3D Scene

if (pD3DDevice != NULL) pD3DDevice->Release(); // Release D3D Device

if (pD3D != NULL) pD3D->Release(); // Release D3D Interface

if (fullscreen) // Are We In Fullscreen Mode?
{
ChangeDisplaySettings(NULL,0); // If So Switch Back To The Desktop
ShowCursor(TRUE); // Show Mouse Pointer
}

if (hDC && !ReleaseDC(hWnd,hDC)) // Are We Able To Release The DC
{
MessageBox(NULL,"Release Device Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hDC=NULL; // Set DC To NULL
}

if (hWnd && !DestroyWindow(hWnd)) // Are We Able To Destroy The Window?
{
MessageBox(NULL,"Could Not Release hWnd.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hWnd=NULL; // Set hWnd To NULL
}

if (!UnregisterClass("Direct3D",hInstance)) // Are We Able To Unregister Class
{
MessageBox(NULL,"Could Not Unregister Class.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hInstance=NULL; // Set hInstance To NULL
}
}

/* This Code Creates Our DirectX 3D Window. Parameters Are: *
* title - Title To Appear At The Top Of The Window *
* width - Width Of The D3D Window Or Fullscreen Mode *
* height - Height Of The D3D Window Or Fullscreen Mode *
* fullscreenflag - Use Fullscreen Mode (TRUE) Or Windowed Mode (FALSE) */




/////////////////////////////////////////////////////////////////////////////////////////////////
// THE CREATE D3D WINDOW
/////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CreateD3DWindow(char* title, int width, int height, bool fullscreenflag)
{
WNDCLASS wc;
DWORD dwExStyle; // Window Extended Style
DWORD dwStyle; // Window Style
RECT WindowRect; // Grabs Rectangle Upper Left / Lower Right Values
WindowRect.left=(long)0; // Set Left Value To 0
WindowRect.right=(long)width; // Set Right Value To Requested Width
WindowRect.top=(long)0; // Set Top Value To 0
WindowRect.bottom=(long)height; // Set Bottom Value To Requested Height

fullscreen=fullscreenflag; // Set The Global Fullscreen Flag

hInstance = GetModuleHandle(NULL); // Grab An Instance For Our Window
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Size, And Own DC For Window.
wc.lpfnWndProc = (WNDPROC) WndProc; // WndProc Handles Messages
wc.cbClsExtra = 0; // No Extra Window Data
wc.cbWndExtra = 0; // No Extra Window Data
wc.hInstance = hInstance; // Set The Instance
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Load The Default Icon
wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Load The Arrow Pointer
wc.hbrBackground = NULL; // No Background Required For D3D
wc.lpszMenuName = NULL; // We Don't Want A Menu
wc.lpszClassName = "Direct3D"; // Set The Class Name


if (!RegisterClass(&wc)) // Attempt To Register The Window Class
{
MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

if (fullscreen) // Fullscreen Mode?
{
dwExStyle=WS_EX_APPWINDOW; // Window Extended Style
dwStyle=WS_POPUP; // Windows Style
ShowCursor(FALSE); // Hide Mouse Pointer
}
else
{
dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window Extended Style
dwStyle=WS_OVERLAPPEDWINDOW; // Windows Style
}


AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); // Adjust Window To True Requested Size


// Create The Window
if (!(hWnd=CreateWindowEx( dwExStyle, // Extended Style For The Window
"Direct3D", // Class Name
title, // Window Title
dwStyle | // Defined Window Style
WS_CLIPSIBLINGS | // Required Window Style
WS_CLIPCHILDREN, // Required Window Style
0, 0, // Window Position
WindowRect.right-WindowRect.left, // Calculate Window Width
WindowRect.bottom-WindowRect.top, // Calculate Window Height
NULL, // No Parent Window
NULL, // No Menu
hInstance, // Instance
NULL))) // Dont Pass Anything To WM_CREATE
{
KillD3DWindow(); // Reset The Display
MessageBox(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}


if (!(hDC=GetDC(hWnd))) // Did We Get A Device Context?
{
KillD3DWindow(); // Reset The Display
MessageBox(NULL,"Can't Create A Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}


pD3D = Direct3DCreate9( D3D_SDK_VERSION ); // Check for correct DirectX 3D version
if ( pD3D == NULL )
{
KillD3DWindow(); // Reset The Display
MessageBox(NULL,"Can't find D3D SDK Version 9.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}


D3DPRESENT_PARAMETERS d3dpp= // d3dpp Tells Windows How We Want Things To Be
{
width, // Back Buffer Width
height, // Back Buffer Height
D3DFMT_R5G6B5, // Back Buffer Format (Color Depth)
1, // Back Buffer Count (Double Buffer)
D3DMULTISAMPLE_NONE, // Multi Sample Type
0, // Multi Sample Quality
D3DSWAPEFFECT_DISCARD, // Swap Effect (Fast)
hWnd, // The Window Handle
!fullscreen, // Windowed or Fullscreen
TRUE, // Enable Auto Depth Stencil
D3DFMT_D16, // 16Bit Z-Buffer (Depth Buffer)
0, // No Flags
D3DPRESENT_RATE_DEFAULT, // Default Refresh Rate
D3DPRESENT_INTERVAL_DEFAULT // Default Presentation Interval (vertical sync)
};


// Check The Wanted Surface Format.
if ( FAILED( pD3D->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
d3dpp.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL,
D3DRTYPE_SURFACE, d3dpp.AutoDepthStencilFormat ) ) )
{
KillD3DWindow(); // Reset The Display
MessageBox(NULL,"Can't Find Surface Format.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}


// Create The DirectX 3D Device
if(FAILED( pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pD3DDevice ) ) )
{
KillD3DWindow(); // Reset The Display
MessageBox(NULL,"Can't Create DirectX 3D Device.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}


ShowWindow(hWnd,SW_SHOW); // Show The Window
SetForegroundWindow(hWnd); // Slightly Higher Priority
SetFocus(hWnd); // Sets Keyboard Focus To The Window
ReSizeD3DScene(width, height); // Set Up Our Perspective D3D Screen


if (!InitD3D()) // Initialize Our Newly Created D3D Window
{
KillD3DWindow(); // Reset The Display
MessageBox(NULL,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

return TRUE;
}



/////////////////////////////////////////////////////////////////////////////////////////////////
// THE WINDOW PROCEDURE
/////////////////////////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK WndProc( HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam )
{
switch( uMsg )
{
case WM_ACTIVATE: // Watch For Window Activate Message
{
if (!HIWORD(wParam)) // Check Minimization State
{
active=TRUE; // Program Is Active
}
else
{
active=FALSE; // Program Is No Longer Active
}

return 0; // Return To The Message Loop
}

case WM_SYSCOMMAND: // Intercept System Commands
{
switch (wParam) // Check System Calls
{
case SC_SCREENSAVE: // Screensaver Trying To Start?
case SC_MONITORPOWER: // Monitor Trying To Enter Powersave?
return 0; // Prevent From Happening
}
break; // Exit
}

case WM_CLOSE: // Did We Receive A Close Message?
{
PostQuitMessage(0); // Send A Quit Message
return 0; // Jump Back
}

case WM_KEYDOWN: // Is A Key Being Held Down?
{
keys[wParam] = TRUE; // If So, Mark It As TRUE
return 0; // Jump Back
}

case WM_KEYUP: // Has A Key Been Released?
{
keys[wParam] = FALSE; // If So, Mark It As FALSE
return 0; // Jump Back
}

case WM_SIZE: // Resize The Direct3D Window
{
if(!fullscreen)
ReSizeD3DScene(LOWORD(lParam), HIWORD(lParam)); // LoWord=Width, HiWord=Height
return 0; // Jump Back
}
}

// Pass All Unhandled Messages To DefWindowProc
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}



/////////////////////////////////////////////////////////////////////////////////////////////////
// THE WINMAIN
/////////////////////////////////////////////////////////////////////////////////////////////////
int WINAPI WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow )
{

MSG msg;
BOOL done=FALSE; // Bool Variable To Exit Loop

// Ask The User Which Screen Mode They Prefer
//if (MessageBox(NULL,"Would You Like To Run In Fullscreen Mode?", "Start FullScreen?",MB_YESNO|MB_ICONQUESTION)==IDNO)
//{
fullscreen=FALSE; // Windowed Mode
//}

// Create Our DirectX 3D Window
if (!CreateD3DWindow("APRON TUTORIALS",640,480,fullscreen))
{
return 0; // Quit If Window Was Not Created
}


while(!done) // Loop That Runs While done=FALSE
{
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) // Is There A Message Waiting?
{
if (msg.message==WM_QUIT) // Have We Received A Quit Message?
{
done=TRUE; // If So done=TRUE
}
else // If Not, Deal With Window Messages
{
TranslateMessage(&msg); // Translate The Message
DispatchMessage(&msg); // Dispatch The Message
}
}
else // If There Are No Messages
{

//NEW//////////////////NEW//////////////////NEW//////////////////NEW////////////////

Keyboard_Input();

//NEW//////////////////NEW//////////////////NEW//////////////////NEW////////////////

// Draw The Scene. Watch For ESC Key And Quit Messages From DrawD3DScene()
if ((active && !DrawD3DScene()) || keys[VK_ESCAPE]) // Active? Was There A Quit Received?
{
done=TRUE; // ESC or DrawD3DScene Signalled A Quit
}

if (keys[VK_F1]) // Is F1 Being Pressed?
{
keys[VK_F1]=FALSE; // If So Make Key FALSE
KillD3DWindow(); // Kill Our Current Window
fullscreen=!fullscreen; // Toggle Fullscreen / Windowed Mode
// Recreate Our DirectX 3D Window
if (!CreateD3DWindow("APRON TUTORIALS",640,480,fullscreen))
{
return 0; // Quit If Window Was Not Created
}
}
}
}

// Shutdown
KillD3DWindow();
return (msg.wParam); // Exit The Program
}


/////////////////////////////////////////////////////////////////////////////////////////////////
// THE KEYBOARD INPUT
/////////////////////////////////////////////////////////////////////////////////////////////////
void Keyboard_Input()
{
if(GetKeyState(VK_UP) & 0x80)
{
objCamera.Move_Camera( CAMERASPEED);
}

if(GetKeyState(VK_DOWN) & 0x80)
{
objCamera.Move_Camera(-CAMERASPEED);
}

//NEW//////////////////NEW//////////////////NEW//////////////////NEW////////////////

if(GetKeyState(VK_LEFT) & 0x80)
{
objCamera.Rotate_View( CAMERASPEED);
}

if(GetKeyState(VK_RIGHT) & 0x80)
{
objCamera.Rotate_View(-CAMERASPEED);
}

//NEW//////////////////NEW//////////////////NEW//////////////////NEW////////////////

}


/*
*****************************************************************************
NOTES:
*****************************************************************************

It’s impossible for people to move around physically in a "virtual 3D world",
we therefore use a "camera" to get orientated. When setting up a basic
camera in Direct3D there are two main subjects to be taken into consideration,
the camera handling and the perspective.


The standard Direct3D camera consists of three vectors: position, view and up.
The "position", is the actual point where the camera is located,
while the "view" is the target point that the camera is looking at.
If you're standing in a room looking at a picture on the wall,
then your eyes are the position and the picture is the view.
You can say that the position point and the target point form a
view-vector.The "up" or "tilt" decides if the camera is tilting
(used in flight simulators).


You can set up your "camera lens" in Direct3D by altering the perspective values.
The perspective of an Direct3D camera consists of four elements: fovy, aspect,
near and far. "Fovy" specifies the field of view angle, in degrees,
in the y-direction. "Aspect" specifies the aspect ratio that determines the
field of view in the x-direction. The aspect ratio is the ratio of x (width)
to y (height). "Near" specifies the distance from the viewer to the nearest
clipping plane (always positive). "Far" specifies the disistance from the viewer
to the far clipping plane (always positive).


This is the first camera tutorial it lets you move forward and backward.

The Move_Camera function moves the camera in the direction of our view vector.
This means that it moves along the view vector by the camera speed that is passed in.

The Position_Camera function positions the camera.

In this tutorial the view vector is parallel to the the z-axis,
so the camera is only able move forwards and backwards.

Use the arrow keys to move.

-----------------------------------------------------------------------------
*/

//Regards
//Ronny André Reierstad
//www.morrowland.com
//apron@morrowland.com



Share this post


Link to post
Share on other sites
Well, I have everything working fine until I tried to make cull based on frustum. I think it should work, but I am obviously going wrong somewhere. I think I have followed the advice exactly as I was suppose to. Anyways, the grass is not drawing based on the frustum data.

Here is the code im using to check and then I try to mem copy the new matrix data but its not working as expected. I'm getting mixed results, it seems as if I am very close to getting it. Thank you.





//build up a dynamic list of data to render each frame based on if its in the frustum or not
UINT GrassCount = 0;



for( int i = 0; i < MAX_GRASS; i++)
{

//compare against the original
//MyGrassBase.ScaleObject( .2,.2,.2 );
MyGrassBase.PositionObject( wrld[i]._41,wrld[i]._42,wrld[i]._43);
MyGrassBase.ComputeWorldMatrix(false);

D3DXVECTOR3 pos;
pos.x = wrld[i]._41;
pos.y = wrld[i]._42;
pos.z = wrld[i]._43;

if( MyGrassBase.SphereInFrustum( &pos , 1 ) == true ){

wrld2[GrassCount]._41 = pos.x;
wrld2[GrassCount]._42 = pos.y;
wrld2[GrassCount]._43 = pos.z;
GrassCount++;

//these cubes are just placeholders and I know the frustum culling is working
MyCubeBase.PositionObject( wrld2[GrassCount]._41, wrld2[GrassCount]._42, wrld2[GrassCount]._43 );
MyCubeBase.ComputeWorldMatrix(false);
MyCubeBase.SetShaderOff();
MyCubeBase.Render();

//D3DXMatrixTranspose( &wrld2[GrassCount], &wrld2[GrassCount]);


}

}


D3DXMATRIX* pData = 0;
gVBufferInst->Lock(0, 0, (LPVOID*)&pData, 0);
memcpy(pData, wrld2, gvSizeInst * GrassCount);
gVBufferInst->Unlock();



dx->SetCullMode(2);
D3DDevice->SetVertexDeclaration(ShaderDeclaration);
D3DDevice->SetIndices( IB );

D3DDevice->SetStreamSourceFreq(0, (D3DSTREAMSOURCE_INDEXEDDATA | GrassCount));
D3DDevice->SetStreamSource(0, VB, 0, gvSizegeom);

D3DDevice->SetStreamSourceFreq(1,(D3DSTREAMSOURCE_INSTANCEDATA | 1));
D3DDevice->SetStreamSource(1, gVBufferInst , 0, gvSizeInst );


effectShader->SetTechnique("Draw");

// Set the shader parameters.

D3DXMATRIX WorldInverseTranspose;

D3DXMatrixInverse( &WorldInverseTranspose,0, wrld2 );
D3DXMatrixTranspose(&WorldInverseTranspose, &WorldInverseTranspose);

effectShader->SetMatrix("world", wrld2);
effectShader->SetMatrix("view", &ViewMatrix);
effectShader->SetMatrix("proj", &ProjectionMatrix);
effectShader->SetMatrix("WorldInverseTranspose", &WorldInverseTranspose);

effectShader->SetTexture( "ModelTexture", Texture0 );


UINT cPasses;
effectShader->Begin(&cPasses, 0);
for (DWORD iPass = 0; iPass < cPasses; iPass++)
{
effectShader->BeginPass(iPass) ;

//CubeMesh->DrawSubset(iPass) ;
D3DDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0,0, numVert,0, numInd);
effectShader->EndPass() ;
}
effectShader->End() ;



D3DDevice->SetStreamSourceFreq(0,1);
D3DDevice->SetStreamSourceFreq(1,1);

dx->SetCullMode(0);









I'm basically trying to check it an object is visible, if so then put its matrix data into an array and add a count so I know how many items have been added. Then memcopy this matrix data into the buffer and feed it into the shader using the new world data list. I think I'm going wrong with either the memcopy or the way I'm submitting the data to the shader.


EDIT: I figured out the problem it was in the shader world calculation. Works as expected now. Thanks All. Gonna have to give some Rep for this one. lol.

[Edited by - david w on December 30, 2010 10:10:59 AM]

Share this post


Link to post
Share on other sites

This topic is 2538 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this