इसके लिए रोटेशन का उपयोग न करें जब आप सीधे तीरहेड बना सकते हैं। इसी प्रकार झुका हुआ ट्यूब भी इस तरह से किया जा सकता है। केवल इसके लिए आपको जिस चीज की आवश्यकता है वह अंतिम पंक्ति खंड A,B
एंडपॉइंट्स द्वारा परिभाषित किया गया है।
A
तेज बिंदु और B
डिस्क बेस सेंटर बनें। तीरहेड बनाने के लिए आपको 2 अतिरिक्त आधार वैक्टरों की आवश्यकता है, उन्हें बेस डिस्क के U,V
और त्रिज्या r
पर कॉल करें। उन लोगों से आप इस तरह सरल चक्र फार्मूले के साथ डिस्क अंक बना सकते हैं:
AB
अंतिमबिंदुओं
गणना U,V
आधार वैक्टर
U,V
होनी चाहिए प्राप्त तीरहेड के डिस्क बेस में और पेपे होना चाहिए एक दूसरे के लिए सामान्य।तीर (लाइन |BA|
) की दिशा सामान्य तो पार उत्पाद का फायदा उठाने डिस्क स्थान है जहाँ बढ़ी लोगों इतना करने के लिए खड़ा वेक्टर देता है:
W = B-A;
W /= |W|; // unit vector
T = (1,0,0); // temp any non zero vector not parallel to W
if (|(W.T)|>0.75) T = (0,1,0); // if abs dot product of T and W is close to 1 it means they are close to parallel so chose different T
U = (T x W) // U is perpendicular to T,W
V = (U x W) // V is perpendicular to U,W
बनाने/प्रस्तुत करना तीर ज्यामिति
आसान बूथ है
P(ang) = B + U.r.cos(ang) + V.r.sin(ang)
तो बस पाश: A,B
त्रिकोण प्रशंसक (जरूरत 2) और डिस्क आधार अंक के केन्द्रों इस तरह की गणना कर रहे हैंपूरे चरण के माध्यम से पूरे चरण के माध्यम से आपको पर्याप्त अंक मिलते हैं (आमतौर पर 36 पर्याप्त है) और दोनों त्रिभुज प्रशंसकों को करते हैं। भूलें कि अंतिम डिस्क बिंदु पहले जैसा ही होना चाहिए अन्यथा आपको ang = 0
या 360
डिग्री पर बदसूरत लग रहा है या छेद मिलेगा।
यदि आप अभी भी घूर्णन के लिए जाना चाहते हैं तो यह ऐसा करने योग्य है। उपरोक्त के रूप में U,V,W
की गणना करें और उनसे रूपांतरण मैट्रिक्स बनाएं। मूल O
बिंदु B
और अक्ष X,Y,Z
U,V,W
होगा आदेश आपके तीरहेड मॉडल पर निर्भर करता है। W
मॉडल धुरी से मेल खाना चाहिए। U,V
किसी भी क्रम में हो सकता है। तो बस सभी वैक्टरों को अपने स्थानों पर कॉपी करें और प्रतिपादन के लिए इस मैट्रिक्स का उपयोग करें। अधिक जानकारी के लिए देखें:
[नोट्स]
आप पार/डॉट उत्पादों या निरपेक्ष मूल्य की तरह वेक्टर संचालन गणना करने के लिए कैसे देखते हैं पता नहीं है:
// cross product: W = U x V
W.x=(U.y*V.z)-(U.z*V.y)
W.y=(U.z*V.x)-(U.x*V.z)
W.z=(U.x*V.y)-(U.y*V.x)
// dot product: a = (U.V)
a=U.x*V.x+U.y*V.y+U.z*V.z
// abs of vector a = |U|
a=sqrt((U.x*U.x)+(U.y*U.y)+(U.z*U.z))
[संपादित करें] सरल जीएल कार्यान्वयन
मैं अपने वातावरण में नहीं कोड है, लेकिन downvote और टिप्पणी के रूप में सुझाव है कि आप लोगों को जो अजीब पर विचार आप इस मिल गया है अब तक इसलिए यहाँ सरल सी ++/जीएल की कैसे उदाहरण के अपने दम पर एक साथ इस डाल करने के लिए सक्षम नहीं हैं इस (आप कर सकते हैं अपने वातावरण को यह बंदरगाह) कार्य करें:
void glArrowRoundxy(GLfloat x0,GLfloat y0,GLfloat z0,GLfloat r,GLfloat r0,GLfloat r1,GLfloat a0,GLfloat a1,GLfloat a2)
{
const int _glCircleN=50; // points per circle
const int n=3*_glCircleN;
int i,j,ix,e;
float x,y,z,x1,y1,z1,a,b,da,db=pi2/(_glCircleN-1);
float ux,uy,uz,vx,vy,vz,u,v;
// buffers
GLfloat ptab[6*_glCircleN],*p0,*p1,*n0,*n1,*p;
p0=ptab+(0*_glCircleN); // previous tube segment circle points
p1=ptab+(3*_glCircleN); // actual tube segment circle points
da=+db; if (a0>a1) da=-db; // main angle step direction
ux=0.0; // U is normal to arrow plane
uy=0.0;
uz=1.0;
// arc interpolation a=<a0,a1>
for (e=1,j=0,a=a0;e;j++,a+=da)
{
// end conditions
if ((da>0.0)&&(a>=a1)) { a=a1; e=0; }
if ((da<0.0)&&(a<=a1)) { a=a1; e=0; }
// compute actual tube ceneter
x1=x0+(r*cos(a));
y1=y0+(r*sin(a));
z1=z0;
// V is direction from (x0,y0,z0) to (x1,y1,z1)
vx=x1-x0;
vy=y1-y0;
vz=z1-z0;
// and unit of coarse
b=sqrt((vx*vx)+(vy*vy)+(vz*vz));
if (b>1e-6) b=1.0/b; else b=0.0;
vx*=b;
vy*=b;
vz*=b;
// tube segment
for (ix=0,b=0.0,i=0;i<_glCircleN;i++,b+=db)
{
u=r0*cos(b);
v=r0*sin(b);
p1[ix]=x1+(ux*u)+(vx*v); ix++;
p1[ix]=y1+(uy*u)+(vy*v); ix++;
p1[ix]=z1+(uz*u)+(vz*v); ix++;
}
if (!j)
{
glBegin(GL_TRIANGLE_FAN);
glVertex3f(x1,y1,z1);
for (ix=0;ix<n;ix+=3) glVertex3fv(p1+ix);
glEnd();
}
else{
glBegin(GL_QUAD_STRIP);
for (ix=0;ix<n;ix+=3)
{
glVertex3fv(p0+ix);
glVertex3fv(p1+ix);
}
glEnd();
}
// swap buffers
p=p0; p0=p1; p1=p;
p=n0; n0=n1; n1=p;
}
// arrowhead a=<a1,a2>
for (ix=0,b=0.0,i=0;i<_glCircleN;i++,b+=db)
{
u=r1*cos(b);
v=r1*sin(b);
p1[ix]=x1+(ux*u)+(vx*v); ix++;
p1[ix]=y1+(uy*u)+(vy*v); ix++;
p1[ix]=z1+(uz*u)+(vz*v); ix++;
}
glBegin(GL_TRIANGLE_FAN);
glVertex3f(x1,y1,z1);
for (ix=0;ix<n;ix+=3) glVertex3fv(p1+ix);
glEnd();
x1=x0+(r*cos(a2));
y1=y0+(r*sin(a2));
z1=z0;
glBegin(GL_TRIANGLE_FAN);
glVertex3f(x1,y1,z1);
for (ix=n-3;ix>=0;ix-=3) glVertex3fv(p1+ix);
glEnd();
}
इस केंद्र x,y,z
और बड़े त्रिज्या r
साथ XY विमान में मुड़ा हुआ तीर बना देता है। r0
ट्यूब त्रिज्या है और r1
तीरहेड आधार त्रिज्या है। चूंकि मेरे पास आपकी वक्र परिभाषा नहीं है, मैं XY विमान में सर्कल चुनता हूं। a0,a1,a2
कोण हैं जहां तीर शुरू होता है (a0
), तीरहेड शुरू होता है (a1
) और समाप्त होता है (a2
)। pi2
सिर्फ स्थिर pi2=6.283185307179586476925286766559
है।
विचार वास्तविक और पिछले ट्यूब खंड सर्कल बिंदुओं को याद रखना है, इसलिए के लिए अन्यथा आपको दो बार गणना करने की आवश्यकता होगी।
जैसा कि मैंने सीधे एक्सवाई विमान चुना है, मुझे पता है कि एक बेस वेक्टर सामान्य है।और दूसरा इसके लिए लंबवत है और तीर दिशा सौभाग्य से सर्कल गुणों को स्वयं ही प्रदान करता है इसलिए इस मामले में क्रॉस उत्पादों की आवश्यकता नहीं है।
आशा है कि अगर मुझे टिप्पणी न करें तो यह पर्याप्त स्पष्ट है।
[EDIT2]
मैं तो यहाँ मेरी इंजन में जोड़ने के लिए 3 डी संस्करण (न केवल गठबंधन तीर अक्ष के लिए बाध्य और शंकु भी मुड़ा हुआ है) की जरूरत है। वेक्टर गणना के आधार पर यह वही है और मैं हेडर <a0,a1>
में कुछ कोणों को भी बदलता हूं, पूरे अंतराल और aa
तीर का आकार है लेकिन बाद में कोड में इसे मूल सम्मेलन में परिवर्तित कर दिया जाता है। मैंने प्रकाश गणना के लिए भी मानक जोड़ा। मैंने रैखिक तीर भी जोड़ा जहां आधार वैक्टरों की गणना अलग-अलग वक्र होने पर सर्कल गुणों का लाभ नहीं ले रही है। यहाँ परिणाम:
//---------------------------------------------------------------------------
const int _glCircleN=50; // points per circle
//---------------------------------------------------------------------------
void glCircleArrowxy(GLfloat x0,GLfloat y0,GLfloat z0,GLfloat r,GLfloat r0,GLfloat r1,GLfloat a0,GLfloat a1,GLfloat aa)
{
double pos[3]={ x0, y0, z0};
double nor[3]={0.0,0.0,1.0};
double bin[3]={1.0,0.0,0.0};
glCircleArrow3D(pos,nor,bin,r,r0,r1,a0,a1,aa);
}
//---------------------------------------------------------------------------
void glCircleArrowyz(GLfloat x0,GLfloat y0,GLfloat z0,GLfloat r,GLfloat r0,GLfloat r1,GLfloat a0,GLfloat a1,GLfloat aa)
{
double pos[3]={ x0, y0, z0};
double nor[3]={1.0,0.0,0.0};
double bin[3]={0.0,1.0,0.0};
glCircleArrow3D(pos,nor,bin,r,r0,r1,a0,a1,aa);
}
//---------------------------------------------------------------------------
void glCircleArrowxz(GLfloat x0,GLfloat y0,GLfloat z0,GLfloat r,GLfloat r0,GLfloat r1,GLfloat a0,GLfloat a1,GLfloat aa)
{
double pos[3]={ x0, y0, z0};
double nor[3]={0.0,1.0,0.0};
double bin[3]={0.0,0.0,1.0};
glCircleArrow3D(pos,nor,bin,r,r0,r1,a0,a1,aa);
}
//---------------------------------------------------------------------------
void glCircleArrow3D(double *pos,double *nor,double *bin,double r,double r0,double r1,double a0,double a1,double aa)
{
// const int _glCircleN=20; // points per circle
int e,i,j,N=3*_glCircleN;
double U[3],V[3],u,v;
double a,b,da,db=pi2/double(_glCircleN-1),a2,rr;
double *ptab,*p0,*p1,*n0,*n1,*pp,p[3],q[3],c[3],n[3],tan[3];
// buffers
ptab=new double [12*_glCircleN]; if (ptab==NULL) return;
p0=ptab+(0*_glCircleN);
n0=ptab+(3*_glCircleN);
p1=ptab+(6*_glCircleN);
n1=ptab+(9*_glCircleN);
// prepare angles
a2=a1; da=db; aa=fabs(aa);
if (a0>a1) { da=-da; aa=-aa; }
a1-=aa;
// compute missing basis vectors
vector_copy(U,nor); // U is normal to arrow plane
vector_mul(tan,nor,bin); // tangent is perpendicular to normal and binormal
// arc interpolation a=<a0,a2>
for (e=0,j=0,a=a0;e<5;j++,a+=da)
{
// end conditions
if (e==0) // e=0
{
if ((da>0.0)&&(a>=a1)) { a=a1; e++; }
if ((da<0.0)&&(a<=a1)) { a=a1; e++; }
rr=r0;
}
else{ // e=1,2,3,4
if ((da>0.0)&&(a>=a2)) { a=a2; e++; }
if ((da<0.0)&&(a<=a2)) { a=a2; e++; }
rr=r1*fabs(divide(a-a2,a2-a1));
}
// compute actual tube segment center c[3]
u=r*cos(a);
v=r*sin(a);
vector_mul(p,bin,u);
vector_mul(q,tan,v);
vector_add(c,p, q);
vector_add(c,c,pos);
// V is unit direction from arrow center to tube segment center
vector_sub(V,c,pos);
vector_one(V,V);
// tube segment interpolation
for (b=0.0,i=0;i<N;i+=3,b+=db)
{
u=cos(b);
v=sin(b);
vector_mul(p,U,u); // normal
vector_mul(q,V,v);
vector_add(n1+i,p,q);
vector_mul(p,n1+i,rr); // vertex
vector_add(p1+i,p,c);
}
if (e>1) // recompute normals for cone
{
for (i=3;i<N;i+=3)
{
vector_sub(p,p0+i ,p1+i);
vector_sub(q,p1+i-3,p1+i);
vector_mul(p,p,q);
vector_one(n1+i,p);
}
vector_sub(p,p0 ,p1);
vector_sub(q,p1+N-3,p1);
vector_mul(p,q,p);
vector_one(n1,p);
if (da>0.0) for (i=0;i<N;i+=3) vector_neg(n1+i,n1+i);
if (e== 3) for (i=0;i<N;i+=3) vector_copy(n0+i,n1+i);
}
// render base disc
if (!j)
{
vector_mul(n,U,V);
glBegin(GL_TRIANGLE_FAN);
glNormal3dv(n);
glVertex3dv(c);
if (da<0.0) for (i=N-3;i>=0;i-=3) glVertex3dv(p1+i);
else for (i= 0;i< N;i+=3) glVertex3dv(p1+i);
glEnd();
}
// render tube
else{
glBegin(GL_QUAD_STRIP);
if (da<0.0) for (i=0;i<N;i+=3)
{
glNormal3dv(n1+i); glVertex3dv(p1+i);
glNormal3dv(n0+i); glVertex3dv(p0+i);
}
else for (i=0;i<N;i+=3)
{
glNormal3dv(n0+i); glVertex3dv(p0+i);
glNormal3dv(n1+i); glVertex3dv(p1+i);
}
glEnd();
}
// swap buffers
pp=p0; p0=p1; p1=pp;
pp=n0; n0=n1; n1=pp;
// handle r0 -> r1 edge
if (e==1) a-=da;
if ((e==1)||(e==2)||(e==3)) e++;
}
// release buffers
delete[] ptab;
}
//---------------------------------------------------------------------------
void glLinearArrow3D(double *pos,double *dir,double r0,double r1,double l,double al)
{
// const int _glCircleN=20; // points per circle
int e,i,N=3*_glCircleN;
double U[3],V[3],W[3],u,v;
double a,da=pi2/double(_glCircleN-1),r,t;
double *ptab,*p0,*p1,*n1,*pp,p[3],q[3],c[3],n[3];
// buffers
ptab=new double [9*_glCircleN]; if (ptab==NULL) return;
p0=ptab+(0*_glCircleN);
p1=ptab+(3*_glCircleN);
n1=ptab+(6*_glCircleN);
// compute basis vectors
vector_one(W,dir);
vector_ld(p,1.0,0.0,0.0);
vector_ld(q,0.0,1.0,0.0);
vector_ld(n,0.0,0.0,1.0);
a=fabs(vector_mul(W,p)); pp=p; t=a;
a=fabs(vector_mul(W,q)); if (t>a) { pp=q; t=a; }
a=fabs(vector_mul(W,n)); if (t>a) { pp=n; t=a; }
vector_mul(U,W,pp);
vector_mul(V,U,W);
vector_mul(U,V,W);
for (e=0;e<4;e++)
{
// segment center
if (e==0) { t=0.0; r= r0; }
if (e==1) { t=l-al; r= r0; }
if (e==2) { t=l-al; r= r1; }
if (e==3) { t=l; r=0.0; }
vector_mul(c,W,t);
vector_add(c,c,pos);
// tube segment interpolation
for (a=0.0,i=0;i<N;i+=3,a+=da)
{
u=cos(a);
v=sin(a);
vector_mul(p,U,u); // normal
vector_mul(q,V,v);
vector_add(n1+i,p,q);
vector_mul(p,n1+i,r); // vertex
vector_add(p1+i,p,c);
}
if (e>2) // recompute normals for cone
{
for (i=3;i<N;i+=3)
{
vector_sub(p,p0+i ,p1+i);
vector_sub(q,p1+i-3,p1+i);
vector_mul(p,p,q);
vector_one(n1+i,p);
}
vector_sub(p,p0 ,p1);
vector_sub(q,p1+N-3,p1);
vector_mul(p,q,p);
vector_one(n1,p);
}
// render base disc
if (!e)
{
vector_neg(n,W);
glBegin(GL_TRIANGLE_FAN);
glNormal3dv(n);
glVertex3dv(c);
for (i=0;i<N;i+=3) glVertex3dv(p1+i);
glEnd();
}
// render tube
else{
glBegin(GL_QUAD_STRIP);
for (i=0;i<N;i+=3)
{
glNormal3dv(n1+i);
glVertex3dv(p0+i);
glVertex3dv(p1+i);
}
glEnd();
}
// swap buffers
pp=p0; p0=p1; p1=pp;
}
// release buffers
delete[] ptab;
}
//---------------------------------------------------------------------------
उपयोग:
glColor3f(0.5,0.5,0.5);
glCircleArrowyz(+3.5,0.0,0.0,0.5,0.1,0.2,0.0*deg,+270.0*deg,45.0*deg);
glCircleArrowyz(-3.5,0.0,0.0,0.5,0.1,0.2,0.0*deg,-270.0*deg,45.0*deg);
glCircleArrowxz(0.0,+3.5,0.0,0.5,0.1,0.2,0.0*deg,+270.0*deg,45.0*deg);
glCircleArrowxz(0.0,-3.5,0.0,0.5,0.1,0.2,0.0*deg,-270.0*deg,45.0*deg);
glCircleArrowxy(0.0,0.0,+3.5,0.5,0.1,0.2,0.0*deg,+270.0*deg,45.0*deg);
glCircleArrowxy(0.0,0.0,-3.5,0.5,0.1,0.2,0.0*deg,-270.0*deg,45.0*deg);
glColor3f(0.2,0.2,0.2);
glLinearArrow3D(vector_ld(+2.0,0.0,0.0),vector_ld(+1.0,0.0,0.0),0.1,0.2,2.0,0.5);
glLinearArrow3D(vector_ld(-2.0,0.0,0.0),vector_ld(-1.0,0.0,0.0),0.1,0.2,2.0,0.5);
glLinearArrow3D(vector_ld(0.0,+2.0,0.0),vector_ld(0.0,+1.0,0.0),0.1,0.2,2.0,0.5);
glLinearArrow3D(vector_ld(0.0,-2.0,0.0),vector_ld(0.0,-1.0,0.0),0.1,0.2,2.0,0.5);
glLinearArrow3D(vector_ld(0.0,0.0,+2.0),vector_ld(0.0,0.0,+1.0),0.1,0.2,2.0,0.5);
glLinearArrow3D(vector_ld(0.0,0.0,-2.0),vector_ld(0.0,0.0,-1.0),0.1,0.2,2.0,0.5);
और (छवि के दाईं ओर) arows का अवलोकन:
मैं तो यहाँ मेरी वेक्टर lib उपयोग कर रहा हूँ कुछ स्पष्टीकरण हैं:
vector_mul(a[3],b[3],c[3])
पार उत्पाद a = b x c
vector_mul(a[3],b[3],c)
a = b/|b|
vector_copy(a[3],b[3])
सिर्फ नकल कर रहा है द्वारा अदिश a = b.c
a = vector_mul(b[3],c[3])
सरल गुणा डॉट उत्पाद a = (b.c)
vector_one(a[3],b[3])
है इकाई वेक्टर है a = b
vector_add(a[3],b[3],c[3])
a = b + c
vector_sub(a[3],b[3],c[3])
जोड़ रहा है a = b - c
vector_neg(a[3],b[3])
substracting हैनकारात्मक है
vector_ld(a[3],x,y,z)
सिर्फ a = (x,y,z)
pos
लोड कर रहा है अपने सर्कल तीर के केंद्र की स्थिति है और nor
विमान, जिसमें तीर झूठ का सामान्य है। bin
द्वि-सामान्य है और कोण इस धुरी से शुरू हो रहे हैं। nor
पर लंबवत होना चाहिए। r,r0,r1
तीर (मोड़, ट्यूब, शंकु)
रैखिक तीर समान dir
तीर की दिशा है की दायरों के हैं, l
तीर आकार है और al
तीर आकार है।
ने मेरे उत्तर – Spektre