Author Topic: 3d angle?  (Read 8490 times)

0 Members and 1 Guest are viewing this topic.

Offline Kirl

  • Senior Member
  • Pentium
  • ********
  • Posts: 1217
  • Karma: 230
    • View Profile
    • Homepage
3d angle?
« on: April 26, 2012 »
Alright so I'm happily clicking away at my keyboard, reformulating 2d math formulas into 3d without much problems until I hit upon a problem.

How do I calculate and define an angle in 3d?

In 2d it's pretty straightforward, I take the x and y distance (dx & dy) and do Math.atan2(dy, dx). I don't know why this works exactly, but it's easy enough to remember. How do I get and define angle between two points in xyz space?
www.kirl.nl
Challenge Trophies Won:

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: 3d angle?
« Reply #1 on: April 26, 2012 »
Math.atan2(dy, dx).
I don't know why this works exactly, but it's easy enough to remember.
Because of the unit circle.

Quote
How do I get and define angle between two points in xyz space?
acos( angle ) = |v1| dot |v2|
 - where |v| is a normalized vector (means length = 1)
 - "dot" is the dot-product (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z)
 - "acos(a)" is the inverse of cos(a)

« Last Edit: April 26, 2012 by hellfire »
Challenge Trophies Won:

Offline Kirl

  • Senior Member
  • Pentium
  • ********
  • Posts: 1217
  • Karma: 230
    • View Profile
    • Homepage
Re: 3d angle?
« Reply #2 on: April 26, 2012 »
Thanks Hellfire, some familiar bits in there. I've ran into the dotprod a nr of times before, looks a lot like getting the distance. I'm not entirely clear on everything yet, probably need a couple more read overs to really sink in. :)

I just got quite a generous helping of extra work on my plate for the comming weeks however, so I'll prolly revisit this at a later time.
www.kirl.nl
Challenge Trophies Won:

Offline combatking0

  • JavaScript lives!
  • Senior Member
  • DBF Aficionado
  • ********
  • Posts: 4569
  • Karma: 235
  • Retroman!
    • View Profile
    • Combat King's Barcode Battler Home
Re: 3d angle?
« Reply #3 on: May 01, 2012 »
My approach would be to use two angles in the style of coordinates.

The first angle would be on the horizontal plane, relative to the X axis.

The second angle is then measured from the horizontal plane up to the line of elevation.

Hopefully my diagram will be clearer than my explanation.
You are our 9001st visitor.
Challenge Trophies Won:

Offline Kirl

  • Senior Member
  • Pentium
  • ********
  • Posts: 1217
  • Karma: 230
    • View Profile
    • Homepage
Re: 3d angle?
« Reply #4 on: May 01, 2012 »
Thanks CK, that looks pretty straightforward. I guess I could do the movement in sequence as well. Unfortunatly I have a pretty bad cold atm and I'm not feeling very adventurous. I'll give this a try when I'm feeling a bit better. Thanks for the alternate, somewhat more familiar aproach! :)
www.kirl.nl
Challenge Trophies Won:

Offline combatking0

  • JavaScript lives!
  • Senior Member
  • DBF Aficionado
  • ********
  • Posts: 4569
  • Karma: 235
  • Retroman!
    • View Profile
    • Combat King's Barcode Battler Home
Re: 3d angle?
« Reply #5 on: May 01, 2012 »
I understand - I'm struggling to understand how to put X/Y/Z axes angles into a quaternion, and get the resulting X/Y/Z coordinates out of the other side.

I'm trying to avoid the "gimbal lock" issue caused by using static Euler angles.

My head hurts just thinking about it.
You are our 9001st visitor.
Challenge Trophies Won:

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: 3d angle?
« Reply #6 on: May 01, 2012 »
I'm struggling to understand how to put X/Y/Z axes angles into a quaternion, and get the resulting X/Y/Z coordinates out of the other side.
Euler-angles are just axis-angle rotations with an implicitly given axis.
You can describe two consecutive axis-angle rotations as a single rotation around a different axis (just like multiplying two matrices).
Just consider quaternions as a special form of axis-angle with a very useful interpolation operation.
Conversion from axis-angle to quaternion and back is described here and here.
When creating quaternions from an axis-angle representation be careful with angles of +/- 180 degrees.
Quaternions can be converted to a rotation matrix to transform your vectors conventionally.
« Last Edit: May 01, 2012 by hellfire »
Challenge Trophies Won:

Offline combatking0

  • JavaScript lives!
  • Senior Member
  • DBF Aficionado
  • ********
  • Posts: 4569
  • Karma: 235
  • Retroman!
    • View Profile
    • Combat King's Barcode Battler Home
Re: 3d angle?
« Reply #7 on: May 01, 2012 »
Thanks Hellfire,

I had found another page on one of the websites you have suggested, but it didn't have the information on the pages you have linked to.

