Tin*_*Zea 5 javascript geometry trigonometry three.js
如何在 Three.js 中弧形或弯曲圆柱体类型的几何体(有变形)?
我想指定这些参数:
我将用滑块控制它们。我的圆柱体形状是通过用户绘制的贝塞尔曲线的挤压创建的( Three.js 中几何类的扩展)。
我还希望能够将多个弯曲效果叠加在一起。因此,弯曲可能会影响第一个零件,然后第二个弯曲可能会使圆柱体向后弯曲。
我不是最擅长数学,所以这就是为什么我要求可以在 Three.js 中完成此操作的提示或公式。我想也许我可以在中心轴上放一条线,然后用贝塞尔曲线弯曲它。从那里我可以使用线位置来影响圆柱体的顶点。这听起来是个好主意吗?
您需要做的是将网格切成片,并以与我在此处处理圆圈相同的方式转换每个片:
这样做是这样的:
直形坐标系
创建位置P0和 3 个基向量,X0,Y0,Z0以直线形式表示网格的坐标。假设 是Z0您要弯曲的轴。
将每个顶点转换为P0,X0,Y0,Z0局部坐标
所以任意点P都会转化为:
P.x' = dot( P-P0 , X0 )
P.y' = dot( P-P0 , Y0 )
P.z' = dot( P-P0 , Z0 )
Run Code Online (Sandbox Code Playgroud)创建折弯形状坐标系P1,X1,Y1,Z1
因此,只需根据P.z'用作参数(弯曲形状上的弧长)计算弯曲弧的角度并旋转X0,Y0,Z0到,X1,Y1,Z1如果弯曲在X那时X1 = X0,您只需要旋转其他两个向量。
将 P' 转换为弯曲形式 P''
只需这样做:
P'' = P1 + P.x'*X1 + P.y'*Y1
Run Code Online (Sandbox Code Playgroud)
现在P''是形状的最终顶点。因此,您可以在转换网格的所有点后渲染网格。正如您所看到的,我们不需要P.z...,因为它P1已经编码在该位置中。因此也没有真正需要计算Z1基向量。
[笔记]
请注意,如果弯曲太大,太大的弯曲可能会破坏您的网格拓扑,然后您可以使切片彼此相交。
此外,所有相应的基向量理想单位应该具有相同的大小。
的旋转Y0 -> Y1是简单的二维问题,如果Y0=(0,1,0)它更简单,只需点在圆上Y1=(cos(a),sin(a),0)......所以你甚至不需要二维旋转公式。
[编辑1] C++/GL 示例
我很好奇,所以我拿了一个带有窦螺钉的生成管并将其弯曲......这就是结果:
我渲染了直网格和弯曲网格以进行视觉比较。红点是折弯中心,线将其连接到P0。我选择P0,X0,Y0,Z0匹配单位矩阵。该示例已转换,因此它与该问题中的图像匹配(处于非动画状态)。这是我使用的C++/GL代码:
网格和弯曲zavit.h:
P.x' = dot( P-P0 , X0 )
P.y' = dot( P-P0 , Y0 )
P.z' = dot( P-P0 , Z0 )
Run Code Online (Sandbox Code Playgroud)
以及主要的VCL应用程序代码(忽略VCL内容,只需移植/使用您需要的内容):
P'' = P1 + P.x'*X1 + P.y'*Y1
Run Code Online (Sandbox Code Playgroud)
对于OpenGL,我使用GLEW和我的gl_simple.h,可以在这里找到:
GLSL_math.h是我的模仿GLSL数学的矢量数学,但您可以使用任何矢量数学...您只需要这些都是基本操作,您也可以自己编码或使用GLM或其他...+,-,dot,cross,normalize,length
[Edit2] 一些更多的简化和可重复性
好吧,根据你的草图和后来的评论,它不适用于高度。相反,使用弧长(直线网格中的高度)作为参数。经过更多的教导后,我最终得到了这个:
为了简化事情,我为每个切片添加了中心点、主轴方向和切片长度。这使得计算变得更加简单......这里预览应用的 45 度弯曲两次(+45 和 -45):
RGB线是弯曲网格渲染的全局坐标系,黄色是网格中心轴+用于调试的最后弯曲的弯曲范围,红色是最后弯曲中心。
这里是新的 C++ 代码zavit.h:
//---------------------------------------------------------------------------
//--- tube with sinus screw -------------------------------------------------
//---------------------------------------------------------------------------
const int ca=20;
const int cb=50;
const float r0=0.3;
const float r1=0.35;
const float l1=2.0;
const float nz=5.0;
vec3 pnt0[ca][cb]; // straight mesh
vec3 nor0[ca][cb];
vec2 txr0[ca][cb];
//---------------------------------------------------------------------------
vec3 pnt1[ca][cb]; // bended mesh
vec3 nor1[ca][cb];
vec2 txr1[ca][cb];
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
void obj0_init() // sin screw
{
int i,j,i0,j0;
float a,b,l,da,db,dl,r,s,c,tx,ty;
float dtx=1.0/float(ca-1),dty=1.0/float(cb-1);
vec3 u,v;
// pnt,txr
da=2.0*M_PI/float(ca-1);
db=nz*2.0*M_PI/float(cb);
dl=l1/float(cb);
for (a=0.0,tx=0.0,i=0;i<ca;i++,a+=da,tx+=dtx)
{
s=sin(a);
c=cos(a);
for (l=-0.5*l1,b=0,ty=0.0,j=0;j<cb;j++,b+=db,l+=dl,ty+=dty)
{
r=r0+((r1-r0)*cos(a+b));
pnt0[i][j].x=r*c;
pnt0[i][j].y=r*s;
pnt0[i][j].z=l;
txr0[i][j].x=tx;
txr0[i][j].y=ty;
}
}
// nor
for (i0=ca-2,i=0;i<ca;i0=i,i++)
for (j0=cb-1,j=0;j<cb;j0=j,j++)
{
u=pnt0[i][j]-pnt0[i0][j];
v=pnt0[i][j]-pnt0[i][j0];
nor0[i][j]=normalize(cross(v,u));
}
}
//---------------------------------------------------------------------------
void obj1_bend(vec3 center) // bend obj0 -> obj1 ... pc center, P0,X0,Y0,Z0 = unit matrix
{
int i,j,i0,j0;
float a,r;
vec3 p,p1,x1,y1,u,v;
// bend pnt, copy txr
r=length(center);
for (i=0;i<ca;i++)
for (j=0;j<cb;j++)
{
p=pnt0[i][j]; // p' = p
a=p.z/r; // arc length -> angle [rad]
p1=center; // p1 point on circleYZ (bending around X)
p1.y-=r*cos(a);
p1.z-=r*sin(a);
x1=vec3(1.0,0.0,0.0); // basis vectors
y1=vec3(0.0,cos(a),sin(a));
p=p1+(p.x*x1)+(p.y*y1); // p''
pnt1[i][j]=p;
txr1[i][j]=txr0[i][j];
}
// nor
for (i0=ca-2,i=0;i<ca;i0=i,i++)
for (j0=cb-1,j=0;j<cb;j0=j,j++)
{
u=pnt1[i][j]-pnt1[i0][j];
v=pnt1[i][j]-pnt1[i][j0];
nor1[i][j]=normalize(cross(v,u));
}
}
//---------------------------------------------------------------------------
void obj0_draw()
{
int i,j;
glColor3f(1.0,1.0,1.0);
glEnable(GL_CULL_FACE);
glFrontFace(GL_CCW);
for (i=0;i<ca-1;i++)
{
glBegin(GL_QUAD_STRIP);
for (j=0;j<cb;j++)
{
glTexCoord2fv(txr0[i+1][j].dat);
glNormal3fv (nor0[i+1][j].dat);
glVertex3fv (pnt0[i+1][j].dat);
glTexCoord2fv(txr0[i ][j].dat);
glNormal3fv (nor0[i ][j].dat);
glVertex3fv (pnt0[i ][j].dat);
}
glEnd();
}
}
//---------------------------------------------------------------------------
void obj1_draw()
{
int i,j;
glColor3f(1.0,1.0,1.0);
glEnable(GL_CULL_FACE);
glFrontFace(GL_CCW);
for (i=0;i<ca-1;i++)
{
glBegin(GL_QUAD_STRIP);
for (j=0;j<cb;j++)
{
glTexCoord2fv(txr1[i+1][j].dat);
glNormal3fv (nor1[i+1][j].dat);
glVertex3fv (pnt1[i+1][j].dat);
glTexCoord2fv(txr1[i ][j].dat);
glNormal3fv (nor1[i ][j].dat);
glVertex3fv (pnt1[i ][j].dat);
}
glEnd();
}
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)
VCL窗口代码:
//---------------------------------------------------------------------------
#include <vcl.h>
#include <math.h>
#pragma hdrstop
#include "Unit1.h"
#include "gl_simple.h"
double divide(double a,double b){ if (fabs(b)<1e-10) return 0.0; return a/b; }
#include "GLSL_math.h"
#include "zavit.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
void gl_draw()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
float aspect=float(xs)/float(ys);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0/aspect,aspect,0.1,100.0);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0,0.0,-5.5);
glRotatef(-80.0,1.0,0.0,0.0); // Z+ up slightly forw
static float ang=0.0; ang+=5.0;
glRotatef(45.0+ang,0.0,0.0,1.0); // X+ right forw, Y+ left forw, + animation rotation around up
glEnable(GL_DEPTH_TEST);
glDisable(GL_TEXTURE_2D);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
// [original mesh]
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glTranslatef(-0.7,0.0,0.0);
glColor3f(1.0,1.0,1.0);
obj0_draw();
glPopMatrix();
// [bended mesh]
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glTranslatef(+0.7,0.0,0.0);
glColor3f(1.0,1.0,1.0);
obj1_draw();
// debug draws
int j;
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
// global coordinates
glBegin(GL_LINES);
glColor3f(1.0,0.0,0.0); glVertex3f(0.0,0.0,0.0); glVertex3f(1.0,0.0,0.0);
glColor3f(0.0,1.0,0.0); glVertex3f(0.0,0.0,0.0); glVertex3f(0.0,1.0,0.0);
glColor3f(0.0,0.0,1.0); glVertex3f(0.0,0.0,0.0); glVertex3f(0.0,0.0,1.0);
glEnd();
// mesh axis
glLineWidth(2.0); glColor3f(0.9,0.6,0.1); glBegin(GL_LINE_STRIP);
for (j=0;j<bend_j0;j++) glVertex3fv(mid1[j].dat); if (j<cb){ glVertex3fv(mid1[j].dat); glVertex3fv(bend_pc.dat); }
for ( ;j<bend_j1;j++) glVertex3fv(mid1[j].dat); if (j<cb){ glVertex3fv(mid1[j].dat); glVertex3fv(bend_pc.dat); }
for ( ;j<cb ;j++) glVertex3fv(mid1[j].dat);
glEnd(); glLineWidth(1.0);
// bending center
glColor3f(1.0,0.0,0.0);
glPointSize(10.0);
glBegin(GL_POINTS);
glVertex3fv(bend_pc.dat);
glEnd();
glPointSize(1.0);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glFlush();
SwapBuffers(hdc);
}
/
| 归档时间: |
|
| 查看次数: |
3113 次 |
| 最近记录: |