- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
如标题所述:我想创建一个 3D 齿轮,它有 10 个齿,围绕其中心旋转(就像齿轮一样)。齿轮有方形齿,为了简单起见,齿间有平坦的侧面 - 这个齿轮上没有曲线。
齿轮一侧的可视化效果。请注意,角度并非 100% 完美。
如上图所示,每个嵌齿轮齿都必须是 8 边多边形,而齿之间的每一边都必须是 4 边多边形。然而,现在, dentry 绘图会执行以下操作:
s
缩放,并使用 0
或 0.5
作为顶点坐标)。完全可重现的例子:
import java.awt.Dimension;
import javax.swing.JFrame;
import com.jogamp.opengl.GL;
import com.jogamp.opengl.GL2;
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.awt.GLJPanel;
import com.jogamp.opengl.glu.GLU;
import com.jogamp.opengl.util.FPSAnimator;
public class SpinCog3D implements GLEventListener {
JFrame jf;
GLJPanel gljpanel;
Dimension dim = new Dimension(800, 600);
FPSAnimator animator;
float rotation;
float speed;
// set up the OpenGL Panel within a JFrame
public SpinCog3D() {
jf = new JFrame();
gljpanel = new GLJPanel();
gljpanel.addGLEventListener(this);
gljpanel.requestFocusInWindow();
jf.getContentPane().add(gljpanel);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setVisible(true);
jf.setPreferredSize(dim);
jf.pack();
animator = new FPSAnimator(gljpanel, 20);
rotation = 0.0f;
speed = 0.1f;
animator.start();
}
public static void main(String[] args) {
new SpinCog3D();
}
public void init(GLAutoDrawable dr) {
GL2 gl2 = dr.getGL().getGL2();
GLU glu = new GLU();
gl2.glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
gl2.glEnable(GL2.GL_DEPTH_TEST);
gl2.glMatrixMode(GL2.GL_PROJECTION);
gl2.glLoadIdentity();
glu.gluPerspective(60.0, 1.0, 100.0, 800.0);
}
public void display(GLAutoDrawable dr) {
GL2 gl2 = dr.getGL().getGL2();
GLU glu = new GLU();
gl2.glMatrixMode(GL2.GL_MODELVIEW);
gl2.glLoadIdentity();
glu.gluLookAt(0.0, 200.0, 500.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
gl2.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
// Draw 1 Cog Tooth + 1 Side
drawTooth(gl2, 100.0, 1.0f, 0.0f, 0.0f, 0.0, 0.0, 1.0, 0.0, 0);
drawSide(gl2, 100.0, 0.0f, 1.0f, 0.0f, 0.0, 0.0, 1.0, 0.0, 10);
// Draw Floor
sideRotatedColorScaledFloor(gl2, 300.0, 0.0f, 0.0f, 0.0f, 90.0, 1.0, 0.0, 0.0, 0.0);
gl2.glFlush();
rotation += speed;
if (rotation > 360.9f)
rotation = 0.0f;
}
// draw a single side with a set color and orientation
private void drawTooth(GL2 gl2, double s, float r, float g, float b, double a, double ax, double ay,
double az, double zoffset) {
gl2.glPushMatrix();
gl2.glRotated(a, ax, ay, az);
gl2.glColor3f(r, g, b);
gl2.glTranslated(0.0, 0.0, zoffset);
gl2.glScaled(s, s, s);
tooth(gl2);
gl2.glPopMatrix();
}
private void drawSide(GL2 gl2, double s, float r, float g, float b, double a, double ax, double ay,
double az, double zoffset) {
gl2.glPushMatrix();
gl2.glRotated(a, ax, ay, az);
gl2.glColor3f(r, g, b);
gl2.glTranslated(0.0, 0.0, zoffset);
gl2.glScaled(s, s, s);
side(gl2);
gl2.glPopMatrix();
}
private void sideRotatedColorScaledFloor(GL2 gl2, double s, float r, float g, float b, double a, double ax, double ay,
double az, double zoffset) {
gl2.glPushMatrix();
gl2.glRotated(a, ax, ay, az);
gl2.glColor3f(r, g, b);
gl2.glTranslated(0.0, 0.0, zoffset);
gl2.glScaled(s, s, s);
side(gl2);
gl2.glPopMatrix();
}
private void tooth(GL2 gl2) {
gl2.glBegin(GL2.GL_POLYGON);
gl2.glVertex3d(-0.5, -0.5, 0.0);
gl2.glVertex3d(-0.5, 0.5, 0.0);
gl2.glVertex3d(0.5, 0.5, 0.0);
gl2.glVertex3d(0.5, -0.5, 0.0);
gl2.glVertex3d(-0.5, -0.5, 0.5);
gl2.glVertex3d(-0.5, 0.5, 0.5);
gl2.glVertex3d(0.5, 0.5, 0.5);
gl2.glVertex3d(0.5, -0.5, 0.5);
gl2.glEnd();
}
private void side(GL2 gl2) {
gl2.glBegin(GL2.GL_POLYGON);
gl2.glVertex3d(-0.5, -0.5, 0.0);
gl2.glVertex3d(-0.5, 0.5, 0.0);
gl2.glVertex3d(0.5, 0.5, 0.0);
gl2.glVertex3d(0.5, -0.5, 0.0);
gl2.glEnd();
}
}
是的,我知道 glBegin()
和 glEnd()
已经被弃用了,但这不是重点。如何让我的 dentry 正确拔牙并正确对齐两侧?
最佳答案
tooth drawing does all sorts of weird things...
不是一个很好的问题描述。我敢打赌你的网格有很多间隙和重叠,因为你使用的是硬编码形状,没有对 Cog 的实际尺寸进行任何修正。比如必须有多大的 dentry 才能让它们中的 n
正好覆盖整个圆...
如何改用参数圆方程?
这会摆脱矩阵困惑,我认为会更简单。
所以我会简单地将齿轮分成三角形切片,每个切片都有很少的边缘点。因此,将它们与 QUAD
连接起来,并将其放入 for
循环中执行所有切片。
我不使用 JAVA 编写代码,但这里使用旧的 GL api 和没有花哨的 C++ 东西的小 C++ 示例,因此您应该能够轻松地移植它:
void glCog(float r0,float r1,float r2,float w,int n) // shaft/inner/outer radiuses, width, tooths
{
int i;
float a,da,x,y,c,s;
float p[6][3],q[6][3]; // slice points
// set z for slice points
a=-0.5*w; for (i=0;i<3;i++){ p[i][2]=a; q[i][2]=a; }
a=+0.5*w; for (i=3;i<6;i++){ p[i][2]=a; q[i][2]=a; }
// init first slice
q[0][0]= r0; q[5][0]= r0;
q[0][1]=0.0; q[5][1]=0.0;
q[1][0]= r1; q[4][0]= r1;
q[1][1]=0.0; q[4][1]=0.0;
q[2][0]= r2; q[3][0]= r2;
q[2][1]=0.0; q[3][1]=0.0;
// divide circle to 2*n slices
da=2.0*M_PI/float(4*n);
glBegin(GL_QUADS);
for (a=0.0,i=0;i<=n;i++)
{
// points on circles at angle a
c=cos(a); s=sin(a); a+=da;
x=r0*c; y=r0*s; p[0][0]=x; p[5][0]=x;
p[0][1]=y; p[5][1]=y;
x=r1*c; y=r1*s; p[1][0]=x; p[4][0]=x;
p[1][1]=y; p[4][1]=y;
x=r2*c; y=r2*s; p[2][0]=x; p[3][0]=x;
p[2][1]=y; p[3][1]=y;
// render tooth
c=cos(a); s=sin(a); a+=da;
glNormal3f(0.0,0.0,-1.0); // -Z base
glVertex3fv(p[0]);
glVertex3fv(p[2]);
glVertex3fv(q[2]);
glVertex3fv(q[0]);
glNormal3f(0.0,0.0,+1.0); // +Z base
glVertex3fv(p[3]);
glVertex3fv(p[5]);
glVertex3fv(q[5]);
glVertex3fv(q[3]);
glNormal3f(-c,-s,0.0); // shaft circumference side
glVertex3fv(p[5]);
glVertex3fv(p[0]);
glVertex3fv(q[0]);
glVertex3fv(q[5]);
glNormal3f(c,s,0.0); // outter circumference side
glVertex3fv(p[2]);
glVertex3fv(p[3]);
glVertex3fv(q[3]);
glVertex3fv(q[2]);
glNormal3f(-s,c,0.0);
glVertex3fv(p[4]);
glVertex3fv(p[3]);
glVertex3fv(p[2]);
glVertex3fv(p[1]);
glNormal3f(s,-c,0.0);
glVertex3fv(q[1]);
glVertex3fv(q[2]);
glVertex3fv(q[3]);
glVertex3fv(q[4]);
// points on circles at angle a
c=cos(a); s=sin(a); a+=da;
x=r0*c; y=r0*s; q[0][0]=x; q[5][0]=x;
q[0][1]=y; q[5][1]=y;
x=r1*c; y=r1*s; q[1][0]=x; q[4][0]=x;
q[1][1]=y; q[4][1]=y;
x=r2*c; y=r2*s; q[2][0]=x; q[3][0]=x;
q[2][1]=y; q[3][1]=y;
// render gap
c=cos(a); s=sin(a); a+=da;
glNormal3f(0.0,0.0,-1.0); // -Z base
glVertex3fv(q[0]);
glVertex3fv(q[1]);
glVertex3fv(p[1]);
glVertex3fv(p[0]);
glNormal3f(0.0,0.0,+1.0); // +Z base
glVertex3fv(q[4]);
glVertex3fv(q[5]);
glVertex3fv(p[5]);
glVertex3fv(p[4]);
glNormal3f(-c,-s,0.0); // shaft circumference side
glVertex3fv(q[5]);
glVertex3fv(q[0]);
glVertex3fv(p[0]);
glVertex3fv(p[5]);
glNormal3f(c,s,0.0); // outter circumference side
glVertex3fv(q[1]);
glVertex3fv(q[4]);
glVertex3fv(p[4]);
glVertex3fv(p[1]);
}
glEnd();
}
这里是 glCog(0.1,0.5,0.6,0.1,10);
的预览:
这里是 glCog(0.2,0.5,0.52,0.2,50);
的预览:
但是请注意, dentry 并不是完全矩形的。齿数越少误差越大。如果你想要完全矩形的 dentry ,你需要平移最外面的点而不是旋转(或校正它们计算的角度)
使用翻译来解决这个问题:
void glCog(float r0,float r1,float r2,float w,int n) // shaft/inner/outer radiuses, width, tooths
{
int i,j;
float a,da,dr,x,y,c,s;
float p[6][3],q[6][3]; // slice points
// divide circle to 2*n slices
da=2.0*M_PI/float(4*n);
dr=r2-r1;
// set z for slice points
a=-0.5*w; for (i=0;i<3;i++){ p[i][2]=a; q[i][2]=a; }
a=+0.5*w; for (i=3;i<6;i++){ p[i][2]=a; q[i][2]=a; }
// init first slice
q[0][0]= r0; q[5][0]= r0;
q[0][1]=0.0; q[5][1]=0.0;
q[1][0]= r1; q[4][0]= r1;
q[1][1]=0.0; q[4][1]=0.0;
x=r1+dr*cos(-da); y=dr*sin(-da);
q[2][0]= x; q[3][0]= x;
q[2][1]= y; q[3][1]= y;
glBegin(GL_QUADS);
for (a=0.0,i=0;i<=n;i++)
{
// points on circles at angle a
c=cos(a); s=sin(a);
x=r0*c; y=r0*s; p[0][0]=x; p[5][0]=x;
p[0][1]=y; p[5][1]=y;
x=r1*c; y=r1*s; p[1][0]=x; p[4][0]=x;
p[1][1]=y; p[4][1]=y;
c=cos(a-da); s=sin(a-da); a+=da;
x+=dr*c;y+=dr*s;p[2][0]=x; p[3][0]=x;
p[2][1]=y; p[3][1]=y;
c=cos(a); s=sin(a); a+=da;
// render tooth
glNormal3f(0.0,0.0,-1.0); // -Z base
glVertex3fv(p[0]);
glVertex3fv(p[1]);
glVertex3fv(q[1]);
glVertex3fv(q[0]);
glVertex3fv(p[1]);
glVertex3fv(p[2]);
glVertex3fv(q[2]);
glVertex3fv(q[1]);
glNormal3f(0.0,0.0,+1.0); // +Z base
glVertex3fv(p[3]);
glVertex3fv(p[4]);
glVertex3fv(q[4]);
glVertex3fv(q[3]);
glVertex3fv(p[4]);
glVertex3fv(p[5]);
glVertex3fv(q[5]);
glVertex3fv(q[4]);
glNormal3f(-c,-s,0.0); // shaft circumference side
glVertex3fv(p[5]);
glVertex3fv(p[0]);
glVertex3fv(q[0]);
glVertex3fv(q[5]);
glNormal3f(c,s,0.0); // outter circumference side
glVertex3fv(p[2]);
glVertex3fv(p[3]);
glVertex3fv(q[3]);
glVertex3fv(q[2]);
glNormal3f(-s,c,0.0);
glVertex3fv(p[4]);
glVertex3fv(p[3]);
glVertex3fv(p[2]);
glVertex3fv(p[1]);
glNormal3f(s,-c,0.0);
glVertex3fv(q[1]);
glVertex3fv(q[2]);
glVertex3fv(q[3]);
glVertex3fv(q[4]);
// points on circles at angle a
c=cos(a); s=sin(a);;
x=r0*c; y=r0*s; q[0][0]=x; q[5][0]=x;
q[0][1]=y; q[5][1]=y;
x=r1*c; y=r1*s; q[1][0]=x; q[4][0]=x;
q[1][1]=y; q[4][1]=y;
c=cos(a+da); s=sin(a+da); a+=da;
x+=dr*c;y+=dr*s;q[2][0]=x; q[3][0]=x;
q[2][1]=y; q[3][1]=y;
c=cos(a); s=sin(a); a+=da;
// render gap
glNormal3f(0.0,0.0,-1.0); // -Z base
glVertex3fv(q[0]);
glVertex3fv(q[1]);
glVertex3fv(p[1]);
glVertex3fv(p[0]);
glNormal3f(0.0,0.0,+1.0); // +Z base
glVertex3fv(q[4]);
glVertex3fv(q[5]);
glVertex3fv(p[5]);
glVertex3fv(p[4]);
glNormal3f(-c,-s,0.0); // shaft circumference side
glVertex3fv(q[5]);
glVertex3fv(q[0]);
glVertex3fv(p[0]);
glVertex3fv(p[5]);
glNormal3f(c,s,0.0); // outter circumference side
glVertex3fv(q[1]);
glVertex3fv(q[4]);
glVertex3fv(p[4]);
glVertex3fv(p[1]);
}
glEnd();
}
所以只是点 p[2],q[2],p[3],q[3]
略有变化,基端必须用更多的 QUADS 来补偿 ...
这里是 glCog(0.2,0.5,0.6,0.2,10);
的预览:
关于java - 在 OpenGL 中绘制绕 Y 轴旋转的 Cog,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57918291/
在 OpenGL/ES 中,在实现渲染到纹理功能时,您必须小心,不要引起反馈循环(从正在写入的同一纹理中读取像素)。由于显而易见的原因,当您读取和写入纹理的相同像素时,行为是未定义的。但是,如果您正在
正如我们最终都知道的那样,规范是一回事,实现是另一回事。大多数错误是我们自己造成的,但有时情况并非如此。 我相信列出以下内容会很有用: GPU 驱动程序中当前已知的与最新版本的 OpenGL 和 GL
很难说出这里问的是什么。这个问题是模棱两可的、模糊的、不完整的、过于宽泛的或修辞的,无法以目前的形式得到合理的回答。为了帮助澄清这个问题以便可以重新打开它,visit the help center
我正在学习 OpenGL,非常想知道与显卡的交互如何。 我觉得了解它是如何在图形驱动程序中实现的,会让我了解 opengl 的完整内部结构(通过这个我可以知道哪些阶段/因素影响我对 opengl 性能
我正在尝试绘制到大于屏幕尺寸(即 320x480)的渲染缓冲区 (512x512)。 执行 glReadPixels 后,图像看起来是正确的,除非图像的尺寸超过屏幕尺寸——在本例中,超过 320 水平
我正在 Windows 中制作一个 3D 小行星游戏(使用 OpenGL 和 GLUT),您可以在其中穿过一堆障碍物在太空中移动并生存下来。我正在寻找一种方法来针对无聊的 bg 颜色选项设置图像背景。
如果我想要一个包含 100 个 10*10 像素 Sprite 的 Sprite 表,是否可以将它们全部排成一排来制作 1,000*10 像素纹理?还是 GPU 对不那么窄的纹理表现更好?这对性能有什
这个问题在这里已经有了答案: Rendering 2D sprites in a 3D world? (7 个答案) 关闭 6 年前。 我如何概念化让图像始终面对相机。我尝试将三角函数与 arcta
是否可以在 OpenGL 中增加缓冲区? 假设我想使用实例化渲染。每次在世界上生成一个新对象时,我都必须用实例化数据更新缓冲区。 在这种情况下,我有一个 3 个 float 的缓冲区 std::v
有人可以向我解释为什么下面的代码没有绘制任何东西,但如果我使用 GL_LINE_LOOP 它确实形成了一个闭环吗? glBegin(GL_POLYGON); for(int i = 0; i <= N
正如标题所说,OpenGL 中的渲染目标是什么?我对 OpenGL 很陌生,我看到的所有网站都让我很困惑。 它只是一个缓冲区,我在其中放置稍后将用于渲染的东西吗? 如果您能提供一个很好的引用来阅读它,
当使用 OpenGL 1.4 固定功能多纹理时,每个纹理阶段的输出在传递到下一个阶段之前是否都固定在 [0, 1]? spec说(第 153 页): If the value of TEXTURE_E
我比较了 2 个函数 openGL ES 和 openGL gvec4 texelFetchOffset(gsampler2DArray sampler, ivec3 P, int lod, ivec
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 10 年前。 Improve thi
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?将问题更新为 on-topic对于堆栈溢出。 6年前关闭。 Improve this qu
那么当你调用opengl函数时,比如glDraw或者gLBufferData,是否会导致程序线程停止等待GL完成调用呢? 如果不是,那么 GL 如何处理调用像 glDraw 这样的重要函数,然后立即更
我正在尝试实现级联阴影贴图,当我想访问我的视锥体的每个分区的相应深度纹理时,我遇到了一个错误。 更具体地说,当我想选择正确的阴影纹理时会出现我的问题,如果我尝试下面的代码,我会得到一个像 this 中
我想为OpenGL ES和OpenGL(Windows)使用相同的着色器源。为此,我想定义自定义数据类型并仅使用OpenGL ES函数。 一种方法是定义: #define highp #define
我尝试用 6 个位图映射立方体以实现天空盒效果。我的问题是一个纹理映射到立方体的每个面。我已经检查了 gDEBugger,在立方体纹理内存中我只有一个 图像(因为我尝试加载六个图像)。 代码准备纹理:
在 OpenGL 中偏移深度的最佳方法是什么?我目前每个多边形都有索引顶点属性,我将其传递给 OpenGL 中的顶点着色器。我的目标是在深度上偏移多边形,其中最高索引始终位于较低索引的前面。我目前有这
我是一名优秀的程序员,十分优秀!