I think I'll be able to get it working with this new data. K++
You are our 9001st visitor.
Challenge Trophies Won:

Offline combatking0

  • JavaScript lives!
  • Senior Member
  • DBF Aficionado
  • ********
  • Posts: 4569
  • Karma: 235
  • Retroman!
    • View Profile
    • Combat King's Barcode Battler Home
Re: 3d angle?
« Reply #8 on: May 02, 2012 »
I have put together a spreadsheet which converts X/Y/Z rotations into a Quaternion, and combines them with the coordinates of a point to give the resulting rotated coordinates after the rotations have been applied.

I will try to summerise my findings in code for the languages I know.

Quaternions in Yabasic anybody?
You are our 9001st visitor.
Challenge Trophies Won:

Offline combatking0

  • JavaScript lives!
  • Senior Member
  • DBF Aficionado
  • ********
  • Posts: 4569
  • Karma: 235
  • Retroman!
    • View Profile
    • Combat King's Barcode Battler Home
Re: 3d angle?
« Reply #9 on: May 03, 2012 »
Below is the Euler transformation, written in Actionscript:

Code: [Select]
function eulerTransform(x1,y1,z1,xr,yr,zr,xo,yo,zo){
var x2,y2,z2,pts=new Array();
// Rotate about X axis
x2=x1;
y2=y1*Math.cos(xr)+z1*Math.sin(xr);
z2=z1*Math.cos(xr)-y1*Math.sin(xr);
// Rotate about Y axis
y1=y2;
x1=x2*Math.cos(yr)-z2*Math.sin(yr);
z1=x2*Math.sin(yr)+z2*Math.cos(yr);
// Rotate about Z axis
z2=z1;
x2=x1*Math.cos(zr)-y1*Math.sin(zr);
y2=x1*Math.sin(zr)+y1*Math.cos(zr);
// Apply offsets in 3D space
pts[0]=x2+xo;
pts[1]=y2+yo;
pts[2]=z2+zo;
return(pts);
}

And below is the equivalent Quaternion transform, which takes the same arguments:

Code: [Select]
function quaternionTransform(x1,y1,z1,xr,yr,zr,xo,yo,zo){
var xc,yc,zc,xs,ys,zs,qr,q1,q2,q3;
xc=Math.cos(xr*0.5);
yc=Math.cos(yr*0.5);
zc=Math.cos(zr*0.5);
xs=Math.sin(xr*0.5);
ys=Math.sin(yr*0.5);
zs=Math.sin(zr*0.5);
qr=new Array();
qr[0]=xc*yc*zc-xs*ys*zs;
qr[1]=xs*yc*zc+xc*ys*zs;
qr[2]=xc*ys*zc-xs*yc*zs;
qr[3]=xs*ys*zc+xc*yc*zs;
q1=new Array(qr[0],0-qr[1],0-qr[2],0-qr[3]);
q2=new Array(0,x1,y1,z1);
q3=new Array(qr[0],qr[1],qr[2],qr[3]);
q2=qMult(q2,q1);
q3=qMult(q3,q2);
q3[1]+=xo;
q3[2]+=yo;
q3[3]+=zo;
q3.shift();
return(q3);
}

function qMult(m0,m1){
var m2=new Array();
m2[0]=m0[0]*m1[0]-m0[1]*m1[1]-m0[2]*m1[2]-m0[3]*m1[3];
m2[1]=m0[0]*m1[1]+m0[1]*m1[0]+m0[2]*m1[3]-m0[3]*m1[2];
m2[2]=m0[0]*m1[2]+m0[2]*m1[0]+m0[3]*m1[1]-m0[1]*m1[3];
m2[3]=m0[0]*m1[3]+m0[3]*m1[0]+m0[1]*m1[2]-m0[2]*m1[1];
return(m2);
}

The Quaternion code includes a 4*1 Array multiplier, since AS2 lacks the ability to multiply matrices, as far as I know.

I have attached a quick demonstration of the differences which I will include in a tutorial.
You are our 9001st visitor.
Challenge Trophies Won:

Offline Raizor

  • Founder Member
  • Pentium
  • ********
  • Posts: 1154
  • Karma: 175
    • View Profile
Re: 3d angle?
« Reply #10 on: May 03, 2012 »
That's great CK. A very useful demo. K++
raizor

Challenge Trophies Won:

Offline jace_stknights

  • Amiga 1200
  • ****
  • Posts: 399
  • Karma: 32
  • PEEK & POKE are not MOVEM!
    • View Profile
    • ST Knights WebSite
Re: 3d angle?
« Reply #11 on: May 04, 2012 »
heyyyy what strange, I'm just working on this tooo! Got some perspective problems with my 3d rout. I'm using them since the 80's with low resolution. And Actually, i got a very by distort on screen...

