looking very nice Bubba. When can we expect a playable demo? even if its just a flight sim of sorts...
This is a discussion on New screenshots from engine within the Game Programming forums, part of the General Programming Boards category; looking very nice Bubba. When can we expect a playable demo? even if its just a flight sim of sorts......
looking very nice Bubba. When can we expect a playable demo? even if its just a flight sim of sorts...
The system I'm running on is fairly dated. It's just an AMD 1.333 GHz with 64 MB GeForce 3 and 896 MB RAM with an Audigy 2 sound card.
Right now this is brute force. The hardware is clipping/culling the frustrum which is not the best idea in the world. I really want to implement my own frustrum culling except I'm not quite sure how to get the clip matrix from D3D. Once I figure that out I just test
-x<w<x
-y<w<y
-z<w<z
To create my render list. I have optimized the inner loop so that it renders all alpha blended objects at one time. Even if I have well over 10000 alpha blended objects it still only requires 2 state changes per frame which is very nice.
The planets are not progressive meshes and I'm kinda deciding whether to use them or not. It is a good possibility that progressive meshes may actually take longer to decimate than simply using set LOD's. Progressive LOD's may not work well.
Also as my system is old it really doesn't matter to me if I tax it because my system is not a good representation of my target platform. I also cannot use any pixel shaders over version 2.0 or vertex shaders over version 2.0. My card does not support them. So just because it lags on my system does not mean it will lag on another.
Very very soon I'm going to put all of this stuff in effects files so that I can check the device caps and adjust my display quality based on the rig it's running on.
Need help on these problems
But I'm having some problems with Window's messages. It seems that every time I move the cursor in the upper left hand corner the stupid mouse cursor appears, as well as when I move it in the upper right. I've trapped the WM_SYSCOMMAND message and trapped cracked it into lParam and wParam but it still allows you to select the system menu. I've looked at the Direct3D framework that MS wrote and it isn't doing anything I'm not doing. It's really 'bugging' me.
Firing lasers so they move through the target
Now I have this figured out except that the lasers don't look as though they move through the target until they are way off in the distance. In essence I need to adjust the convergence of the lasers so that they converge at a spot just in front or some distance in front of the ship. Should I alter the direction vector components individually by the up and right vectors of the camera or should I just wait until these are actually being fired by a gun in 3D space?
Sound clipping
It seems that DirectMusic doesn't like playing a lot of sound effects through one channel. It tends to clip them rather quickly. This is probably due to them using some crappy additive mixing scheme in the primary buffer. I.E.:
I would imagine its something like this since I do have some experience in writing sound engines.
This is of course for unsigned short sample buffers, but you get the idea. I shudder to think about writing my own mixer but if I keep getting this clipping I just might.Code:WORD finalsamplevalue=0; std::vector<Buffer>::iterator ptr; for (ptr=Buffers.begin();ptr!=Buffers.end();ptr++) { WORD samplevalue=(ptr->SoundData[ptr->PlayCursor]*ptr->VolumeCoef); finalsamplevalue++; } finalsamplevalue/=numsamples; //clamp final mix if (finalsamplevalue<0) finalsamplevalue=0; if (finalsamplevalue>65535) finalsamplevalue=65535; ....write final sample value to buffer
That's where I'll probably move to pure assembly and use MMX so I can be fast...even though it won't be as fast as the hardware.
Rotating objects to match their velocity vector
Now I know how to compute a velocity vector from one point in space to another, but I'm not sure how to actually rotate the object to match the given vector orientation. Just simply using the normalized vector components for rotation does not work. The normalized vector will always fall in the range 0 to 1.0f, but the D3DXRotation functions expect a value from -PI to PI.
Things I've tried:
1. Compute dot product between velocity vector and current lookAt vector for object. Use dot product as angle argument for D3DXRotationAxis along the Velocity Vector.
But this does not work. This assumes that we are already on the velocity vector axis and so it does not work. If I use the base vector as the vector it still does not work properly.Code:D3DXVECTOR3 Base(0.0f,0.0f,1.0f); //pointing down positive Z //Find angle between vectors float dot=D3DXVec3Dot(&Base,&VelocityVector); //Rotate on velocity vector by specified angle D3DXMATRIX Final; D3DXMatrixRotationAxis(&Final,&VelocityVector,dot);
I'm sorta lost.
2. Compute the picking ray that goes through mouse point mx,my. Compute atan2(y,z), atan2(x,z) and atan2(x,y). Rotate object by those amounts on x,y, and z. This produces some very ugly gimbal lock situations and is quite slow because of the atan2.
Here is the code I have so far:
That's the relevant code for my laser creation and rendering. Please help me.Code:#include "CLaser.h" #include "math.h" const DWORD LaserVertex::FVF=D3DFVF_XYZ | D3DFVF_TEX1; void CActiveLaserContainer::Create(IDirect3DDevice9 *_Device,std::string _File) { Device=_Device; //Properties.Position=D3DXVECTOR3(0.0f,0.0f,0.0f); LaserVertex *verts; Device->CreateVertexBuffer(4*sizeof(LaserVertex), D3DUSAGE_WRITEONLY, LaserVertex::FVF, D3DPOOL_MANAGED, &VB, 0); VB->Lock(0,0,(void **)&verts,0); verts[0]=LaserVertex(D3DXVECTOR3(-.3f, 0.0f, 5.0f), 0.0f, 0.0f); verts[1]=LaserVertex(D3DXVECTOR3(.3f, 0.0f, 5.0f), 1.0f, 0.0f); verts[2]=LaserVertex(D3DXVECTOR3(-.3f, 0.0f, 0.0f), 0.0f, 1.0f); verts[3]=LaserVertex(D3DXVECTOR3(.3f, 0.0f, 0.0f), 1.0f, 1.0f); VB->Unlock(); D3DXCreateTextureFromFile(Device,_File.c_str(),&Texture); } void CLaser::Create(IDirect3DDevice9 *_Device, LaserProps _Props, D3DXMATRIX _view, D3DXVECTOR3 _lookAt, unsigned long _mx, unsigned long _my) { Properties=_Props; //Compute picking ray float px=0.0f; float py=0.0f; D3DVIEWPORT9 vp; _Device->GetViewport(&vp); D3DXMATRIX proj; _Device->GetTransform(D3DTS_PROJECTION,&proj); px=((( 2.0f*_mx)/ vp.Width ) - 1.0f)/ (proj(0,0)); py=(((-2.0f*_my)/ vp.Height) + 1.0f)/ (proj(1,1)); D3DXVECTOR3 Direction(px,py,1.0f); //Compute Velocity Vector D3DXMATRIX ViewInverse; D3DXMatrixInverse(&ViewInverse,0,&_view); D3DXVec3TransformNormal(&Direction,&Direction,&ViewInverse); D3DXVec3Normalize(&Direction,&Direction); Properties.VelocityVector=Direction; //Setup base translation matrix D3DXMATRIX Trans; D3DXMatrixTranslation(&Trans, Properties.GunPos.x, Properties.GunPos.y, Properties.GunPos.z); //Setup laser-to-target translation matrices D3DXMATRIX Trans2; D3DXMatrixTranslation(&Trans2,Direction.x,Direction.y,1.0f); //Rotate lasers toward's target D3DXMATRIX Rot; D3DXMatrixRotationYawPitchRoll(&Rot,px,-py,1.0f); //Store our world matrix so we don't compute later Properties.World=Rot*Trans*Trans2*ViewInverse; } void CActiveLaserContainer::Render(float timeDelta,D3DXMATRIX view,CLaser *Laser) { D3DXMATRIX world=Laser->Properties.World; //Fast translation - no multiply world._41=Laser->Properties.Position.x; world._42=Laser->Properties.Position.y; world._43=Laser->Properties.Position.z; //Transform object Device->SetTransform(D3DTS_WORLD,&world); //Render object Device->SetStreamSource(0,VB,0,sizeof(LaserVertex)); Device->SetFVF(LaserVertex::FVF); Device->SetTexture(0,Texture); Device->DrawPrimitive(D3DPT_TRIANGLESTRIP,0,2); }
Here are the headers:
Notice that I've left some code in CLaser that doesn't do anything. I used to update the lasers in the local class but then decided it was faster to update it from the container class. In fact I'm learning that structure is very very important to how fast the thing will render. Making something private just to be C++-like is a sure way to destroy your framerates. Every time you call a function you create function call overhead. Do that about 10000 times a frame and you crawl.Code:#ifndef CLASER #define CLASER #include "d3dx9.h" #include "CQuickCom.h" #include <vector> //Current vertex type struct LaserVertex { D3DXVECTOR3 Position; float u,v; LaserVertex(D3DXVECTOR3 &_pos,float _u,float _v):Position(_pos),u(_u),v(_v) {} static const DWORD FVF; }; //Structure for a ray if needed struct CRay { D3DXVECTOR3 Origin; D3DXVECTOR3 Direction; }; //Laser properties structure - still a work in progress struct LaserProps { //Position, speed, picking ray, and world matrix for this object D3DXMATRIX World; CRay PickingRay; float Speed; D3DXVECTOR3 Position; //Convergence factor - not working D3DXVECTOR3 ConvergenceVector; //Current gun position and rotational matrix D3DXVECTOR3 GunPos; D3DXMATRIX *RotationMatrix; D3DXVECTOR3 Rotation; D3DXVECTOR3 VelocityVector; //Attributes float FireRate; float RechargeRate; float EnergyDrain; float DamageAmount; unsigned int DamageType; float LifeTimer; float LifeDistance; //Textures - not used yet IDirect3DTexture9 *Texture; IDirect3DTexture9 *AlphaTexture; //Sounds WCHAR *SoundFile; }; class CLaser { protected: friend class CActiveLaserContainer; LaserProps Properties; CLaser(void) {} public: LaserProps GetProps(void) {return Properties;}; void Create(IDirect3DDevice9 *_Device, LaserProps _Props, D3DXMATRIX _view, D3DXVECTOR3 _lookAt, unsigned long _mx, unsigned long _my); //Update ourself void Update(float timeDelta) { Properties.Position+=((Properties.VelocityVector*Properties.Speed)*timeDelta); } }; class CActiveLaserContainer { protected: std::vector<CLaser> Lasers; //Shared resources IDirect3DTexture9 *Texture; IDirect3DDevice9 *Device; IDirect3DVertexBuffer9 *VB; public: CActiveLaserContainer(void):Texture(NULL),Device(NULL),VB(NULL) {} virtual ~CActiveLaserContainer(void) { Lasers.clear(); SAFE_RELEASE(Texture); SAFE_RELEASE(VB); } void Create(IDirect3DDevice9 *_Device,std::string _File); //Add a laser to the mix unsigned int AddLaser(LaserProps _NewLaser, D3DXMATRIX _view, D3DXVECTOR3 _lookAt, unsigned long _mx, unsigned long _my) { CLaser temp; temp.Create(Device,_NewLaser,_view,_lookAt,_mx,_my); Lasers.push_back(temp); return Lasers.size()-1; } void Render(float timeDelta,D3DXMATRIX _view,CLaser *Laser); void RemoveLaser(unsigned int _ID); bool GetProps(unsigned int lasernum,LaserProps *outProps) { if (Lasers.empty()) return false; std::vector<CLaser>::iterator laser=Lasers.begin(); int count=0; while (count!=lasernum) { laser++; count++; } outProps=&(laser->Properties); return true; } //Update all lasers void Update(D3DXVECTOR3 &_ObjectVector,D3DXMATRIX view,float timeDelta) { std::vector<CLaser>::iterator laser; for (laser=Lasers.begin();laser!=Lasers.end();laser++) { //Check life-span if (laser->Properties.LifeTimer>laser->Properties.LifeDistance) { if (laser!=Lasers.end()-1) { //We are dying laser=Lasers.erase(laser); } } //Make sure we are not at end of list - big time crash if we are if (laser!=(Lasers.end())) { laser->Properties.LifeTimer+=timeDelta; //Update laser -> faster than calling laser->Update() laser->Properties.Position+= (laser->Properties.VelocityVector*laser->Properties.Speed)*timeDelta; //Draw the laser Render(timeDelta,view,laser); } } } }; #endif
Sorry so long but you can't say I didn't post enough code for you to help me. I tried on my own first I'm thinking.
![]()
Last edited by VirtualAce; 11-22-2004 at 01:49 PM.
See what the board did to my first sections of code??? Thats what we are talking about. Anytime you edit your post it kills the spaces and moves everything to the left. Notice my second code block does not suffer from this. That's because I hit edit post and posted the header later - thus it moved all my code block(s) from the initial post to the left margin and yet preserved the later code block(s).
Quite an annoying board bug.
I can help with the rotation problem you are experiencing. I have implemented the code so that enemies in a 3D world will rotate towards you and face you. Do you want me to explain my method, or do you want me to try to find a possible error in your code and edit it? I am very willing to help, if you want me to.
Either way is fine with me. I understand the concepts and can draw it out, but I'm obviously missing something. This is the laser code so it prob wont help to point out anything here.
Just explain it to me if you could please.
Firstly, does D3DXVec3Dot really return the angle between vectors, or just the dotproduct? If it just takes the dotproduct, and not the angle, then does D3DMatrixRotationAxis know how to compute the correct rotation axis when you give it the two vectors and the dotproduct between the two? If not, you need to take the inverse cosine of the dotproduct in order to get an angle. If this is stuff you already know, I'm sorry, I'm just trying to see if there's something 'easy' that might've been missed.D3DXVECTOR3 Base(0.0f,0.0f,1.0f); //pointing down positive Z
//Find angle between vectors
float dot=D3DXVec3Dot(&Base,&VelocityVector);
//Rotate on velocity vector by specified angle
D3DXMATRIX Final;
D3DXMatrixRotationAxis(&Final,&VelocityVector,dot) ;
In my next post i'm going to describe what works for me in my method.
This is my code just for computing the angle yaw. It's similar for pitch, and I don't know how to do roll. This works perfectly.
Code:Vector3Double PlayerPos = Engine->GetPlayerPos(); Vector3Double ToPlayer = PlayerPos - this->mPosition; ToPlayer.y = 0; //I am doing this because I am doing a polar coordinate calculation on the y = 0 plane, this calculates the rotation angle on the y axis ToPlayer.Normalize(); this->mYaw = acosf(-ToPlayer.z); //This is the same as taking the dotproduct between the ToPlayer vector and the 'base vector'. //I am in OpenGL, so the base vector is (0,0,-1), else it's (0,0,1) //This step is crucial because I only know the angle between the two vectors, but I don't know if it is a positive or negative angle! if(PlayerPos.x > this->mPosition.x) this->mYaw *= -1;
Last edited by Darkness; 11-22-2004 at 02:34 PM.
Well thats sort of what I figured it would be. However I'm not calculating the arccos of the dot product. I would like to be able to do it w/o making that computation. However your basis vector is exactly what I've been doing.
All my objects have a base vector of 0,0,1. That is they are all in model space pointing down the positive (in Direct3D away from the camera) z axis. So it makes a lot of sense that you compute the dot product between the base vector and the vector you need to rotate to. So I wasn't too far off. Thanks a bunch and I will try it. I think for Z rotation you need to setup so that Z will always rotate the object or roll the object. This is done by using your 3 basis vectors. Roll really doesn't matter in most cases and especially in my game. As long as the object heads towards you is all that matters.
If all of the basis vectors are correct and you are using the inverse view matrix then roll is simply a matter of saying roll this way or that way. To roll upright you would simply roll until your vector was 0,0,1 or what you started with.
Also to answer your second question.....each laser in that picture represents 2 tri's. Each side of the skybox represent's two tri's and the mouse cursor object represent's 2 tri's. The planet's each have 32 facets north/south and east/west or 32*32*2 tri's in them (2048 tri's per planet). In this render there are 2 planets in system. So here is the triangle breakdown by object:
Triangles per object:
Skybox: 12 (6 faces *2 tri's per face)
Mouse cursor: 2 (triangulated quad)
Lasers: 2 (triangulated quad)
Planets: 2048
I cannot tell exactly how many lasers there are because there are more off screen as well. I would say that there are about 500 or more lasers or about 1000 tri's.
So in all there are only about 2048+12+2+1000 tri's (3062 triangles).
But note that there are NOT 1000 textures, sounds, or vertex buffers in memory. Each laser share's the container's vertex buffer, sound, and texture. I coded it this way to be efficient and it seems to have worked. When you create a container you must specify the texture you want and you must specify the model (or manually create one in the create() function of the container class) as well. This works quite nice and makes a lot more sense as well. The class also DOES NOT change any render states whatsoever. The engine does that.
EDIT:
Ok I underestimated somewhat. Here is a screenie with an exact count of lasers.
Last edited by VirtualAce; 11-23-2004 at 12:56 AM.
Another test: Bad frames but lots of crapola on the screen.
I wish i could program like he can... im stuck in stupid 2D programming right now....
The Matrix Will Live Again!
It's nothing spectacular. Look on some game sites. They blow my screenies out of the water. I need more people...namely 3D modelers and artists.
Don't say 'stuck' and dont say 'stupid 2D programming'.
You are never 'stuck' and there is nothing stupid about programming.
(Unless it's COBOL, but that is another story)
[edit]
Oh and a lot of us wish we could program as well as Bubba could
[/edit]
Just outa curiosity, and im sure i am the odd one for asking this out of all the masterful coding being displayed lol, but where are you hosting those pics?
01110111011000010110110001100100011011110010000001 11000101110101011010010111010000100000011011000110 10010110011001100101001000000111100101101111011101 0100100000011011100111010101100010
They are attached to the board