In 3D vector graphics is the trick done with 4x4 homogenous transform matrices
- You create the matrix and apply it on the whole geometry
- that is usually done on gfx HW side
- in your case you don't even need to calculate the angles just compute the basis vectors
This is the glCircle3D in C++/OpenGL of mine:
void glCircle3D(double *pos,double *nor,double r,bool _fill)
{
int i,n=36;
double a,da=divide(pi2,n),p[3],dp[3],x[3],y[3];
// set x to something not parallel to normal vector
if (fabs(nor[0]-nor[1])>1e-6) vector_ld(x,nor[1],nor[0],nor[2]);
else if (fabs(nor[0]-nor[2])>1e-6) vector_ld(x,nor[2],nor[1],nor[0]);
else if (fabs(nor[1]-nor[2])>1e-6) vector_ld(x,nor[0],nor[2],nor[1]);
else vector_ld(x,1.0,0.0,0.0);
vector_mul(x,x,nor); // x=cross(x,nor)
vector_mul(y,x,nor); // y=cross(x,nor)
vector_len(x,x,r); // x=r*x/|x| ... r is scalar
vector_len(y,y,r); // y=r*y/|y| ... r is scalar
if (_fill)
{
glBegin(GL_TRIANGLE_FAN);
glVertex3dv(pos);
}
else glBegin(GL_LINE_STRIP);
for (a=0.0,i=0;i<=n;i++,a+=da)
{
vector_mul(dp,x,cos(a)); vector_add(p,pos,dp);
vector_mul(dp,y,sin(a)); vector_add(p,p ,dp);
glVertex3dv(p);
}
glEnd();
}
nor
is circle normal (in your case second vector)
pos
is circle center position (in your case 0,0,0)
r
is radius (in your case size of your first vector)
x,y
vectors are basis vectors with nor
defining orthogonal coordinate system
- if you want to construct the transform matrix then just copy the x,y,nor,pos to appropriate fields of the matrix
- and use circle geometry with radius 1
- as you can see no
atan2
or acos(dot(v1,v2))
is needed
- just simple cross product suffice...
- the code of mine use mine vector library
- so you just need to code functions like
vector_ld(a,x,y,z)
a[]={ x,y,z }
vector_mul(a,b,c)
a[]=b[] x c[]
vector_mul(a,b,c)
a[]=b[] * c
vector_add(a,b,c)
a[]=b[] + c[]
vector_sub(a,b,c)
a[]=b[] - c[]
vector_len(a,b,c)
a[]=b[]* c / |b[]|
- The circle coordinates are simple:
p=pos+x*cos(alpha)+y*sin(alpha);
- radius
r
is inside x,y
basis vectors already so no need to multiply by it