The way I'm calculating is like this:

Code: [Select]
; angleX, angleY and angleZ are the rotation in each axis

  C.f = -Sin(angleY)
  F.f = Cos(angleY) * Sin(angleY) ; = (sin x+y + sin x-y)/2
  I.f = Cos(angleY) * Cos(angleX) ;= (cos y+x + cos y-x)/2
  A.f = Cos(angleZ) * Cos(angleY) ;= (cos z+y + cos z-y)/2
  D.f = -Sin(angleZ) * Cos(angleX) + Cos(angleZ) * Sin(angleY) * Sin(angleX)          ; D = (cos z+y-x + cos z-y+x - cos z+y+x - cos z-y-x)/4 - (sin z+x + sin z-x)/2
  G.f = Sin(angleZ) * Sin(angleX) + Cos(angleZ) * Sin(angleY) * Cos(angleX)           ; G = (sin y+x+z + sin y+x-z + sin y-x+z + sin y-x-z)/4 + (cos z-x - cos z+x)/2
  B.f = Sin(angleZ) * Cos(angleY) ;= (sin z+y + sin z-y)/2
  E.f = Cos(angleZ) * Cos(angleX) + Sin(angleZ) * Sin(angleY) * Sin(angleX)           ; E = (sin z+y-x + sin z-y+x - sin z+y+x - sin z-y-x)/4 + (cos z+x + cos z-x)/2
  H.f = -Cos(angleZ) * Sin(angleX) + Sin(angleZ) * Sin(angleY) * Cos(angleX)         ; H = (cos z-y-x - cos z+y+x + cos z-y+x - cos z+y-x)/4 - (sin x+z + sin x-z)/2

; here is the x,y,z axis conversion in 2D
    q.f = 1 -((C*x+F*y+I*z)+Dz)/400
    xplot = (((A*x+D*y+G*z)+Dx)/q)*+ screenw/2
    yplot = (((B*x+E*y+H*z)+Dy)/q)*+ screenh/2

I got at the end the coords for the 2D point. But this way gave me a big distort for big values... Someone got a simple technique for 3D to 2D perspective translation?
Challenge Trophies Won:

Offline combatking0

  • JavaScript lives!
  • Senior Member
  • DBF Aficionado
  • ********
  • Posts: 4569
  • Karma: 235
  • Retroman!
    • View Profile
    • Combat King's Barcode Battler Home
Re: 3d angle?
« Reply #12 on: May 04, 2012 »
Here's my 3D to 2D converter:

Code: [Select]
function transform2D(x1,y1,z1,zm,sz,xo,yo){
var x2,y2,pts=new Array();
var dv=(z1*zm*0.0125)+1;
x2=sz*(x1/dv)+xo;
y2=-sz*(y1/dv)+yo;
pts[0]=x2;
pts[1]=y2;
return(pts);
}

x1, y1 and z1 are the 3D coordinates of the point.
zm is the Z-Multiplier - I use a value of 40 for this, but you can change it to suit your needs.
sz is the Size Multiplier. Typical values for this can be 50 to 500, depending on the size of your graphic window and the scale of your 3D coordinates.
xo and yo are the 2D offsets. Use these if the 0,0 point of your graphic window is in a corner. OpenGL has its 0,0 point in the centre, so these may be set to 0 for OpenGL.

The output is an array with 2 values. Value 0 is the X coordinate, and value 1 is the Y coordinate.
You are our 9001st visitor.
Challenge Trophies Won:

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: 3d angle?
« Reply #13 on: May 04, 2012 »
zm is the Z-Multiplier - I use a value of 40 for this, but you can change it to suit your needs.
That's what they call field of view in photography (the projection models the attributes of your camera) and it's convenient to describe it as an angle.
Since it's just a 2d-scale it can be multiplied with the transformation matrix beforehand.
So you're just deviding by z in the perspective transform which makes 3d clipping and culling very efficient.
To test if a vertex is inside the view fructum you just have to test:
Code: [Select]
-z > x < +z
-z > y < +z
Challenge Trophies Won:

Offline Kirl

  • Senior Member
  • Pentium
  • ********
  • Posts: 1217
  • Karma: 230
    • View Profile
    • Homepage
Re: 3d angle?
« Reply #14 on: May 04, 2012 »
Hey that is pretty excellent, I've been looking for exactly that as well! Some really good info to process and digist in here, thanks CK0 and Hellfire!

My 3d to 2d screen coord function is as follows, it evolved from Keith Peters code. I like it as I can adjust fl (cam focal length) and the vpX, vpY (vanishing points):

Code: [Select]
function doDepth( xx, yy, zz ) // return screen xy
{
var vScale = fl / (fl + zz);
return { x:(vpX + xx * vScale), y:(vpY + yy * vScale) };
}
www.kirl.nl
Challenge Trophies Won: