March 28, 2024, 06:24:00 PM

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


Function / Subroutine Take Vector Direction return Degrees (360)

Started by kryton9, August 09, 2006, 10:39:47 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

kryton9

I got the function finished tonight. You just send it the vector values and it will return the heading between 0 - 360 degrees.
I will write another one that will tell you the bearing between 2 objects soon, that is-- you will know from where you are to what heading you need to move to find the second object.

// Vector to Degrees Routine
// by Kryton9 written 8/9/2006
//
Declare import,timeGetTime(),int;
VECTOR3 camDir;

global sub main()
{
C3DScreen s;
C3DCamera c;
C3DMesh m,m2;
C3DObject scene;
C3DLight light,light2,light3;
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,"VecToDgrsÂÃ,  -ÂÃ,  Use arrow keys to move aroundÂÃ,  -ÂÃ,  Escape to quit",NULL,false);
di.Init(s);

c.Create(s);
c.Position(0,-300,0);
c.Orient(0,1,0,0,0,1);
c.SetBackPlane(10000);

s.Clear(RGBA(0,0,0,255));
s.BeginScene(c);
s.RenderScene();


m.CreateBox(s,25,10,50,false);
m2.CreateSphere(s,25,1000,true);

light.Create(s,LIGHT_POINT,1);
light.Position(75,75,75);
light.SetDiffuse(255, 0, 0, 255);
light.SetAttenuation(0,1/1000.0,0);
light2.Create(s,LIGHT_POINT,2);
light2.Position(-75,-75,-75);
light2.SetAttenuation(0,1/2000.0,0);
light2.SetDiffuse(0, 0, 255, 255);
light3.Create(s,LIGHT_POINT,3);
light3.Position(-75,0,75);
light3.SetAttenuation(0,1/2000.0,0);
light3.SetDiffuse(0, 255, 0, 255);

scene.CreateScene(s);
scene.AddChild(light);
scene.AddChild(m);
scene.AddChild(m2);

int fps = 0;
int startTime;
do
{
camDir = c.GetDirection();
IF di.KeyDown(DIK_UP) c.Move(0.0f,.75f);

IF di.KeyDown(DIK_DOWN) c.Move(0.0f,-.75f);

IF di.KeyDown(DIK_RIGHT)c.Rotate(.0174533/2,0,0);
IF di.KeyDown(DIK_LEFT) c.Rotate(-.0174533/2,0,0);

m.Rotate(timeGetTime()/1500.0,timeGetTime()/1500.0,0);

s.Clear(RGBA(0,0,0,255));
s.BeginScene(c);
scene.Draw();

s.RenderText(300,10,"Heading:ÂÃ,  "+NumToStr(VecToDgrs(camDir.x,camDir.y))+" ,ÂÃ,  camDir.x "+NumToStr(camDir.x,3)+" ,ÂÃ,  camDir.y "+NumToStr(camDir.y,3),RGBA(0,0,0,255));
s.RenderText(10,10,"FPS: "+NumToStr(fps),RGBA(0,0,0,255));

fps = s.RenderScene();
fAdjust = (timeGetTime() - startTime) / fTarget;
}until di.KeyDown(DIK_ESCAPE);
Scene.Free();
}


sub VecToDgrs(float x, float y),float
{
pi=3.14159265;
if x<0 AND y <0 {Result = 180-(180*atan(abs(x/y))/pi);}
else if x<0 AND y>0 {Result = 180*atan(abs(x/y))/pi;}
else if x>0 AND y<0 {Result = 180+(180*atan(abs(x/y))/pi);}
else if x>0 AND y>0 {Result = 360-(180*atan(abs(x/y))/pi);}
return result;
}

kryton9

This gives your heading (direction) in degrees 0 - 360

sub VecToDgrs(float x, float y),floatÂÃ,  ÂÃ, 


This gives you the heading you need to match to find the target object

sub HdngToTarget(double x, double y, double tx, double ty),doubleÂÃ, 

You might ask why did I use float in one and double in the other? The answer: I am not sure which to use, so was experimenting. I don't know if one is better than the other, it will be easy enough to change once someone can tell me which would be better :)

Till then enjoy, sorry about the psychedlic colors, but just wanted to show how you can do some cool things just by using lights in both examples. The heading to target comes in handy on this one as it is easy to lose the rectangle.

