Someone asked if it was possible to use point lists with the engine in it's current starte. And the answer is yes.
This bit of code creates randomly colored points in 3D space, and a planet to give it a bit of a flair.
//An example using a point list to draw a starfield.
//Arrow keys to move camera.
//PgUp/PgDn to pan up and down.
//Z and X to rotate on Z axis.
declare import,timeGetTime(),int;
//Our FVF structure for points
struct point_vertex{
VECTOR3 pos;
DWORD color; // The vertex colour.
};
#define point_fvf D3DFVF_XYZ|D3DFVF_DIFFUSE
#define num_points 5000
global sub main()
{
C3DScreen s;
C3DCamera c;
C3DMesh m;
C3DMesh planet;
C3DObject scene;
C3DLight light;
CDirectInput di;
float fadjust,fTarget;
//target 60FPS for camera movement
fTarget = 1.0f / /*FPS*/60.0f * 1000.0f;
fAdjust = 1.0f;
s.CreateWindowed(0,0,640,480,AWS_CAPTION|AWS_VISIBLE|AWS_SIZE|AWS_CENTERED,0,"3D Points - ESC exits",NULL,false);
di.Init(s);
c.Create(s);
c.Position(0,0,-50);
c.Orient(0,0,1,0,1,0);
c.SetBackPlane(1000);
s.Clear(RGBA(0,0,0,255));
s.BeginScene(c);
s.RenderText(0,10,"Loading objects...",RGBA(255,255,0,255));
s.RenderScene();
//create a point mesh with 'num_points' points.
m.CreateMeshEx(s,D3DPT_POINTLIST,num_points,num_points,num_points,point_fvf);
//Lock the vertex and index buffers so we can write to them.
point_vertex *v = m.LockVertexBuffer();
word *idx = m.LockIndexBuffer();
for(int x=0;x < num_points;x++)
{
*idx = x;
v->pos.x = rnd(-100,100);
v->pos.y = rnd(-100,100);
v->pos.z = rnd(-100,100);
v->color = RGBA(rnd(100,255),rnd(100,255),rnd(100,255),255);
v+=len(point_vertex);
idx+=len(word);
}
m.UnlockVertexBuffer();
m.UnlockIndexBuffer();
m.EnableLighting(false);
m.UseVertexColor(true);
m.SetVisible(true);
planet.CreateSphere(s,25,5.0,false);
planet.LoadTexture(0,GetStartPath()+"media\\tile3.tga",0);
light.Create(s,LIGHT_POINT,1);
light.Position(-80,20,-150);
light.SetAttenuation(0,1/200.0,0);
light.SetSpecular(.5,.5,.5,1);
light.SetAmbient(.4,.4,.4,1);
scene.CreateScene(s);
scene.AddChild(light);
scene.AddChild(m);
scene.AddChild(planet);
int fps = 0;
int startTime;
do
{
startTime = timeGetTime();
//check for keys and move camera accordingly
IF di.KeyDown(DIK_UP)
c.Move(0.0f,.25f * fAdjust);
IF di.KeyDown(DIK_DOWN)
c.Move(0.0f,-.25f * fAdjust);
IF di.KeyDown(DIK_RIGHT)
c.Rotate(1*.01745 * fAdjust,0,0);
IF di.KeyDown(DIK_LEFT)
c.Rotate(-1*.01745 * fAdjust,0,0);
IF di.KeyDown(DIK_Z)
c.Rotate(0,0,-1 *.01745 * fAdjust);
IF di.KeyDown(DIK_X)
c.Rotate(0,0,1 *.01745 * fAdjust);
IF di.KeyDown(DIK_PRIOR)
c.Rotate(0,-1 *.01745 * fAdjust,0);
IF di.KeyDown(DIK_NEXT)
c.Rotate(0,1 *.01745 * fAdjust,0);
IF di.KeyDown(DIK_R)
c.LookAt(0,0,0);
planet.Rotate(0,startTime / 2000.0f,0);
s.Clear(RGBA(0,0,0,255));
s.BeginScene(c);
scene.Draw();
s.RenderText(0,10,"FPS:"+NumToStr(fps),RGBA(255,255,0,255));
s.RenderText(0,30,"Use arrow keys,PgUp,PgDn to move around",RGBA(255,255,0,255));
fps = s.RenderScene();
fAdjust = (timeGetTime() - startTime) / fTarget;
}until di.KeyDown(DIK_ESCAPE);
Scene.Free();
}
Keep them coming Paul, that is nice. Will definitly come in very handy!! Just by bumping the random from 100 to 1000, the points are farther away and so far I haven't had any near the planet.
I like how you positioned the light so it really lights up the planet nicely and gives a very nice look from many different angles too!!
Wanted just a hint of a shadow on the planet, so moved the light down the X axis a bit.
And using a +/- 1000 does make it a bit more realistic ;)
Well, with all the goodies so far, I got enough to keep me busy for awhile. The sprites are going to allow some cool things to happen. I am eager to start, but trying to get a handle on pointers and classes before I start :)
Paul, that's a neat example.
when you drag the window's edge to stretch it bigger, the planet and space warps/stretches.
can you scale the image and remaining borders to suit the dragging of the border?
Also, how do you return the global xyz position and global xyz looking direction of the camera? I want to add that so I can find my way back to the planet easier.
Just press the R key. That resets the lookat point to 0,0,0 and you'll be facing the planet.
You can get all of the camera's paramters. See Aurora 3D Users Guide->Classes->C3DCamera->Methods.
GetPosition
GetDirection
GetUpVector
GetLookAt
Quote
can you scale the image and remaining borders to suit the dragging of the border?
Not currently. The final version will have an option to change the backbuffer size in response to an OnSize message.
Thanks,
I'm playing around with it. I found the X, Z and R controls and I added A and S.
I'm tweaking the starfield size ("fieldwidth"), color and backdrop and I'm adding position and heading info:
1st edit: editted to add functions and output position and heading (still need to tweak heading output)
2nd edit: editted to modify heading output to read degrees, repositioned the light source to shine from the y-axis
and made planet rotate about z-axit. I slowed the planets rotation abit and sped up the camera movement in and out.
3rd edit: fixed heading to reflect correct heading unit vector
// starfield.src
// An example using a point list to draw a starfield.
// Arrow keys to move camera.
// PgUp/PgDn to pan up and down.
// Z and X to rotate on Z axis.
declare import,timeGetTime(),int;
//Our FVF structure for points
struct point_vertex{
VECTOR3 pos;
DWORD color; // The vertex colour.
};
VECTOR3 c_ps, c_hd, c_up; // camera position & heading
#define point_fvf D3DFVF_XYZ|D3DFVF_DIFFUSE
#define num_points 20000
#define fieldwidth 1000
global sub main()
{
C3DScreen s;
C3DCamera c;
C3DMesh m;
C3DMesh planet;
C3DObject scene;
C3DLight light;
CDirectInput di;
float fadjust,fTarget;
//target 60FPS for camera movement
fTarget = 1.0f / /*FPS*/60.0f * 1000.0f;
fAdjust = 1.0f;
s.CreateWindowed(0,0,640,480,AWS_CAPTION|AWS_VISIBLE|AWS_SIZE|AWS_CENTERED,0,"3D Points - ESC exits",NULL,false);
di.Init(s);
c.Create(s);
c.Position(0,0,-50);
c.Orient(0,0,1,0,1,0);
c.SetBackPlane(1.75*fieldwidth);
s.Clear(RGBA(0,0,0,255));
s.BeginScene(c);
s.RenderText(0,10,"Loading objects...",RGBA(255,255,0,255));
s.RenderScene();
//create a point mesh with 'num_points' points.
m.CreateMeshEx(s,D3DPT_POINTLIST,num_points,num_points,num_points,point_fvf);
//Lock the vertex and index buffers so we can write to them.
point_vertex *v = m.LockVertexBuffer();
word *idx = m.LockIndexBuffer();
for(int x=0;x < num_points;x++)
{
*idx = x;
v->pos.x = rnd(-fieldwidth,fieldwidth);
v->pos.y = rnd(-fieldwidth,fieldwidth);
v->pos.z = rnd(-fieldwidth,fieldwidth);
v->color = RGBA(rnd(140,255),rnd(140,255),rnd(140,255),255);
v+=len(point_vertex);
idx+=len(word);
}
m.UnlockVertexBuffer();
m.UnlockIndexBuffer();
m.EnableLighting(false);
m.UseVertexColor(true);
m.SetVisible(true);
planet.CreateSphere(s,25,5.0,false);
planet.LoadTexture(0,GetStartPath()+"media\\tile3.tga",0);
light.Create(s,LIGHT_POINT,1);
light.Position(950,0,0);
light.SetAttenuation(0,1/2000.0,0);
light.SetSpecular(.5,.5,.5,1);
light.SetAmbient(.15,.15,.15,1);
scene.CreateScene(s);
scene.AddChild(light);
scene.AddChild(m);
scene.AddChild(planet);
int fps = 0;
int startTime;
do
{
startTime = timeGetTime();
// Position, Heading & Up Vectors of Camera
c_ps = c.GetPosition();
c_up = c.GetUpVector();
c_hd = c.GetDirection();
//check for keys and move camera accordingly
IF di.KeyDown(DIK_UP)
c.Move(0.0f,.75f * fAdjust);
IF di.KeyDown(DIK_DOWN)
c.Move(0.0f,-.75f * fAdjust);
IF di.KeyDown(DIK_RIGHT)
c.Rotate(1*.0174533 * fAdjust,0,0);
IF di.KeyDown(DIK_LEFT)
c.Rotate(-1*.0174533 * fAdjust,0,0);
IF di.KeyDown(DIK_Z)
c.Rotate(0,0,-1 *.0174533 * fAdjust);
IF di.KeyDown(DIK_X)
c.Rotate(0,0,1 *.0174533 * fAdjust);
IF di.KeyDown(DIK_PRIOR)
c.Rotate(0,-1 *.0174533 * fAdjust,0);
IF di.KeyDown(DIK_NEXT)
c.Rotate(0,1 *.0174533 * fAdjust,0);
IF di.KeyDown(DIK_R)
c.LookAt(0,0,0);
IF di.KeyDown(DIK_A)
c.Move(-.5f * fAdjust, 0.0f);
IF di.KeyDown(DIK_S)
c.Move( .5f * fAdjust, 0.0f);
planet.Rotate(0,0,startTime / 6000.0f);
s.Clear(RGBA(0,0,0,255));
s.BeginScene(c);
scene.Draw();
s.RenderText(10,10,"FPS: "+NumToStr(fps),RGBA(255,255,0,255));
s.RenderText(85,10,"Position: "+NumToStr(c_ps.x)+", "+NumToStr(c_ps.y)+", "+NumToStr(c_ps.z),RGBA(255,255,0,255));
s.RenderText(230,10,"Heading: "+NumToStr(c_hd.x, 3)+", "+NumToStr(c_hd.y, 3)+", "+NumToStr(c_hd.z, 3),RGBA(255,255,0,255));
s.RenderText(450,10,"Up:",RGBA(255,255,0,255));
s.RenderText(500,10,NumToStr(c_up.x, 2)+", "+NumToStr(c_up.y, 2)+", "+NumToStr(c_up.z, 2),RGBA(255,255,0,255));
s.RenderText(10,425,"Use arrow keys, PgUp, PgDn, A, S, Z, X, R to move around",RGBA(255,255,0,255));
fps = s.RenderScene();
fAdjust = (timeGetTime() - startTime) / fTarget;
}until di.KeyDown(DIK_ESCAPE);
Scene.Free();
}
Cool, some more interested in this stuff and playing and sharing, thanks.
I editted it again just before or after your reply. The heading output isn't working yet
Yep, got the new one. I had the same problem, you have to use USING to display floating numbers correctly.
This:
s.RenderText(450,10,"Heading: "+NumToStr(c_hd.x)+" , "+NumToStr(c_hd.y)+" , "+NumToStr(c_hd.z),RGBA(255,255,0,255));
Will need to be something like this:
headingText = USING("& x:%f###.## y:%f###.## z:%f###.##","Heading ",c_hd.x,c_hd.y,c_hd.z);
s.RenderText(450,10,headingText);
No you don't. Just use the optional parameter of NumToStr.
NumToStr(c_hd.x, 3)
Which specifies the number of decimal places.
Beat me to the punch on that. The second parameter is number of places, look at the tank demo. I am using the place holder.
that gives the direction in unit vector doesn't it?
I'm now using GetDirection and converting to degrees.
I have also changed the rotation of the planet about the z axis and put the light source on the y-axis.
Paul you told me to use using when I had a similar question, wow it is lots easier with that optional parameter :)
Kryton9
check out the last edit
Got it and playing, here is a goodie to say thanks for joining in on the fun, you can go wild with this stuff, enjoy, can't wait to see.
http://www.cortland.edu/flteach/civ/DavidWeb/resources.htm
Click on the planets to get the files from this site:
http://planetpixelemporium.com/earth.html
Paul,
I was looking at the GetUpVector method. Can I use that to determine the cameras rotation?
When using the X & Z controls, I still want A & S to slide the camera in the right and left direction.
The UP and Direction vector describe a 3D objects orientation in space. You can determine the X axis vextor by using the Vec3Cross function.
vxaxis = Vec3Cross(up, direction);
Paul,
I fixed the heading to reflect the unit vector output.
When I use the A & S controls to move the camera left or right after I rotate (using the Z & X controls) the camera does not slide left or right, but goes off in the global x and -x directions. Is this a bug?
here is the code snippet:
IF di.KeyDown(DIK_A)
c.Move(-.5f * fAdjust, 0.0f);
IF di.KeyDown(DIK_S)
c.Move( .5f * fAdjust, 0.0f);
I'm going to have to pull out my Linear Algebra books to refresh my vector math ;)
I take it that all of the methods are floating point? Can they be cast to double precision?
DirectX only uses floats.
And it might be a bug. Have to look into my original intentions ;)
This is sort of working, but not putting out the values constantly, my brain is fried at this point, will sleep on it, but maybe fresh eyes can catch what I am missing.
But it is giving it seems correct readings in 360 degrees when it does report :)
Forgot to mention I am just giving the calculation by using 0,0,0 as the other point, so I just need the one point to test it out
Also, I was lazy and just put the orientation where the x direction would be printed, so don't let that fool you.
// starfield.src
// An example using a point list to draw a starfield.
// Arrow keys to move camera.
// PgUp/PgDn to pan up and down.
// Z and X to rotate on Z axis.
declare import,timeGetTime(),int;
//Our FVF structure for points
struct point_vertex{
VECTOR3 pos;
DWORD color; ÂÃ, Ã‚Ã, Ã‚Ã, Ã‚Ã, // The vertex colour.
};
VECTOR3 c_ps, c_hd; // camera position & heading
#define point_fvf D3DFVF_XYZ|D3DFVF_DIFFUSE
#define num_points 20000
#define fieldwidth 1000
point pt;
global sub main()
{
C3DScreen s;
C3DCamera c;
C3DMesh m;
C3DMesh planet;
C3DObject scene;
C3DLight light;
CDirectInput di;
float fadjust,fTarget;
//target 60FPS for camera movement
fTarget = 1.0f / /*FPS*/60.0f * 1000.0f;
fAdjust = 1.0f;
s.CreateWindowed(0,0,640,480,AWS_CAPTION|AWS_VISIBLE|AWS_SIZE|AWS_CENTERED,0,"3D Points - ESC exits",NULL,false);
di.Init(s);
c.Create(s);
c.Position(0,0,-50);
c.Orient(0,0,1,0,1,0);
c.SetBackPlane(1.75*fieldwidth);
s.Clear(RGBA(0,0,0,255));
s.BeginScene(c);
s.RenderText(0,10,"Loading objects...",RGBA(255,255,0,255));
s.RenderScene();
//create a point mesh with 'num_points' points.
m.CreateMeshEx(s,D3DPT_POINTLIST,num_points,num_points,num_points,point_fvf);
//Lock the vertex and index buffers so we can write to them.
point_vertex *v = m.LockVertexBuffer();
word *idx = m.LockIndexBuffer();
for(int x=0;x < num_points;x++)
{
*idx = x;
v->pos.x = rnd(-fieldwidth,fieldwidth);
v->pos.y = rnd(-fieldwidth,fieldwidth);
v->pos.z = rnd(-fieldwidth,fieldwidth);
v->color = RGBA(rnd(140,255),rnd(140,255),rnd(140,255),255);
v+=len(point_vertex);
idx+=len(word);
}
m.UnlockVertexBuffer();
m.UnlockIndexBuffer();
m.EnableLighting(false);
m.UseVertexColor(true);
m.SetVisible(true);
planet.CreateSphere(s,25,5.0,false);
planet.LoadTexture(0,GetStartPath()+"media\\tile3.tga",0);
light.Create(s,LIGHT_POINT,1);
light.Position(100,0,0);
light.SetAttenuation(0,1/200.0,0);
light.SetSpecular(.5,.5,.5,1);
light.SetAmbient(.15,.15,.15,1);
scene.CreateScene(s);
scene.AddChild(light);
scene.AddChild(m);
scene.AddChild(planet);
int fps = 0;
int startTime;
do
{
startTime = timeGetTime();
//check for keys and move camera accordingly
IF di.KeyDown(DIK_UP)
c.Move(0.0f,.75f * fAdjust);
IF di.KeyDown(DIK_DOWN)
c.Move(0.0f,-.75f * fAdjust);
IF di.KeyDown(DIK_RIGHT)
c.Rotate(1*.01745 * fAdjust,0,0);
IF di.KeyDown(DIK_LEFT)
c.Rotate(-1*.01745 * fAdjust,0,0);
IF di.KeyDown(DIK_Z)
c.Rotate(0,0,-1 *.01745 * fAdjust);
IF di.KeyDown(DIK_X)
c.Rotate(0,0,1 *.01745 * fAdjust);
IF di.KeyDown(DIK_PRIOR)
c.Rotate(0,-1 *.01745 * fAdjust,0);
IF di.KeyDown(DIK_NEXT)
c.Rotate(0,1 *.01745 * fAdjust,0);
IF di.KeyDown(DIK_R)
c.LookAt(0,0,0);
IF di.KeyDown(DIK_A)
c.Move(-.5f * fAdjust,0.0f);
IF di.KeyDown(DIK_S)
c.Move( .5f * fAdjust,0.0f);
planet.Rotate(0,0,startTime / 6000.0f);
s.Clear(RGBA(0,0,0,255));
s.BeginScene(c);
scene.Draw();
s.RenderText(10,10,"FPS: "+NumToStr(fps),RGBA(255,255,0,255));
// ÂÃ, Position & Heading Vectors of Camera
c_ps = c.GetPosition();
c_hd ÂÃ, = c.GetDirection();
pt.x=c_hd.x;pt.y=c_hd.z;
c_hd.x= c_hd.y;
c_hd.y = c_hd.y;
c_hd.z = c_hd.z;
s.RenderText(200,10,"Position: ÂÃ, "+NumToStr(c_ps.x)+" , ÂÃ, "+NumToStr(c_ps.y)+" , ÂÃ, "+NumToStr(c_ps.z),RGBA(255,255,0,255));
s.RenderText(450,10,"Heading: ÂÃ, "+NumToStr(AngleOfPt(Pt))+" , ÂÃ, "+NumToStr(c_hd.y)+" , ÂÃ, "+NumToStr(c_hd.z),RGBA(255,255,0,255));
s.RenderText(10,425,"Use arrow keys, PgUp, PgDn, A, S, Z, X, R to move around",RGBA(255,255,0,255));
fps = s.RenderScene();
fAdjust = (timeGetTime() - startTime) / fTarget;
}until di.KeyDown(DIK_ESCAPE);
Scene.Free();
}
sub AngleOfPt(point Pt),double
{
const RADTODEG = 180 / 3.125;
Result = 0;
if ((Pt.x = 0) and (Pt.y < 0))
ÂÃ, {
Result = 270;
ÂÃ, }
ÂÃ, else if ((Pt.x = 0) and (Pt.y > 0))
ÂÃ, {
Result = 90;
ÂÃ, }
ÂÃ, else if ((Pt.x > 0) and (Pt.y >= 0))
ÂÃ, {
ÂÃ, Ã‚Ã, Result = ATan(Pt.y / Pt.x) * RADTODEG;
ÂÃ, }
ÂÃ, else if ((Pt.x < 0) And (Pt.y > 0))
ÂÃ, {
ÂÃ, Result = 180 - (ATan(Pt.y / Abs(Pt.x))* RADTODEG);
ÂÃ, }
ÂÃ, else if ((Pt.x < 0) And (Pt.y <= 0))
ÂÃ, {
ÂÃ, Ã‚Ã, Result = 180 + (ATan(Pt.y / Pt.x) * RADTODEG);
ÂÃ, }
ÂÃ, else if ((Pt.x > 0) and (Pt.y < 0))
ÂÃ, {
ÂÃ, Ã‚Ã, Result = 360 - (ATan(Abs(Pt.y) / Pt.x) * RADTODEG);
ÂÃ, }
else
{
Result=0;
}
return Result;
}
Paul,
can I scalar multiple a vector? Such as: 5.0 * VECTOR3
What does Vec3Lerp(VECTOR3 v1, VECTOR3 v2, FLOAT s); do?
Vec3Lerp: This function performs the linear interpolation based on the following formula: V1 + s(V2-V1).
No you can' t multiply a constant by a structure. We don't have overloaded operators ;)
Here's a function you can use:
sub Vec3Scale(VECTOR3 v, float s),VECTOR3
{
VECTOR3 ret = v;
v.x *= s;
v.y *= s;
v.z *= s;
return ret;
}
Quote from: John S on August 08, 2006, 10:36:34 PM
When I use the A & S controls to move the camera left or right after I rotate (using the Z & X controls) the camera does not slide left or right, but goes off in the global x and -x directions. Is this a bug?
...
Yep it was a bug, or at least an omission. Forgot to recalculate the Y axis when moving left/right. Fixed for Beta 1.
Thanks Paul,
I really jazzed your example up. I already brute forced the work around for Move and the Scalar function. I'm going to add in that scalar function you wrote to shorten the code.
IF di.KeyDown(DIK_A) // move/slide camera left
{ c_np.x = c_ps.x + c_rt.x*(-.5f * fAdjust);
c_np.y = c_ps.y + c_rt.y*(-.5f * fAdjust);
c_np.z = c_ps.z + c_rt.z*(-.5f * fAdjust);
c.Position(c_np.x,c_np.y,c_np.z);
c.Orient(c_hd.x,c_hd.y,c_hd.z,c_up.x,c_up.y,c_up.z);
};
You should include the scalar function in the next release.
Keep up the outstanding work
Anything that makes it a better engine is a good thing ;)
Just added a Reset method to C3DScreen. For resizing the rendering surface when a window is resized.
MyScreen::OnSize(int nType,int cx,int cy),int
{
Reset(cx,cy,0,false);
float aspect = cx/(cy+0f);
c.SetAspectRatio(aspect);
}
Reset will also allow switching from windowed to fullscreen modes eventually.
I tried using the new sub and Vec3Add and the program gave me goofy results. It worked fine with the brute force method,
New Code:
sub Vec3Scale( VECTOR3 v, float s ), VECTOR3
{
VECTOR3 ret = v;
v.x *= s;
v.y *= s;
v.z *= s;
return ret;
}
I will post the code that worked next
...
IF di.KeyDown(DIK_A) // move/slide camera left
{ c_np = Vec3Scale(c_rt, -.5f * fAdjust);
c_np = Vec3Add(c_ps, c_np);
c.Position(c_np.x,c_np.y,c_np.z);
c.Orient(c_hd.x,c_hd.y,c_hd.z,c_up.x,c_up.y,c_up.z);
};
IF di.KeyDown(DIK_S) // move/slide camera right
{ c_np = Vec3Scale(c_rt, .5f * fAdjust);
c_np = Vec3Add(c_ps, c_np);
c.Position(c_np.x,c_np.y,c_np.z);
c.Orient(c_hd.x,c_hd.y,c_hd.z,c_up.x,c_up.y,c_up.z);
};
IF di.KeyDown(DIK_E) // move/slide camera up
{ c_np = Vec3Scale(c_up, .5f * fAdjust);
c_np = Vec3Add(c_ps, c_np);
c.Position(c_np.x,c_np.y,c_np.z);
c.Orient(c_hd.x,c_hd.y,c_hd.z,c_up.x,c_up.y,c_up.z);
};
IF di.KeyDown(DIK_D) // move/slide camera right
{ c_np = Vec3Scale(c_up, -.5f * fAdjust);
c_np = Vec3Add(c_ps, c_np);
c.Position(c_np.x,c_np.y,c_np.z);
c.Orient(c_hd.x,c_hd.y,c_hd.z,c_up.x,c_up.y,c_up.z);
};
O.K. I learned a lot this evening! Here is my final attempt at this one.
I changed a few more things and added some more stuff.
Changed initial position and orientation of camera and some of the controls and speed of rotations.
Corrected the A & S controls for sliding camera left and right
Added E & D controls for sliding camera up and down
List of controls:
Up Arrow = rotate camera up
Dn Arrow = rotate camera down
Left Arrow = rotate camera left
Right Arrow = rotate camera right
V = Move Camera Forward
C = Move Camera Backward
Z = Roll Camera Counter Clockwise
X = Roll Camera Clockwise
A = Slide Camera Left
S = Slide Camera Right
E = Slide Camera Up
D = Slide Camera Down
R = Turn Camera towards Planet
Added some additional camera methods including:
GetPosition(), GetUpVector(), GetDirection(), Vec3Cross(c_up, c_hd)
New Code:
// 3dstarfield.src
// An example using a point list to draw a starfield.
// Arrow keys to move camera.
// PgUp/PgDn to pan up and down.
// Z and X to rotate on Z axis.
declare import,timeGetTime(),int;
//Our FVF structure for points
struct point_vertex{
VECTOR3 pos;
DWORD color; // The vertex colour.
};
VECTOR3 c_ps, c_hd, c_up, c_rt, c_np; // camera position, heading, etc
#define point_fvf D3DFVF_XYZ|D3DFVF_DIFFUSE
#define num_points 20000
#define fieldwidth 1000
global sub main()
{
C3DScreen s;
C3DCamera c;
C3DMesh m;
C3DMesh planet;
C3DObject scene;
C3DLight light;
CDirectInput di;
float fadjust,fTarget;
//target 60FPS for camera movement
fTarget = 1.0f / /*FPS*/60.0f * 1000.0f;
fAdjust = 1.0f;
s.CreateWindowed(0,0,640,480,AWS_CAPTION|AWS_VISIBLE|AWS_SIZE|AWS_CENTERED,0,"3D Points - ESC exits",NULL,false);
di.Init(s);
c.Create(s);
c.Position(0,-50,0);
c.Orient(0,1,0,0,0,1);
c.SetBackPlane(1.75*fieldwidth);
s.Clear(RGBA(0,0,0,255));
s.BeginScene(c);
s.RenderText(0,10,"Loading objects...",RGBA(255,255,0,255));
s.RenderScene();
//create a point mesh with 'num_points' points.
m.CreateMeshEx(s,D3DPT_POINTLIST,num_points,num_points,num_points,point_fvf);
//Lock the vertex and index buffers so we can write to them.
point_vertex *v = m.LockVertexBuffer();
word *idx = m.LockIndexBuffer();
for(int x=0;x < num_points;x++)
{
*idx = x;
v->pos.x = rnd(-fieldwidth,fieldwidth);
v->pos.y = rnd(-fieldwidth,fieldwidth);
v->pos.z = rnd(-fieldwidth,fieldwidth);
v->color = RGBA(rnd(140,255),rnd(140,255),rnd(140,255),255);
v+=len(point_vertex);
idx+=len(word);
}
m.UnlockVertexBuffer();
m.UnlockIndexBuffer();
m.EnableLighting(false);
m.UseVertexColor(true);
m.SetVisible(true);
planet.CreateSphere(s,25,5.0,false);
planet.LoadTexture(0,GetStartPath()+"media\\tile3.tga",0);
light.Create(s,LIGHT_POINT,1);
light.Position(950,0,0);
light.SetAttenuation(0,1/2000.0,0);
light.SetSpecular(.5,.5,.5,1);
light.SetAmbient(.15,.15,.15,1);
scene.CreateScene(s);
scene.AddChild(light);
scene.AddChild(m);
scene.AddChild(planet);
int fps = 0;
int startTime;
do
{
startTime = timeGetTime();
// Position, Heading & Up Vectors of Camera
c_ps = c.GetPosition();
c_up = c.GetUpVector();
c_hd = c.GetDirection();
c_rt = Vec3Cross(c_up, c_hd);
//check for keys and move camera accordingly
IF di.KeyDown(DIK_V)
c.Move(0.0f,.75f * fAdjust);
IF di.KeyDown(DIK_C)
c.Move(0.0f,-.75f * fAdjust);
IF di.KeyDown(DIK_RIGHT)
c.Rotate(.0174533 * fAdjust/2,0,0);
IF di.KeyDown(DIK_LEFT)
c.Rotate(-.0174533 * fAdjust/2,0,0);
IF di.KeyDown(DIK_Z)
c.Rotate(0,0,-.0174533 * fAdjust/2);
IF di.KeyDown(DIK_X)
c.Rotate(0,0,.0174533 * fAdjust/2);
IF di.KeyDown(DIK_UP)
c.Rotate(0,-.0174533 * fAdjust/2,0);
IF di.KeyDown(DIK_DOWN)
c.Rotate(0,.0174533 * fAdjust/2,0);
IF di.KeyDown(DIK_R)
c.LookAt(0,0,0);
IF di.KeyDown(DIK_A) // move/slide camera left
// c.Move(-.5f * fAdjust, 0.0f);
{ c_np.x = c_ps.x + c_rt.x*(-.5f * fAdjust);
c_np.y = c_ps.y + c_rt.y*(-.5f * fAdjust);
c_np.z = c_ps.z + c_rt.z*(-.5f * fAdjust);
c.Position(c_np.x,c_np.y,c_np.z);
c.Orient(c_hd.x,c_hd.y,c_hd.z,c_up.x,c_up.y,c_up.z);
};
IF di.KeyDown(DIK_S) // move/slide camera right
// c.Move( .5f * fAdjust, 0.0f);
{ c_np.x = c_ps.x + c_rt.x*(.5f * fAdjust);
c_np.y = c_ps.y + c_rt.y*(.5f * fAdjust);
c_np.z = c_ps.z + c_rt.z*(.5f * fAdjust);
c.Position(c_np.x,c_np.y,c_np.z);
c.Orient(c_hd.x,c_hd.y,c_hd.z,c_up.x,c_up.y,c_up.z);
};
IF di.KeyDown(DIK_E) // move/slide camera up
{ c_np.x = c_ps.x + c_up.x*(.5f * fAdjust);
c_np.y = c_ps.y + c_up.y*(.5f * fAdjust);
c_np.z = c_ps.z + c_up.z*(.5f * fAdjust);
c.Position(c_np.x,c_np.y,c_np.z);
c.Orient(c_hd.x,c_hd.y,c_hd.z,c_up.x,c_up.y,c_up.z);
};
IF di.KeyDown(DIK_D) // move/slide camera right
{ c_np.x = c_ps.x + c_up.x*(-.5f * fAdjust);
c_np.y = c_ps.y + c_up.y*(-.5f * fAdjust);
c_np.z = c_ps.z + c_up.z*(-.5f * fAdjust);
c.Position(c_np.x,c_np.y,c_np.z);
c.Orient(c_hd.x,c_hd.y,c_hd.z,c_up.x,c_up.y,c_up.z);
};
planet.Rotate(0,0,startTime / 6000.0f);
s.Clear(RGBA(0,0,0,255));
s.BeginScene(c);
scene.Draw();
s.RenderText(10,10,"FPS: "+NumToStr(fps),RGBA(255,255,0,255));
s.RenderText(85,10,"Position: "+NumToStr(c_ps.x)+", "+NumToStr(c_ps.y)+", "+NumToStr(c_ps.z),RGBA(255,255,0,255));
s.RenderText(250,10,"Heading: "+NumToStr(c_hd.x, 3)+", "+NumToStr(c_hd.y, 3)+", "+NumToStr(c_hd.z, 3),RGBA(255,255,0,255));
s.RenderText(470,10,"Up:",RGBA(255,255,0,255));
s.RenderText(500,10,NumToStr(c_up.x, 2)+", "+NumToStr(c_up.y, 2)+", "+NumToStr(c_up.z, 2),RGBA(255,255,0,255));
s.RenderText(470,30,"Rt:",RGBA(255,255,0,255));
s.RenderText(500,30,NumToStr(c_rt.x, 2)+", "+NumToStr(c_rt.y, 2)+", "+NumToStr(c_rt.z, 2),RGBA(255,255,0,255));
s.RenderText(10,425,"Use arrow keys, A, S, E, D, Z, X, C, V, R to move around and escape key to quit",RGBA(255,255,0,255));
fps = s.RenderScene();
fAdjust = (timeGetTime() - startTime) / fTarget;
}until di.KeyDown(DIK_ESCAPE);
Scene.Free();
}
Sorry I wrote that sub without testing it. Surprised you didn't spot the error ;)
sub Vec3Scale(VECTOR3 v, float s),VECTOR3
{
VECTOR3 ret = v;
ret.x *= s;
ret.y *= s;
ret.z *= s;
return ret;
}
Quote from: Paul Turley on August 09, 2006, 12:27:07 AM
... Surprised you didn't spot the error ;)
It was getting late. I will wrote thas sub in and it works great. Thanks
This weekend, I'm going to take this file and transform the planet into a sun and add a planet in orbit with a moon orbitting the planet.
Here is my final-final attempt at this one.
Corrected the sub Vec3Scale() and used Vec3Add()
List of controls:
Up Arrow = rotate camera up
Dn Arrow = rotate camera down
Left Arrow = rotate camera left
Right Arrow = rotate camera right
V = Move Camera Forward
C = Move Camera Backward
Z = Roll Camera Counter Clockwise
X = Roll Camera Clockwise
A = Slide Camera Left
S = Slide Camera Right
E = Slide Camera Up
D = Slide Camera Down
R = Turn Camera towards Planet
// 3d_starfield.src
// An example using a point list to draw a starfield.
// Arrow keys to move camera.
// PgUp/PgDn to pan up and down.
// Z and X to rotate on Z axis.
declare import,timeGetTime(),int;
sub Vec3Scale( VECTOR3 v, float s ), VECTOR3
{
VECTOR3 ret = v;
ret.x *= s;
ret.y *= s;
ret.z *= s;
return ret;
}
//Our FVF structure for points
struct point_vertex{
VECTOR3 pos;
DWORD color; // The vertex colour.
};
VECTOR3 c_ps, c_hd, c_up, c_rt, c_np; // camera position, heading, etc
#define point_fvf D3DFVF_XYZ|D3DFVF_DIFFUSE
#define num_points 20000
#define fieldwidth 1000
global sub main()
{
C3DScreen s;
C3DCamera c;
C3DMesh m;
C3DMesh planet;
C3DObject scene;
C3DLight light;
CDirectInput di;
float fadjust,fTarget;
//target 60FPS for camera movement
fTarget = 1.0f / /*FPS*/60.0f * 1000.0f;
fAdjust = 1.0f;
s.CreateWindowed(0,0,640,480,AWS_CAPTION|AWS_VISIBLE|AWS_SIZE|AWS_CENTERED,0,"3D Points - ESC exits",NULL,false);
di.Init(s);
c.Create(s);
c.Position(0,-50,0);
c.Orient(0,1,0,0,0,1);
c.SetBackPlane(1.75*fieldwidth);
s.Clear(RGBA(0,0,0,255));
s.BeginScene(c);
s.RenderText(0,10,"Loading objects...",RGBA(255,255,0,255));
s.RenderScene();
//create a point mesh with 'num_points' points.
m.CreateMeshEx(s,D3DPT_POINTLIST,num_points,num_points,num_points,point_fvf);
//Lock the vertex and index buffers so we can write to them.
point_vertex *v = m.LockVertexBuffer();
word *idx = m.LockIndexBuffer();
for(int x=0;x < num_points;x++)
{
*idx = x;
v->pos.x = rnd(-fieldwidth,fieldwidth);
v->pos.y = rnd(-fieldwidth,fieldwidth);
v->pos.z = rnd(-fieldwidth,fieldwidth);
v->color = RGBA(rnd(140,255),rnd(140,255),rnd(140,255),255);
v+=len(point_vertex);
idx+=len(word);
}
m.UnlockVertexBuffer();
m.UnlockIndexBuffer();
m.EnableLighting(false);
m.UseVertexColor(true);
m.SetVisible(true);
planet.CreateSphere(s,25,5.0,false);
planet.LoadTexture(0,GetStartPath()+"media\\tile3.tga",0);
light.Create(s,LIGHT_POINT,1);
light.Position(950,0,0);
light.SetAttenuation(0,1/2000.0,0);
light.SetSpecular(.5,.5,.5,1);
light.SetAmbient(.15,.15,.15,1);
scene.CreateScene(s);
scene.AddChild(light);
scene.AddChild(m);
scene.AddChild(planet);
int fps = 0;
int startTime;
do
{
startTime = timeGetTime();
// Position, Heading & Up Vectors of Camera
c_ps = c.GetPosition();
c_up = c.GetUpVector();
c_hd = c.GetDirection();
c_rt = Vec3Cross(c_up, c_hd);
//check for keys and move camera accordingly
IF di.KeyDown(DIK_V)
c.Move(0.0f,.75f * fAdjust);
IF di.KeyDown(DIK_C)
c.Move(0.0f,-.75f * fAdjust);
IF di.KeyDown(DIK_RIGHT)
c.Rotate(.0174533 * fAdjust/2,0,0);
IF di.KeyDown(DIK_LEFT)
c.Rotate(-.0174533 * fAdjust/2,0,0);
IF di.KeyDown(DIK_Z)
c.Rotate(0,0,-.0174533 * fAdjust/2);
IF di.KeyDown(DIK_X)
c.Rotate(0,0,.0174533 * fAdjust/2);
IF di.KeyDown(DIK_UP)
c.Rotate(0,-.0174533 * fAdjust/2,0);
IF di.KeyDown(DIK_DOWN)
c.Rotate(0,.0174533 * fAdjust/2,0);
IF di.KeyDown(DIK_R)
c.LookAt(0,0,0);
IF di.KeyDown(DIK_A) // move/slide camera left
{ c_np = Vec3Scale(c_rt, -.5f * fAdjust);
c_np = Vec3Add(c_ps, c_np);
c.Position(c_np.x,c_np.y,c_np.z);
c.Orient(c_hd.x,c_hd.y,c_hd.z,c_up.x,c_up.y,c_up.z);
};
IF di.KeyDown(DIK_S) // move/slide camera right
{ c_np = Vec3Scale(c_rt, .5f * fAdjust);
c_np = Vec3Add(c_ps, c_np);
c.Position(c_np.x,c_np.y,c_np.z);
c.Orient(c_hd.x,c_hd.y,c_hd.z,c_up.x,c_up.y,c_up.z);
};
IF di.KeyDown(DIK_E) // move/slide camera up
{ c_np = Vec3Scale(c_up, .5f * fAdjust);
c_np = Vec3Add(c_ps, c_np);
c.Position(c_np.x,c_np.y,c_np.z);
c.Orient(c_hd.x,c_hd.y,c_hd.z,c_up.x,c_up.y,c_up.z);
};
IF di.KeyDown(DIK_D) // move/slide camera right
{ c_np = Vec3Scale(c_up, -.5f * fAdjust);
c_np = Vec3Add(c_ps, c_np);
c.Position(c_np.x,c_np.y,c_np.z);
c.Orient(c_hd.x,c_hd.y,c_hd.z,c_up.x,c_up.y,c_up.z);
};
planet.Rotate(0,0,startTime / 6000.0f); // spin the planet
s.Clear(RGBA(0,0,0,255));
s.BeginScene(c);
scene.Draw();
s.RenderText(10,10,"FPS: "+NumToStr(fps),RGBA(255,255,0,255));
s.RenderText(85,10,"Position: "+NumToStr(c_ps.x)+", "+NumToStr(c_ps.y)+", "+NumToStr(c_ps.z),RGBA(255,255,0,255));
s.RenderText(250,10,"Heading: "+NumToStr(c_hd.x, 3)+", "+NumToStr(c_hd.y, 3)+", "+NumToStr(c_hd.z, 3),RGBA(255,255,0,255));
s.RenderText(470,10,"Up:",RGBA(255,255,0,255));
s.RenderText(500,10,NumToStr(c_up.x, 2)+", "+NumToStr(c_up.y, 2)+", "+NumToStr(c_up.z, 2),RGBA(255,255,0,255));
s.RenderText(470,30,"Rt:",RGBA(255,255,0,255));
s.RenderText(500,30,NumToStr(c_rt.x, 2)+", "+NumToStr(c_rt.y, 2)+", "+NumToStr(c_rt.z, 2),RGBA(255,255,0,255));
s.RenderText(10,425,"Use arrow keys, A, S, E, D, Z, X, C, V, R to move around and escape key to quit",RGBA(255,255,0,255));
fps = s.RenderScene();
fAdjust = (timeGetTime() - startTime) / fTarget;
}until di.KeyDown(DIK_ESCAPE);
Scene.Free();
}