![]() |
| | #1 |
| mustang benny Join Date: Jul 2002
Posts: 1,401
| Lighting a Direct3D 9 mesh sphere Code: mSphere=Mesh.Sphere(device,1.0f,32,16); mSphere.ComputeNormals(); SphereCol=new Material(); SphereCol.Ambient=Color.DarkRed; SphereCol.Diffuse=Color.Red; SphereCol.Specular=Color.White; . . . device.Lights[0].Type=LightType.Directional; device.Lights[0].Specular=Color.White; device.Lights[0].Diffuse=Color.White; device.Lights[0].Position=new Vector3(0.0f,0.0f, -4.0f); device.Lights[0].Direction=new Vector3(0.0f,0.0f, 1.0f); device.Lights[0].Enabled=true; device.Material=SphereCol; mSphere.DrawSubset(0);
__________________ benforbes@optusnet.com.au Microsoft Visual Studio .NET 2003 Enterprise Architect Windows XP Pro Code Tags Programming FAQ Tutorials |
| bennyandthejets is offline | |
| | #2 |
| Super Moderator Join Date: Aug 2001
Posts: 7,472
| Yes I have. Are you normalizing the normals? |
| Bubba is offline | |
| | #3 |
| Super Moderator Join Date: Aug 2001
Posts: 7,472
| And another shot. |
| Bubba is offline | |
| | #4 |
| Super Moderator Join Date: Aug 2001
Posts: 7,472
| And this one shows it well. |
| Bubba is offline | |
| | #5 |
| Super Moderator Join Date: Aug 2001
Posts: 7,472
| Here is the code I'm using. CPlanet uses a CSphere object. I separated them for rendering reasons and I'll spare you the details. CSphere.cpp Code: #define CSPHERE
#include "d3dx9.h"
#include "CQuickCom.h"
#include "CFileLog.h"
#include "d3dx9mesh.h"
//Converts degrees to radians
#define DEGTORAD(x) (x*D3DX_PI/180.0f)
struct CSphereVertex
{
D3DXVECTOR3 pos;
D3DXVECTOR3 normal;
float u,v;
static const DWORD FVF;
CSphereVertex(D3DXVECTOR3 tpos,D3DXVECTOR3 tnormal,float tu,float tv):
pos(tpos),normal(tnormal),u(tu),v(tv){}
};
class CSphere
{
protected:
CFileLog SphereLog;
IDirect3DDevice9 *Device;
ID3DXMesh *SphereMesh;
unsigned int NumTris;
unsigned int NumFaces;
unsigned int NumVertices;
unsigned int NumVertsPerRow;
unsigned int NumVertsPerCol;
float Radius;
public:
CSphere(void) {Device=NULL,NumTris=0,NumFaces=0,
NumVertices=0,NumVertsPerRow=0,NumVertsPerCol=0,Radius=0.0f;};
~CSphere(void)
{
if (SphereMesh) SphereMesh->Release();
}
//Old deprecated function
//void CreateSphere(IDirect3DDevice9 *_device,
// float _radius,
// unsigned int _faces,
// float _texmag,
// D3DXVECTOR3 &pos);
void CreateMeshSphere(IDirect3DDevice9 *_device,
float _radius,
unsigned int _faces);
ID3DXMesh *GetMesh(void) {return SphereMesh;};
unsigned int GetNumTris(void) {return NumTris;};
unsigned int GetNumVertices(void) {return NumVertices;};
};
#endif
Code: #include "CSphere.h"
const DWORD CSphereVertex::FVF=D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1;
//Create mesh
void CSphere::CreateMeshSphere(IDirect3DDevice9 *_device,float _radius,unsigned int _faces)
{
//Class vars
Device=_device;
Radius=_radius;
NumFaces=_faces;
//Create temp mesh
LPD3DXMESH temp;
if (FAILED(D3DXCreateSphere(Device,Radius,NumFaces,NumFaces,&temp,NULL)))
{
::MessageBox(0,"Failed to create sphere",0,0);
}
//Clone mesh with new FVF
if (FAILED(temp->CloneMeshFVF(D3DXMESH_SYSTEMMEM,CSphereVertex::FVF,Device,&SphereMesh)))
{
::MessageBox(0,"Failed to clone mesh",0,0);
}
//Lock vertex buffer
CSphereVertex *Vertices;
SphereMesh->LockVertexBuffer(0,(void **)&Vertices);
//Setup mapping vars
float angleinc_alpha=360.0f/_faces;
float angleinc_beta=180.0f/_faces;
float alpha=0.0f;
float beta=-180.0f;
float u=0.0f,v=0.0f;
unsigned int vertex_count;
//Set 2*PI - no mul in for loop
float PI2=D3DX_PI*2.0f;
//Map U,V coords
//Produces very good results for 2:1 texture ratios
for (unsigned int i=0;i<SphereMesh->GetNumVertices();i++)
{
u=(DEGTORAD(alpha)+D3DX_PI)/(PI2);
v=DEGTORAD(beta)/D3DX_PI;
Vertices[i].u=u;
Vertices[i].v=v;
alpha+=angleinc_alpha;
vertex_count++;
if (vertex_count>=(_faces))
{
alpha=0.0f;
beta+=angleinc_beta;
//Disabled test area
//Vertices[i+1].v=0.0f;
//Vertices[i+1].u=0.0f;
vertex_count=0;
}
}
//Unlock vertex buffer
SphereMesh->UnlockVertexBuffer();
//Discard temp mesh
temp->Release();
}
Code: #include "CPlanet.h"
//Constructor - self explanatory
CPlanet::CPlanet(void)
{
Device=NULL;
Pos=D3DXVECTOR3(0.0f,0.0f,0.0f);
Rotation=D3DXVECTOR3(0.0f,0.0f,0.0f);
RotationVelocity=D3DXVECTOR3(0.0f,0.0f,0.0f);
Texture=NULL;
BumpMap=NULL;
Radius=0.0f;
}
//Destructor - release COM objects - decrement their reference counts
CPlanet::~CPlanet(void)
{
if (Texture) Texture->Release();
if (BumpMap) BumpMap->Release();
}
//Set planet texture
void CPlanet::SetTexture(std::string PlanetFile)
{
if (FAILED(D3DXCreateTextureFromFile(Device,PlanetFile.c_str(),&Texture)))
{
::MessageBox(0,"Failed to load planet texture",0,0);
return;
}
}
//Set bump map -> fake bump mapping not per-pixel
void CPlanet::SetBumpMap(std::string PlanetFile)
{
if (FAILED(D3DXCreateTextureFromFile(Device,PlanetFile.c_str(),&BumpMap)))
{
::MessageBox(0,"Failed to load planet texture",0,0);
return;
}
}
//Create the model -> call CSphere::CreateMeshSphere()
void CPlanet::CreateModel(IDirect3DDevice9 *_Device,float _Radius,int _Faces,D3DXVECTOR3 &pos)
{
Device=_Device;
Radius=_Radius;
Faces=_Faces;
SetPosition(&pos);
Planet.CreateMeshSphere(Device,Radius,_Faces);
}
//Disabled - unsure of atmospheres at this time
void CPlanet::SetAtmosphere(D3DMATERIAL9 *_material,float _radius)
{
//AMaterial=*_material;
//ARadius=_radius;
//AtmosphereFlag=true;
//Atmosphere.CreateMeshSphere(Device,ARadius,Faces);
}
//Render object
void CPlanet::Render(float timeDelta,D3DXVECTOR3 cameraPos)
{
//Set U,V wrapping to true - must do this to get rid of render artifacts
Device->SetRenderState(D3DRS_WRAP0,true);
Device->SetRenderState(D3DRS_WRAP1,true);
//Change model rotation based on velocity presets and time from last frame
Rotation.x+=(RotationVelocity.x*timeDelta);
Rotation.y+=(RotationVelocity.y*timeDelta);
Rotation.z+=(RotationVelocity.z*timeDelta);
//Setup world rotation matrix
D3DXMATRIX rot;
D3DXMatrixRotationYawPitchRoll(&rot,Rotation.x,Rotation.y,Rotation.z);
//Setup translation -> no mul here
rot._41=Pos.x;
rot._42=Pos.y;
rot._43=Pos.z;
//Set transform
Device->SetTransform(D3DTS_WORLD,&rot);
//Set material
D3DXVECTOR3 distvect;
D3DXVec3Subtract(&distvect,&Pos,&cameraPos);
float length=D3DXVec3Length(&distvect);
float actualdist=10000.0f-(length-8000.0f);
if (actualdist>0.0f)
{
AlphaValue=actualdist/10000.0f;
} else AlphaValue=0.0f;
if (AlphaValue>=1.0f) AlphaValue=1.0f;
if (AlphaValue<=0.0f) AlphaValue=0.0f;
Material.Diffuse.a=AlphaValue;
Device->SetMaterial(&Material);
//Set texture
//Device->SetTextureStageState(0,D3DTSS_ALPHAARG1,D3DTA_DIFFUSE);
//Device->SetTextureStageState(0,D3DTSS_ALPHAOP,D3DTOP_SELECTARG1);
Device->SetTexture(0,Texture);
//Check pointer -> prob disabled on release build
if (!Planet.GetMesh())
{
::MessageBox(0,0,"Null pointer in mesh",0);
}
//Render object
if (FAILED(Planet.GetMesh()->DrawSubset(0)))
{
::MessageBox(0,0,"Cannot draw mesh",0);
}
//Restore render states
Device->SetRenderState(D3DRS_WRAP0,false);
Device->SetRenderState(D3DRS_WRAP1,false);
//Device->SetTextureStageState(1,D3DTSS_COLOROP,D3DTOP_DISABLE);
//Device->SetTextureStageState(0,D3DTSS_ALPHAOP,D3DTOP_MODULATE);
}
Code:
#ifndef CPLANET
#define CPLANET
#include "CPrimitives.h"
#include "d3dx9.h"
#include <String>
#include "CQuickCom.h"
#include "CSphere.h"
class CPlanet
{
//Device interface pointer
IDirect3DDevice9 *Device;
//Sphere object
CSphere Planet;
//Model properties
D3DXVECTOR3 Pos;
D3DXVECTOR3 Rotation;
D3DXVECTOR3 RotationVelocity;
//Textures
IDirect3DTexture9 *Texture;
IDirect3DTexture9 *BumpMap;
//Materials
D3DMATERIAL9 Material;
D3DMATERIAL9 AMaterial;
float Radius;
float ARadius;
int Faces;
bool AtmosphereFlag;
public:
float AlphaValue;
CPlanet(void);
~CPlanet(void);
void SetTexture(std::string PlanetFile);
void SetBumpMap(std::string PlanetFile);
void SetPosition(D3DXVECTOR3 *_newpos) {Pos=*_newpos;};
void GetPosition(D3DXVECTOR3 *_curpos) {*_curpos=Pos;};
void SetRotationParams(D3DXVECTOR3 *_rotation,D3DXVECTOR3 *_rotation_velocity)
{
Rotation=*_rotation;
RotationVelocity=*_rotation_velocity;
}
void GetRotationParams(D3DXVECTOR3 *_rotation,D3DXVECTOR3 *_rotation_velocity)
{
*_rotation=Rotation;
*_rotation_velocity=RotationVelocity;
}
void CreateModel(IDirect3DDevice9 *_Device,float _Radius,int _Faces,D3DXVECTOR3 &pos);
void TestCreateModel(IDirect3DDevice9 *_device,float _radius,unsigned int _faces)
{
Device=_device;
Radius=_radius;
Faces=_faces;
Planet.CreateMeshSphere(_device,_radius,_faces);
D3DXComputeNormals(Planet.GetMesh(),NULL);
}
void SetMaterial(D3DMATERIAL9 *_material) {Material=*_material;};
void GetMaterial(D3DMATERIAL9 *_material) {*_material=Material;};
float GetRadius(void) {return Radius;};
float GetAtmosphereRadius(void) {return ARadius;};
void SetAtmosphere(D3DMATERIAL9 *_material,float _radius);
void Render(float timeDelta,D3DXVECTOR3 cameraPos);
void TestRender(float timeDelta);
};
#endif
Not the fastest way to do things and I'm reworking the code to use a much better rendering system, but you get the idea. This is the most important section: Code: void TestCreateModel(IDirect3DDevice9 *_device,float _radius,unsigned int _faces)
{
Device=_device;
Radius=_radius;
Faces=_faces;
Planet.CreateMeshSphere(_device,_radius,_faces);
D3DXComputeNormals(Planet.GetMesh(),NULL);
}
Code: D3DXVECTOR v1=Vertex[vnum+1]-Vertex[vnum]; D3DXVECTOR v2=Vertex[vnum+2]-Vertex[vnum+1]; D3DXVECTOR Cross; D3DXVec3Cross(&Cross,&v1,&v2); D3DXVec3Normalize(&Cross,&Cross); //No normal averaging Vertex[vnum].normal=Cross; Vertex[vnum+1].normal=Cross; Vertex[vnum+2].normal=Cross; There is an easier way to compute the normals on a sphere. Since all points are equidistant from the center the normal will always be the normalized distance between the vertex on the sphere and the center of the sphere. Since your sphere's are centered around 0,0,0 in model space you can simply normalize the Vertex to get the normal. You are essentially then clamping the vertex to the surface of a unit sphere. Code: D3DXVECTOR3 vNormal; D3DXVec3Normalize(&vNormal,Vertex[vnum]); Vertex[vnum].normal=vNormal; Code: mSphere=Mesh.Sphere(device,1.0f,32,16); mSphere.ComputeNormals(); Last edited by Bubba; 02-07-2005 at 09:50 PM. |
| Bubba is offline | |
| | #6 |
| mustang benny Join Date: Jul 2002
Posts: 1,401
| Thanks heaps for the code, I haven't found anything nearly as good on the net. Unfortunately it's a bit above my level so it will take some time to work out. As for the scope and resource leak issues, remember I'm using C#, everything should technically be managed for me. I think I will however go back to using C++. The only reason I was using C# was to learn a .NET language, but I do sorely miss the satisfaction of good C++ code. Once I've finished I'll let you know.
__________________ benforbes@optusnet.com.au Microsoft Visual Studio .NET 2003 Enterprise Architect Windows XP Pro Code Tags Programming FAQ Tutorials |
| bennyandthejets is offline | |
| | #7 |
| Confused Join Date: Sep 2001 Location: Sweden
Posts: 3,122
| From the screenies it looks like the camera is rotating, but the light source is still in the same spot which should give the effect shown in those screenies. You sure this is not the case?
__________________ MagosX.com Give a man a fish and you feed him for a day. Teach a man to fish and you feed him for a lifetime. |
| Magos is offline | |
| | #8 |
| mustang benny Join Date: Jul 2002
Posts: 1,401
| The light is fixed and the camera is moving around in a circle. Maybe the pictures don't illustrate the problem, but believe me if you ran the program you would see what I mean. I can post the binary if you trust me not to infect you.
__________________ benforbes@optusnet.com.au Microsoft Visual Studio .NET 2003 Enterprise Architect Windows XP Pro Code Tags Programming FAQ Tutorials |
| bennyandthejets is offline | |
| | #9 |
| Confused Join Date: Sep 2001 Location: Sweden
Posts: 3,122
| How 'bout posting both the binary and the source and someone could give a more accurate solution.
__________________ MagosX.com Give a man a fish and you feed him for a day. Teach a man to fish and you feed him for a lifetime. |
| Magos is offline | |
| | #10 |
| Super Moderator Join Date: Aug 2001
Posts: 7,472
| First people want the source, not the binary. Now they want the binary not just the source. Sheesh. Sorry cannot post the binary. It's way over the board limit. |
| Bubba is offline | |
| | #11 |
| Super Moderator Join Date: Aug 2001
Posts: 7,472
| I see that binary message was for him not me. Sorry. Anyways if your camera is moving around the object and the object is part of your world then it is really the object that is moving, not the camera. Your calculations must be in world space not view space. It seems to me that they are in view space. The camera is moving in space and rotating but to show this you really must rotate the world and move the world, not the camera. You always translate the camera back to 0,0,0 or the origin of the world since the camera is assumed to always be the origin of your world. Everything else is relative to the camera. |
| Bubba is offline | |
| | #12 |
| mustang benny Join Date: Jul 2002
Posts: 1,401
| I think my code does what your saying but I'm not sure. Here it is: Code: CamLookAt.X=(float)Math.Sin((double)angle)+CamPos.X;
CamLookAt.Z=(float)Math.Cos((double)angle)+CamPos.Z;
device.Transform.World=Matrix.Identity;
device.Transform.View=Matrix.LookAtLH(CamPos, CamLookAt, new Vector3(0.0f,1.0f,0.0f) );
device.Transform.Projection=Matrix.PerspectiveFovLH((float)Math.PI/4.0f,1.0f,1.0f,100f);
__________________ benforbes@optusnet.com.au Microsoft Visual Studio .NET 2003 Enterprise Architect Windows XP Pro Code Tags Programming FAQ Tutorials Last edited by bennyandthejets; 02-13-2005 at 05:30 PM. |
| bennyandthejets is offline | |
| | #13 |
| Super Moderator Join Date: Aug 2001
Posts: 7,472
| Set your camera to always look at the same spot. This will compute the correct view matrix for a camera with 3 basis vectors..right, look, and up. Code: void Camera::getViewMatrix(D3DXMATRIX* V)
{
// Keep camera's axes orthogonal to eachother
D3DXVec3Normalize(&_look, &_look);
D3DXVec3Cross(&_up, &_look, &_right);
D3DXVec3Normalize(&_up, &_up);
D3DXVec3Cross(&_right, &_up, &_look);
D3DXVec3Normalize(&_right, &_right);
// Build the view matrix:
float x = -D3DXVec3Dot(&_right, &_pos);
float y = -D3DXVec3Dot(&_up, &_pos);
float z = -D3DXVec3Dot(&_look, &_pos);
(*V)(0,0) = _right.x; (*V)(0, 1) = _up.x; (*V)(0, 2) = _look.x; (*V)(0, 3) = 0.0f;
(*V)(1,0) = _right.y; (*V)(1, 1) = _up.y; (*V)(1, 2) = _look.y; (*V)(1, 3) = 0.0f;
(*V)(2,0) = _right.z; (*V)(2, 1) = _up.z; (*V)(2, 2) = _look.z; (*V)(2, 3) = 0.0f;
(*V)(3,0) = x; (*V)(3, 1) = y; (*V)(3, 2) = z; (*V)(3, 3) = 1.0f;
}
If you are just wanting a stationary camera then set it to look at the same spot at all times. I would have to see what is taking place in order to help you more. |
| Bubba is offline | |
![]() |
| Thread Tools | |
| Display Modes | |
|
Similar Threads | ||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Direct3D Alpha Blend with Lighting ? | rocketman03 | Game Programming | 10 | 07-07-2009 04:04 PM |
| Lighting in Managed Direct3d | Rune Hunter | Game Programming | 0 | 04-30-2006 07:40 AM |
| Mesh Rendering: Z-Buffer and Lighting | Epo | Game Programming | 6 | 04-20-2005 07:11 AM |
| Sphere code not working | Bubba | Game Programming | 2 | 10-03-2004 07:29 AM |
| need help with opengl lighting!! | genghis37 | Game Programming | 1 | 06-22-2002 12:28 AM |