Enjoy :)

// Vector to Degrees Routine
// by Kryton9 written 8/9/2006
//
Declare import,timeGetTime(),int;
VECTOR3 camDir,camPos,mPos;

global sub main()
{
C3DScreen s;
C3DCamera c;
C3DMesh m,m2;
C3DObject scene;
C3DLight light,light2,light3;
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,"VecToDgrsÂÃ,  -ÂÃ,  Use arrow keys to move aroundÂÃ,  -ÂÃ,  Escape to quit",NULL,false);
di.Init(s);

c.Create(s);
c.Position(0,-300,0);
c.Orient(0,1,0,0,0,1);
c.SetBackPlane(10000);

s.Clear(RGBA(0,0,0,255));
s.BeginScene(c);
s.RenderScene();


m.CreateBox(s,25,10,50,false);
m2.CreateSphere(s,25,1000,true);

light.Create(s,LIGHT_POINT,1);
light.Position(0,0,0);
light.SetDiffuse(255, 0, 0, 255);
light.SetAttenuation(0,1/1000.0,0);
light2.Create(s,LIGHT_POINT,2);
light2.Position(0,0,-300);
light2.SetAttenuation(0,1/2000.0,0);
light2.SetDiffuse(0, 0, 255, 255);
light3.Create(s,LIGHT_POINT,3);
light3.Position(-300,0,0);
light3.SetAttenuation(0,1/2000.0,0);
light3.SetDiffuse(0, 255, 0, 255);

scene.CreateScene(s);
scene.AddChild(light);
scene.AddChild(m);
scene.AddChild(m2);

int fps = 0;
int startTime;
do
{
camDir = c.GetDirection();
camPos = c.GetPosition();
mPos = m.GetPosition(0);
IF di.KeyDown(DIK_UP) c.Move(0.0f,.75f);

IF di.KeyDown(DIK_DOWN) c.Move(0.0f,-.75f);

IF di.KeyDown(DIK_RIGHT)c.Rotate(.0174533/2,0,0);
IF di.KeyDown(DIK_LEFT) c.Rotate(-.0174533/2,0,0);

m.Rotate(timeGetTime()/1500.0,timeGetTime()/1500.0,0);

s.Clear(RGBA(0,0,0,255));
s.BeginScene(c);
scene.Draw();

s.RenderText(300,10,"Heading:ÂÃ,  "+NumToStr(VecToDgrs(camDir.x,camDir.y))+" ,ÂÃ,  camDir.x "+NumToStr(camDir.x,3)+" ,ÂÃ,  camDir.y "+NumToStr(camDir.y,3),RGBA(128,128,128,255));//(camDir.y,3)
s.RenderText(200,30,"HeadingToTarget:ÂÃ,  "+NumToStr(HdngToTarget(camPos.x,camPos.y,mPos.x,mPos.y))+" ,ÂÃ,  camPos.x "+NumToStr(camPos.x,3)+" ,ÂÃ,  camPos.y "+NumToStr(camDir.y,3),RGBA(128,128,128,255));
s.RenderText(300,50,"Object Pos :"+"ÂÃ,  mPos.x "+NumToStr(mPos.x,3)+" ,ÂÃ,  mPos.y "+NumToStr(mPos.y,3),RGBA(128,128,128,255));
s.RenderText(10,10,"FPS: "+NumToStr(fps),RGBA(128,128,128,255));

fps = s.RenderScene();
fAdjust = (timeGetTime() - startTime) / fTarget;
}until di.KeyDown(DIK_ESCAPE);
Scene.Free();
}


sub VecToDgrs(float x, float y),float
{
pi=3.14159265;
if x<0 AND y <0 {Result = 180-(180*atan(abs(x/y))/pi);}
else if x<0 AND y>0 {Result = 180*atan(abs(x/y))/pi;}
else if x>0 AND y<0 {Result = 180+(180*atan(abs(x/y))/pi);}
else if x>0 AND y>0 {Result = 360-(180*atan(abs(x/y))/pi);}
return result;
}

sub HdngToTarget(double x, double y, double tx, double ty),double
{
temp = VecToDgrs(x-tx,y-ty);
if temp>180 {temp=temp-180;}
else if temp <180 {temp=temp+180;}
return abs(temp);
}

J B Wood (Zumwalt)

Untested class, this is just the core begining of it, maybe you will find it useful, and I am probably off on my math, so forgive me, I hate math.. This is mainly to help you Kryton9 with your work you are doing.



class V3
{
declare _V3();
declare V3();
float x,y,z;

declare virtual add(C3DMesh obj1, C3DMesh obj2),VECTOR3;
declare virtual subtract(C3DMesh obj1, C3DMesh obj2),VECTOR3;
declare virtual multiply(C3DMesh obj1, C3DMesh obj2),VECTOR3;
declare virtual divide(C3DMesh obj1, C3DMesh obj2),VECTOR3;
declare virtual distance(VECTOR3 obj1, VECTOR3 obj2),VECTOR3;

}

V3 :: V3()
{
}

V3 :: _V3()
{
}

V3 :: add(C3DMesh obj1, C3DMesh obj2),VECTOR3
{
VECTOR3 a,b,c;
a=obj1.GetPosition(0);
b=obj2.GetPosition(0);

c.x=a.x + b.x;
c.y=a.y + b.y;
c.z=a.z + b.z;

return c;
}

V3 :: subtract(C3DMesh obj1, C3DMesh obj2),VECTOR3
{
VECTOR3 a,b,c;
a=obj1.GetPosition(0);
b=obj2.GetPosition(0);

c.x=a.x - b.x;
c.y=a.y - b.y;
c.z=a.z - b.z;

return c;
}

V3 :: multiply(C3DMesh obj1, C3DMesh obj2),VECTOR3
{
VECTOR3 a,b,c;
a=obj1.GetPosition(0);
b=obj2.GetPosition(0);

c.x=a.x * b.x;
c.y=a.y * b.y;
c.z=a.z * b.z;

return c;
}

V3 :: divide(C3DMesh obj1, C3DMesh obj2),VECTOR3
{
VECTOR3 a,b,c;
a=obj1.GetPosition(0);
b=obj2.GetPosition(0);

c.x=a.x / b.x;
c.y=a.y / b.y;
c.z=a.z / b.z;

return c;
}

V3 :: distance(VECTOR3 obj1, VECTOR3 obj2),VECTOR3
{
VECTOR3 diff;
diff.x = obj1.x - obj2.x;
diff.y = obj1.y - obj2.y;
diff.z = obj1.z - obj2.z;
return diff;
}

kryton9

Came across this nice simple method of converting between the 2 systems.

Rads to Degrees:  Rad / 0.0174532925 = Degrees

Degrees ro Rads:  Degrees * 0.0174532925 = Rads

pi / 180 = 0.0174532925

kryton9

Here is another useful routine. You send it an angle, in degrees, it returns back the wrapped value within 0 and 360 degrees.

WrapValue(float angleDegrees), float
{
   float angle;
   angleDegrees = angleDegrees / 360.0;
   angle = ( angleDegrees - Floor( angleDegrees ) ) * 360.0;
   return angle;
}

kryton9

Made the previous Sub even more functional. You can send it Degrees or Rads.

If you send it an angle in Rads, just put a positive int after as a second parameter, it will return back in degrees.
If it is in Degrees already, just leave the optional parameter blank.

So to send a Rad Angle:
WrapValue(-0.12345,1);

To send an Angle in Degrees:
WrapValue(752);

sub WrapValue(float angle, opt int Rad), float
{
   float angleDegrees;
   if (Rad)  angle = angle / 0.0174532925;
   angle = angle / 360.0;
   angleDegrees = ( angle - Floor( angle ) ) * 360.0;
   return angleDegrees;
}

kryton9

Is there a way I can make the function in the previous reply, faster. It is something I will be calling a lot in the future I know, and I would like to make sure it is as fast as can be.
Might as well start learning about writing faster routines.

Ionic Wind Support Team

Yes.  Make sure your not doing unneccessary conversions from double to float.


sub WrapValue(float angle, opt int Rad), float
{
   float angleDegrees;
   if (Rad)  angle = angle / 0.0174532925f;
   angle = angle / 360.0f;
   angleDegrees = ( angle - Floor( angle ) ) * 360.0f;
   return angleDegrees;
}
Ionic Wind Support Team

kryton9

Thanks Paul and thanks again for the LookAt command, that is going to make life a lot easier and funner with 3D calcs!!