Original Post
Hi All,
Since leaving uni and getting a real job I haven't been around on these board a lot, mainly due to the complete lack of programming I have done outside of the office, however recently I decided to start learning 3D programming from a technical standpoint using native Direct X (In the past I have always used wrappers, Ogre, XNA etc).
I have been following a few tutorials learning the syntax and how things fit together, and have come to the topic of lighting, I quickly hacked together my first lighted demo app and amnoticing a very strange occurance that I cannot explain and was hoping a fellow board member could enlighten me as to what is happening.
The program is a simple app that sets up a cube, renders it and allows the user to interact using the keyboard to translate, rotate and scale it. With the D3DRS_LIGHTING renderstate set to false the app works fine, you are able to move the cube around with no problems, (Code listing 2 below). The problem occurs when I refactor the code slightly to turn D3DRS_LIGHTING on and setup one light. The app initially works fine, the cube is correctly lit throught the user moving it, however precicely 6 seconds after the program starts a second cube "Appears" at the origin, this cube then procceeds to play back the motions of the original cube precicely 6 seconds after they happened, mirroring all movements, scaling changes and rotations.
Now barring that I may have accidently stubled upon AI which is currently playing tricks with me and may soon take over the world, I am failing to remove/add bits of code to track down what exactly is causing this strange occurance.
Thanks a lot for any help,
Scott
Code listings for D3D9 setup [1], the program with no lighting[2] and the program with lighting and strange behaviour[3] follow, aswell as my typedefs for a few of D3D's types:
Since leaving uni and getting a real job I haven't been around on these board a lot, mainly due to the complete lack of programming I have done outside of the office, however recently I decided to start learning 3D programming from a technical standpoint using native Direct X (In the past I have always used wrappers, Ogre, XNA etc).
I have been following a few tutorials learning the syntax and how things fit together, and have come to the topic of lighting, I quickly hacked together my first lighted demo app and amnoticing a very strange occurance that I cannot explain and was hoping a fellow board member could enlighten me as to what is happening.
The program is a simple app that sets up a cube, renders it and allows the user to interact using the keyboard to translate, rotate and scale it. With the D3DRS_LIGHTING renderstate set to false the app works fine, you are able to move the cube around with no problems, (Code listing 2 below). The problem occurs when I refactor the code slightly to turn D3DRS_LIGHTING on and setup one light. The app initially works fine, the cube is correctly lit throught the user moving it, however precicely 6 seconds after the program starts a second cube "Appears" at the origin, this cube then procceeds to play back the motions of the original cube precicely 6 seconds after they happened, mirroring all movements, scaling changes and rotations.
Now barring that I may have accidently stubled upon AI which is currently playing tricks with me and may soon take over the world, I am failing to remove/add bits of code to track down what exactly is causing this strange occurance.
Thanks a lot for any help,
Scott
Code listings for D3D9 setup [1], the program with no lighting[2] and the program with lighting and strange behaviour[3] follow, aswell as my typedefs for a few of D3D's types:
#include "DeviceManager.h"
#include "ApplicationDisplay.h"
namespace XF
{
namespace GFX
{
DeviceManager::DeviceManager()
{
d3d = NULL;
d3dDevice = NULL;
}
bool DeviceManager::Init(HWND hWnd, ApplicationDisplay &appDisp)
{
d3d = Direct3DCreate9(D3D_SDK_VERSION);
if(!d3d)
return false;
ZeroMemory(&d3dPP, sizeof(d3dPP));
d3dPP.Windowed = !appDisp.Fullscreen();
d3dPP.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dPP.hDeviceWindow = hWnd;
d3dPP.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dPP.BackBufferWidth = appDisp.WindowWidth();
d3dPP.BackBufferHeight = appDisp.WindowHeight();
d3dPP.EnableAutoDepthStencil = TRUE;
d3dPP.AutoDepthStencilFormat = D3DFMT_D16;
if(FAILED(d3d->CreateDevice(
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dPP,
&d3dDevice)))
{
return false;
}
d3dDevice->SetRenderState(D3DRS_ZENABLE, true);
return true;
}
void DeviceManager::Destroy()
{
d3dDevice->Release();
d3d->Release();
}
void DeviceManager::BeginFrame()
{
d3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
d3dDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
d3dDevice->BeginScene();
}
void DeviceManager::EndFrame()
{
d3dDevice->EndScene();
d3dDevice->Present(NULL, NULL, NULL, NULL);
}
}
}
#include "TestGameScreen.h"
#define CUSTOMFVF (D3DFVF_XYZ | D3DFVF_DIFFUSE)
struct CustomVertex
{
float x, y, z;
DWORD diffuse;
};
bool TestGameScreen::OnInit()
{
CustomVertex vertices[] =
{
{ -1.0f, 1.0f, -1.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 1.0f, 1.0f, -1.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ -1.0f, -1.0f, -1.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ 1.0f, -1.0f, -1.0f, D3DCOLOR_XRGB(0, 255, 255), },
{ -1.0f, 1.0f, 1.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 1.0f, 1.0f, 1.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ -1.0f, -1.0f, 1.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ 1.0f, -1.0f, 1.0f, D3DCOLOR_XRGB(0, 255, 255), },
};
short indices[] =
{
0, 1, 2, // side 1
2, 1, 3,
4, 0, 6, // side 2
6, 0, 2,
7, 5, 6, // side 3
6, 5, 4,
3, 1, 7, // side 4
7, 1, 5,
4, 5, 0, // side 5
0, 5, 1,
3, 7, 2, // side 6
2, 7, 6,
};
app->device.GetDevice()->CreateVertexBuffer(
24 * sizeof(CustomVertex),
0,
CUSTOMFVF,
D3DPOOL_MANAGED,
&vBuffer,
NULL);
app->device.GetDevice()->CreateIndexBuffer(
36 * sizeof(short),
0,
D3DFMT_INDEX16,
D3DPOOL_MANAGED,
&iBuffer,
NULL);
void* voidPtr;
vBuffer->Lock(0, 0, (void**)&voidPtr, 0);
memcpy(voidPtr, vertices, sizeof(vertices));
vBuffer->Unlock();
iBuffer->Lock(0, 0, (void**)&voidPtr, 0);
memcpy(voidPtr, indices, sizeof(indices));
iBuffer->Unlock();
D3DXMatrixLookAtLH( &viewMatrix,
&XF::GFX::Vector3(0.0f, 0.0f, 10.0f),
&XF::GFX::Vector3Zero,
&XF::GFX::Vector3Up);
D3DXMatrixPerspectiveFovLH( &projMatrix,
D3DXToRadian(45),
(float)app->device.GetPresentationParameters().BackBufferWidth /
(float)app->device.GetPresentationParameters().BackBufferHeight,
1.0f,
100.0f);
position = XF::GFX::Vector3Zero;
rotation = XF::GFX::Vector3Zero;
scale = XF::GFX::Vector3One;
ZeroMemory(&light, sizeof(light));
light.Type = D3DLIGHT_DIRECTIONAL;
light.Diffuse = D3DXCOLOR(0.5f, 0.5f, 0.5f, 1.0f);
light.Direction = XF::GFX::Vector3(-1.0f, -0.3f, -1.0f);
app->device.GetDevice()->SetLight(0, &light);
app->device.GetDevice()->LightEnable(0, false);
ZeroMemory(&material, sizeof(XF::GFX::D3DMaterial));
material.Diffuse = D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f);
material.Ambient = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
app->device.GetDevice()->SetMaterial(&material);
return true;
}
void TestGameScreen::OnUpdate(float dT)
{
if(app->input.KeyDown(XF::Keys::Q))
{
scale.x -= 1.0f * dT;
scale.y -= 1.0f * dT;
scale.z -= 1.0f * dT;
}
if(app->input.KeyDown(XF::Keys::R))
{
scale.x += 1.0f * dT;
scale.y += 1.0f * dT;
scale.z += 1.0f * dT;
}
if(app->input.KeyDown(XF::Keys::Up))
position.y += 0.5f * dT;
if(app->input.KeyDown(XF::Keys::Down))
position.y -= 0.5f * dT;
if(app->input.KeyDown(XF::Keys::Left))
position.x += 0.5f * dT;
if(app->input.KeyDown(XF::Keys::Right))
position.x -= 0.5f * dT;
if(app->input.KeyDown(XF::Keys::W))
rotation.z -= 0.5f * dT;
if(app->input.KeyDown(XF::Keys::E))
rotation.z += 0.5f * dT;
if(app->input.KeyDown(XF::Keys::S))
rotation.y -= 0.5f * dT;
if(app->input.KeyDown(XF::Keys:<img src='http://public.gamedev.net/public/style_emoticons/<#EMO_DIR#>/biggrin.gif' class='bbc_emoticon' alt=':D' />))
rotation.y += 0.5f * dT;
}
void TestGameScreen::OnDraw()
{
app->device.GetDevice()->SetRenderState(D3DRS_LIGHTING, false);
//app->device.GetDevice()->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(50, 50, 50));
app->device.GetDevice()->SetFVF(CUSTOMFVF);
XF::GFX::Matrix positionMatrix;
D3DXMatrixTranslation(&positionMatrix,
position.x,
position.y,
position.z);
XF::GFX::Matrix rotationMatrix;
D3DXMatrixRotationYawPitchRoll(
&rotationMatrix,
rotation.y,
rotation.x,
rotation.z);
XF::GFX::Matrix scaleMatrix;
D3DXMatrixScaling(&scaleMatrix,
scale.x,
scale.y,
scale.z);
app->device.GetDevice()->SetTransform(D3DTS_WORLD,
&(rotationMatrix * scaleMatrix * positionMatrix));
app->device.GetDevice()->SetTransform(D3DTS_VIEW, &viewMatrix);
app->device.GetDevice()->SetTransform(D3DTS_PROJECTION, &projMatrix);
app->device.GetDevice()->SetStreamSource(0, vBuffer, 0, sizeof(CustomVertex));
app->device.GetDevice()->SetIndices(iBuffer);
app->device.GetDevice()->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12);
}
void TestGameScreen::OnDestroy()
{
vBuffer->Release();
iBuffer->Release();
}
#include "TestGameScreen.h"
#define CUSTOMFVF (D3DFVF_XYZ | D3DFVF_NORMAL)
struct CustomVertex
{
float x, y, z;
XF::GFX::Vector3 normal;
};
bool TestGameScreen::OnInit()
{
CustomVertex vertices[] =
{
{ -1.0f, -1.0f, 1.0f, XF::GFX::Vector3(0.0f, 0.0f, 1.0f), }, // side 1
{ 1.0f, -1.0f, 1.0f, XF::GFX::Vector3(0.0f, 0.0f, 1.0f), },
{ -1.0f, 1.0f, 1.0f, XF::GFX::Vector3(0.0f, 0.0f, 1.0f), },
{ 1.0f, 1.0f, 1.0f, XF::GFX::Vector3(0.0f, 0.0f, 1.0f), },
{ -1.0f, -1.0f, -1.0f, XF::GFX::Vector3(0.0f, 0.0f, -1.0f), }, // side 2
{ -1.0f, 1.0f, -1.0f, XF::GFX::Vector3(0.0f, 0.0f, -1.0f), },
{ 1.0f, -1.0f, -1.0f, XF::GFX::Vector3(0.0f, 0.0f, -1.0f), },
{ 1.0f, 1.0f, -1.0f, XF::GFX::Vector3(0.0f, 0.0f, -1.0f), },
{ -1.0f, 1.0f, -1.0f, XF::GFX::Vector3(0.0f, 1.0f, 0.0f), }, // side 3
{ -1.0f, 1.0f, 1.0f, XF::GFX::Vector3(0.0f, 1.0f, 0.0f), },
{ 1.0f, 1.0f, -1.0f, XF::GFX::Vector3(0.0f, 1.0f, 0.0f), },
{ 1.0f, 1.0f, 1.0f, XF::GFX::Vector3(0.0f, 1.0f, 0.0f), },
{ -1.0f, -1.0f, -1.0f, XF::GFX::Vector3(0.0f, -1.0f, 0.0f), }, // side 4
{ 1.0f, -1.0f, -1.0f, XF::GFX::Vector3(0.0f, -1.0f, 0.0f), },
{ -1.0f, -1.0f, 1.0f, XF::GFX::Vector3(0.0f, -1.0f, 0.0f), },
{ 1.0f, -1.0f, 1.0f, XF::GFX::Vector3(0.0f, -1.0f, 0.0f), },
{ 1.0f, -1.0f, -1.0f, XF::GFX::Vector3(1.0f, 0.0f, 0.0f), }, // side 5
{ 1.0f, 1.0f, -1.0f, XF::GFX::Vector3(1.0f, 0.0f, 0.0f), },
{ 1.0f, -1.0f, 1.0f, XF::GFX::Vector3(1.0f, 0.0f, 0.0f), },
{ 1.0f, 1.0f, 1.0f, XF::GFX::Vector3(1.0f, 0.0f, 0.0f), },
{ -1.0f, -1.0f, -1.0f, XF::GFX::Vector3(-1.0f, 0.0f, 0.0f), }, // side 6
{ -1.0f, -1.0f, 1.0f, XF::GFX::Vector3(-1.0f, 0.0f, 0.0f), },
{ -1.0f, 1.0f, -1.0f, XF::GFX::Vector3(-1.0f, 0.0f, 0.0f), },
{ -1.0f, 1.0f, 1.0f, XF::GFX::Vector3(-1.0f, 0.0f, 0.0f), },
};
short indices[] =
{
0, 1, 2, // side 1
2, 1, 3,
4, 5, 6, // side 2
6, 5, 7,
8, 9, 10, // side 3
10, 9, 11,
12, 13, 14, // side 4
14, 13, 15,
16, 17, 18, // side 5
18, 17, 19,
20, 21, 22, // side 6
22, 21, 23,
};
app->device.GetDevice()->CreateVertexBuffer(
24 * sizeof(CustomVertex),
0,
CUSTOMFVF,
D3DPOOL_MANAGED,
&vBuffer,
NULL);
app->device.GetDevice()->CreateIndexBuffer(
36 * sizeof(short),
0,
D3DFMT_INDEX16,
D3DPOOL_MANAGED,
&iBuffer,
NULL);
void* voidPtr;
vBuffer->Lock(0, 0, (void**)&voidPtr, 0);
memcpy(voidPtr, vertices, sizeof(vertices));
vBuffer->Unlock();
iBuffer->Lock(0, 0, (void**)&voidPtr, 0);
memcpy(voidPtr, indices, sizeof(indices));
iBuffer->Unlock();
D3DXMatrixLookAtLH( &viewMatrix,
&XF::GFX::Vector3(0.0f, 0.0f, 10.0f),
&XF::GFX::Vector3Zero,
&XF::GFX::Vector3Up);
D3DXMatrixPerspectiveFovLH( &projMatrix,
D3DXToRadian(45),
(float)app->device.GetPresentationParameters().BackBufferWidth /
(float)app->device.GetPresentationParameters().BackBufferHeight,
1.0f,
100.0f);
position = XF::GFX::Vector3Zero;
rotation = XF::GFX::Vector3Zero;
scale = XF::GFX::Vector3One;
ZeroMemory(&light, sizeof(light));
light.Type = D3DLIGHT_DIRECTIONAL;
light.Diffuse = D3DXCOLOR(0.5f, 0.5f, 0.5f, 1.0f);
light.Direction = XF::GFX::Vector3(-1.0f, -0.3f, -1.0f);
app->device.GetDevice()->SetLight(0, &light);
app->device.GetDevice()->LightEnable(0, true);
ZeroMemory(&material, sizeof(XF::GFX::D3DMaterial));
material.Diffuse = D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f);
material.Ambient = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
app->device.GetDevice()->SetMaterial(&material);
return true;
}
void TestGameScreen::OnUpdate(float dT)
{
if(app->input.KeyDown(XF::Keys::Q))
{
scale.x -= 1.0f * dT;
scale.y -= 1.0f * dT;
scale.z -= 1.0f * dT;
}
if(app->input.KeyDown(XF::Keys::R))
{
scale.x += 1.0f * dT;
scale.y += 1.0f * dT;
scale.z += 1.0f * dT;
}
if(app->input.KeyDown(XF::Keys::Up))
position.y += 0.5f * dT;
if(app->input.KeyDown(XF::Keys::Down))
position.y -= 0.5f * dT;
if(app->input.KeyDown(XF::Keys::Left))
position.x += 0.5f * dT;
if(app->input.KeyDown(XF::Keys::Right))
position.x -= 0.5f * dT;
if(app->input.KeyDown(XF::Keys::W))
rotation.z -= 0.5f * dT;
if(app->input.KeyDown(XF::Keys::E))
rotation.z += 0.5f * dT;
if(app->input.KeyDown(XF::Keys::S))
rotation.y -= 0.5f * dT;
if(app->input.KeyDown(XF::Keys:<img src='http://public.gamedev.net/public/style_emoticons/<#EMO_DIR#>/biggrin.gif' class='bbc_emoticon' alt=':D' />))
rotation.y += 0.5f * dT;
}
void TestGameScreen::OnDraw()
{
app->device.GetDevice()->SetRenderState(D3DRS_LIGHTING, true);
app->device.GetDevice()->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(50, 50, 50));
app->device.GetDevice()->SetFVF(CUSTOMFVF);
XF::GFX::Matrix positionMatrix;
D3DXMatrixTranslation(&positionMatrix,
position.x,
position.y,
position.z);
XF::GFX::Matrix rotationMatrix;
D3DXMatrixRotationYawPitchRoll(
&rotationMatrix,
rotation.y,
rotation.x,
rotation.z);
XF::GFX::Matrix scaleMatrix;
D3DXMatrixScaling(&scaleMatrix,
scale.x,
scale.y,
scale.z);
app->device.GetDevice()->SetTransform(D3DTS_WORLD,
&(rotationMatrix * scaleMatrix * positionMatrix));
app->device.GetDevice()->SetTransform(D3DTS_VIEW, &viewMatrix);
app->device.GetDevice()->SetTransform(D3DTS_PROJECTION, &projMatrix);
app->device.GetDevice()->SetStreamSource(0, vBuffer, 0, sizeof(CustomVertex));
app->device.GetDevice()->SetIndices(iBuffer);
app->device.GetDevice()->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12);
}
void TestGameScreen::OnDestroy()
{
vBuffer->Release();
iBuffer->Release();
}
#include <Windows.h>
#include <d3d9.h>
#include <d3dx9.h>
#ifndef XF_GFX_DX9TYPEDEFSANDDEFINES_H
#define XF_GFX_DX9TYPEDEFSANDDEFINES_H
namespace XF
{
namespace GFX
{
typedef LPDIRECT3D9 Direct3D;
typedef LPDIRECT3DDEVICE9 Direct3DDevice;
typedef D3DPRESENT_PARAMETERS PresentationParameters;
typedef LPDIRECT3DVERTEXBUFFER9 VertexBuffer;
typedef LPDIRECT3DINDEXBUFFER9 IndexBuffer;
typedef D3DXMATRIX Matrix;
static const Matrix MatrixIdentity = Matrix(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f);
typedef D3DXVECTOR3 Vector3;
static const Vector3 Vector3Zero = Vector3(0.0f, 0.0f, 0.0f);
static const Vector3 Vector3One = Vector3(1.0f, 1.0f, 1.0f);
static const Vector3 Vector3Up = Vector3(0.0f, 1.0f, 0.0f);
static const Vector3 Vector3Down = Vector3(0.0f, -1.0f, 0.0f);
static const Vector3 Vector3Left = Vector3(-1.0f, 0.0f, 0.0f);
static const Vector3 Vector3Right = Vector3(1.0f, 0.0f, 0.0f);
static const Vector3 Vector3In = Vector3(0.0f, 0.0f, 1.0f);
static const Vector3 Vector3Out = Vector3(0.0f, 0.0f, -1.0f);
typedef D3DXVECTOR2 Vector2;
static const Vector2 Vector2Zero = Vector2(0.0f, 0.0f);
static const Vector2 Vector2One = Vector2(1.0f, 1.0f);
static const Vector2 Vector2Up = Vector2(0.0f, 1.0f);
static const Vector2 Vector2Down = Vector2(0.0f, -1.0f);
static const Vector2 Vector2Left = Vector2(-1.0f, 0.0f);
static const Vector2 Vector2Right = Vector2(1.0f, 0.0f);
typedef D3DLIGHT9 Light;
typedef D3DMATERIAL9 D3DMaterial;
}
}
#endif