的立方体,使之按opengl旋转立方体后,怎么获取定点坐标

How to calculate x and y coordinates of a rotated 3D cube in JavaScript? [如何计算x和一个旋转的3D立方体中的JavaScript Y坐标?] - 问题-字节技术
How to calculate x and y coordinates of a rotated 3D cube in JavaScript?
如何计算x和一个旋转的3D立方体中的JavaScript Y坐标?
问题 (Question)
I am trying to make a cube in 3D, made out of all seperate, little div's. Lets say we have a cube of 3*3*3 div's. The things given about all of the div's:
X, Y, Z coordinate (of the 3D cube)
Rotation angle around the X and Y axis
This should technically be enough to calculate the 2D perspective projection of the cube.
The question now is: How can I calculate the X and Y coordinates of each div?
Ps. A similar example of such a cube is in this link: . The two things I don't like in this example are:
The way how the cube rotates. For example, if I push the mouse down, the cube rotates up. Also, for horizontal movement of the mouse the cube rotates always around the same axis, for vertical movement of the mouse the cube rotates relatively to the horizontal rotation.
The cube has only a "+" at the corners, I want a filled (massive) cube.
我试图在3D制作的立方体,做出来的所有独立的,小的div的。让我们说我们有一个立方体的3×3×3 DIV的。给出了所有的div的东西:X,Y,Z坐标(的3D立方体)旋转角度在X和Y轴这应该是足够的计算多维数据集的二维投影。现在的问题是:我如何计算x坐标每Y div诗一个类似的例子,这样一个立方体是这个链接:。这两件事我不太喜欢这个例子:如何立方体旋转。例如,如果我按了鼠标,立方体旋转。同时,对鼠标的立方体旋转总是在同一轴线的水平移动,鼠标的立方体相对于水平旋转垂直运动。立方体有只有一个“+”在角落,我想要一个填充(大量的)立方体。
最佳答案 (Best Answer)
I think there are two different answers to what you're asking: a direct answer to your question, and an answer to your problem:
To "How can I calculate the X and Y coord. of each div?"
Note - The following answer is a reformulation of a post I made for the thread . You can also chech the Wikipedia article "" for a more generic answer.
You will need a bit more information to execute you perspective projection, such as the position/orientation of your camera/eye, its angle of view, and the surface you want to project your cube on.
With all this, you should be able to loop on your div elements, then on their 4 corner vertices to apply your rotation transform and project each of them, to finally use the 2D coordinates you get to render the elements.
Applying the rotation
Let's simplify the situation. We have:
A vertex A(x_0, y_0, z_0), one of the corners of your div
θ and δ the angles defining the rotation you want to apply, resp. the pitch angle and the yaw angle ()
... and we want:
D(x,y,z), the position of our rotated element
Thus your linearized equations are:
x = sin(δ) * y_0 + cos(δ) * x_0
y = sin(θ) * z_0 + cos(θ) * (cos(δ) * y_0 - sin(δ) * x_0)
z = cos(θ) * z_0 i sin(θ) * (cos(δ) * y_0 - sin(δ) * x_0)
The projection - Intro
Now we have:
Our point D(x,y,z)
w * h, the dimension of the surface you want to project on (innerWidth * innerHeight for instance in your case)
... and we want:
The coordinates of B in the surface plane (let's call them X and Y)
A schema for the X-screen-coordinates:
E is the position of our "eye" in this configuration, which I chose as origin to simplify. If it is not the case and/or if you want to also rotate your camera, you'll need to apply again the corresponding translation and/or rotation transform(s) to D before the next steps.
The focal length f can be estimated knowing that:
tan(α) = (w/2) / f
A bit of Geometry
You can see on the picture that the triangles ECD and EBM are similar, so using the , we get:
MB / CD = EM / EC &=> X / x = f / z (2)
With both (1) and (2), we now have:
X = (x / z) * ( (w / 2) / tan(α) )
Note: Same reasoning for Y.
Practical Use
Some remarks:
Usually, α = 90deg is used, which means tan(α) = 1. That's why this term doesn't appear in many implementations.
If you want to preserve the ratio of the elements you display, keep f constant for both X and Y, ie instead of calculating:
X = (x / z) * ( (w / 2) / tan(α) ) and Y = (y / z) * ( (h / 2) / tan(α) )
X = (x / z) * ( size / 2) / tan(α) ) and Y = (y / z) * ( (size / 2) / tan(α) ) with size a constant value you defined (size = (min(w,h) or size = (w+h)/2 are often used for instance). It will only affect the focal, and thus the angle of view.
As you may have noticed on the picture above, the screen coordinates are here defined between [-w/2 ; w/2] for X and [-h/2 ; h/2] for Y, but you probably want
[0 ; w] and
[0 ; h] instead. X += w/2 and Y += h/2 - Problem solved.
To the problem of displaying a 3D cube made of div
As I see the situation, there is a flaw with the method described above. Sure you can get the 2D coordinates defining your rotated and projected div elements, but how can you use it to render them?.
Once projected, your div won't probably look rectangular anymore, making it hard to render using simple CSS, especially if your div elements contain complex stuff.
So if your real purpose is to display a 3D DOM cube, with rotations and perspective, I recommend you to use CSS3 3D transforms, letting the browser do the computations.
For instance, you'll find
a tutorial to implement such a cube with only HTML and CSS3.
The advantages are multiple:
You benefit of the browsers GPU acceleration, making it smoother than done using plain JS.
It affects the contents of your div (rotation, perpespective)
No maths to implement
You may only have to worry about the browsers compatibility of you aim for older versions ().
If you want to dynamically rotate your cube (for instance when the mouse moves), just use JS to edit your CSS transforms
I quickly made this , simply copying the implementation from the tutorial and adding an onmousemove handler to update the rotation.
Hope it helped, bye!
我认为有两个不同的答案,你的要求:一个直接回答你的问题,和回答你的问题:“我怎么能计算x和y坐标。每个div?”注意:下面的回答是一个重新后我为主线。你也可以检查维基百科的文章”“一个更通用的答案。你将需要更多的信息来执行你的透视投影,如你的位置/方向相机/眼睛,其视角,和面你想把立方体。所有这一切,你应该在你能循环div元素,然后对他们的4个角的顶点将你的旋转变换和项目的每个人,最后使用二维坐标可以渲染元素。应用旋转让我们简化局面。我们有:一个顶点(x_0,y_0,z_0),你的角落divθ和δ确定要应用的旋转角度,分别为。这个俯仰角和偏航角()…我们希望:D(x,y,z),我们的旋转元件的位置因此你的线性方程组:x = sin(δ) * y_0 + cos(δ) * x_0y = sin(θ) * z_0 + cos(θ) * (cos(δ) * y_0 - sin(δ) * x_0)z = cos(θ) * z_0 i sin(θ) * (cos(δ) * y_0 - sin(δ) * x_0)投影-简介现在我们有:我们的D点(x,y,z)W*H,你想项目表面上的尺寸(innerWidth*innerHeight例如,在你的情况下)一个 α…我们希望:在平面B的坐标(让我们称之为X和Y)一种x-screen-coordinates图式:E是我们的“眼睛”在这个位置,我选择的是起源简化。如果你想同时旋转相机这是没有的情况下,和/或,你需要重新申请相应的翻译和/或旋转变换(S)到下一步之前。焦距F估计可以知道:tan(α) = (w/2) / f (1)一点的几何你可以看到,三角形的图片ECD和循证医学是相似的,所以用,我们得到:MB / CD = EM / EC"&& =&& (2)两(1)和(2)现在,我们有:X / x = f / z 注:同一推理Y。实际使用一些评论:通常,α= 90度使用,这意味着X = (x / z) * ( (w / 2) / tan(α) )。这就是为什么这个词没有出现在许多实现。如果你想保留你的元素的显示率,保持F恒定的X和YIE,而不是计算:tan(α) = 1和X = (x / z) * ( (w / 2) / tan(α) )…做:Y = (y / z) * ( (h / 2) / tan(α) )和X = (x / z) * ( size / 2) / tan(α) )随着Y = (y / z) * ( (size / 2) / tan(α) )一个恒定值,你定义(size或size = (min(w,h)通常用于实例)。它只会影响的重点,因此视角。你可能已经注意到在上面的图片,屏幕坐标来定义之间【w / 2 W / 2 ];X和【-的H / 2小时/ 2 ];Y,但你可能想[ 0 ];W和【0小时】;而不是。size = (w+h)/2和X += w/2问题解决了。要显示的3D立方体的问题Y += h/2当我看到的情况,有一个与上述方法的缺陷。当然你可以定义你的二维坐标旋转投影div元素,但你怎么能用它来给他们?。你曾经预计,div不可能再看矩形,难以用简单的CSS渲染,特别是如果你的div元素包含复杂的东西。所以如果你真正的目的是显示一个三维的DOM立方体,旋转和角度,我推荐你使用CSS3的三维变换,让浏览器做计算。例如,你会发现教程来实现这样一个立方体只有HTML和CSS3。优点是多:你对浏览器GPU加速,使它比使用普通js平滑。它会影响你的内容div(旋转,perpespective)没有数学实施你可能只需要担心浏览器兼容旧版本(你的目标)。如果你想动态旋转你的立方体(例如当鼠标移动),只使用JS编辑你的CSS变换的例子我很快就让这简单的复制,实现从教程和加入div处理更新旋转。希望这帮助,再见!
本文翻译自StackoverFlow,英语好的童鞋可直接参考原文:OpenGl(4)
上学期帮舍友改了下的半成品,这次继续学习接着改。
记得老师有说过要注意啥啥按列存储的。
没搞明白,然后发现有的按行存储,甚是不解。
《交互式计算机图形学》这本书上注释着按列存储。
嗯,然后我以为电脑应该一样吧。但是左右上下平移发现怎么有是我按的那个方向的线变短,另一个方向的变长,反正就是正方形变成畸形的六面体了。
可能有的按行有的按列,我用的是vs2013社区版。按行存储
所以样例【其他旋转甚么的也是同理转置一下】
x方向平移athat,y方向平移direct。
t=mat4(1.0,0.0,0.0,0.0,
& & &&0.0,1.0,0.0,0.0,
& & &&0.0,0.0,1.0,0.0,
athat,direct,0.0,1.0);&
其他的按列存储
t=mat4(1.0,0.0,0.0,athat,,
& & &&0.0,1.0,0.0,direct,
& & &&0.0,0.0,1.0,0.0,
& &&&&0.0,0.0,0.0,1.0);&
【简单的说就是它们是互为转置矩阵,更通俗易懂就讲就是沿着 &\ &交换数值】
话说在vshader顶点着色器中&gl_Position =t*rx*rz*ry*sf*vP & &和 & gl_Position =rx*rz*ry*sf*t*vP弄出来的是不一样的哦。
搜罗很多资料,和我要的效果都不一样,然后我就改了一下,发现前者才是我要的效果。
我要的效果是按着世界坐标系上下左右平移旋转,而后者好像貌似是绕着对象坐标系上下左右平移旋转【目前个人感觉应该是这样吧】
整个工程&http://download.csdn.net/detail/u77261
工程里面和exe在同一目录的.glsl忘记更改了。
// 绘制一个旋转的OpenGL立方体在世界坐标系中_缩放_旋转_平移_顶点片源着色器
// 使用空闲回调函数增加旋转的角度
立方体的旋转角度被发送到用于实现立方体旋转的顶点着色器中
#include &Angel.h&
#pragma comment(lib, &glew32.lib&)
typedef Angel::vec4
typedef Angel::vec4
const int NumVertices = 36; //(6 faces)(2 triangles/face)(3 vertices/triangle)
point4 points[NumVertices];
// Vertices of a unit cube centered at origin, sides aligned with axes
point4 vertices[8] = {
point4(-0.5, -0.5, 0.5, 1.0),
point4(-0.5, 0.5, 0.5, 1.0),
point4(0.5, 0.5, 0.5, 1.0),
point4(0.5, -0.5, 0.5, 1.0),
point4(-0.5, -0.5, -0.5, 1.0),
point4(-0.5, 0.5, -0.5, 1.0),
point4(0.5, 0.5, -0.5, 1.0),
point4(0.5, -0.5, -0.5, 1.0)
color4 gr = color4(1.0, 1.0, 1.0, 1.0);
color4 onecolor = color4(1.0, 0.0, 1.0, 1.0);
Axi = 0;//X
Thet[3] = { 0.0, 0.0, 0.0 };
Atha[3] = { 0.0, 0.0, 0.0 };
GLfloat Disx = 0;
GLfloat Dis = 0;
GLfloat fd = 1;
// The location of the &theta& shader uniform variable
//----------------------------------------------------------------------------
// quad generates two triangles for each face and assigns colors
to the vertices
int Index = 0;
quad(int a, int b, int c, int d)
points[Index] = vertices[a]; Index++;
points[Index] = vertices[b]; Index++;
points[Index] = vertices[c]; Index++;
points[Index] = vertices[a]; Index++;
points[Index] = vertices[c]; Index++;
points[Index] = vertices[d]; Index++;
//----------------------------------------------------------------------------
// generate 12 triangles: 36 vertices
colorcube()
quad(1, 0, 3, 2);
quad(2, 3, 7, 6);
quad(3, 0, 4, 7);
quad(6, 5, 1, 2);
quad(4, 5, 6, 7);
quad(5, 4, 0, 1);
//----------------------------------------------------------------------------
// OpenGL initialization
colorcube();
// Create a vertex array object
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Create and initialize a buffer object
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(points),
NULL, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(points), points);
// Load shaders and use the resulting shader program
GLuint program = InitShader(&vshader.glsl&, &fshader.glsl&);
glUseProgram(program);
// set up vertex arrays
GLuint vPosition = glGetAttribLocation(program, &vPosition&);
glEnableVertexAttribArray(vPosition);
glVertexAttribPointer(vPosition, 4, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(0));
cc = glGetUniformLocation(program, &cc&);
thet = glGetUniformLocation(program, &theta&);
atha = glGetUniformLocation(program, &athat&);
direct = glGetUniformLocation(program, &direct&);
f = glGetUniformLocation(program, &ff&);
glEnable(GL_DEPTH_TEST);///开启深度缓存测试
glEnable(GL_CULL_FACE);///启动多边形剔除功能
//glOrtho(1.0, 0.0, 0.0, 1.0, 0.0, 1.0);
//----------------------------------------------------------------------------
display(void)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUniform3fv(thet, 1, Thet);
glUniform1f(atha, Disx);
glUniform1f(direct, Dis);//传递单个的
glUniform1f(f, fd);
glUniform4fv(cc, 1, onecolor);
glDrawArrays(GL_TRIANGLES, 0, NumVertices);
glClearColor(gr[0], gr[1], gr[2], gr[3]);
glFlush();
void ProcessMenu(int value)
if (value == 0)
if (value == 100)
gr = vec4(1.0f, 1.0f, 1.0f, 1.0f);
onecolor = vec4(1.0, 0.0, 1.0, 1.0);
switch (value)
case 21:gr = vec4(0.75f, 0.0f, 1.0f, 1.0f);
case 22:gr = vec4(0.75f, 0.75f, 1.0f, 1.0f);
case 23:gr = vec4(1.75f, 1.75f, 0.75f, 1.0f);
case 24:gr = vec4(1.75f, 1.0f, 1.55f, 1.0f);
case 25:gr = vec4(0.0f, 1.0f, 0.75f, 0.0f);
case 1:onecolor = vec4(0.0f, 0.0f, 0.0f, 1.0f);//黑色
case 2:onecolor = vec4(0.0f, 0.0f, 1.0f, 1.0f);//蓝色
case 3:onecolor = vec4(1.0f, 0.0f, 1.0f, 1.0f);//品红色
case 4:onecolor = vec4(0.0f, 1.0f, 1.0f, 1.0f);//青色
glutSwapBuffers();
glutPostRedisplay();
//----------------------------------------------------------------------------
keyboard(unsigned char key, int x, int y)
switch (key) {
case 'x':
Axi = 0; //X
case 'y':
Axi = 1;//Y
case 'z':
Axi = 2;//Z选择对应的x,y,z旋转角度来变化
case 'f':fd += 0.1;//X
case 's':fd -= 0.1;//Y
case 033: // Escape Key
case 'q': case 'Q':
exit(EXIT_SUCCESS);
if (fd == 0)fd = 0.1;
void SpecialKeys(int key, int x, int y)
switch (key) {
case GLUT_KEY_UP:Dis += 0.01;
case GLUT_KEY_DOWN:Dis -= 0.01;//Y
case GLUT_KEY_LEFT:Disx -= 0.01;
case GLUT_KEY_RIGHT:Disx += 0.01;//X
case 033: // Escape Key
case 'q': case 'Q':
exit(EXIT_SUCCESS);
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
idle(void)
Thet[Axi] += 0.01;
if (Thet[Axi] & 360.0) {
Thet[Axi] -= 360.0;
glutSwapBuffers();
glutPostRedisplay();
//----------------------------------------------------------------------------
main(int argc, char **argv)
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(512, 512);
glutInitContextVersion(3, 1);
//这里在舍友的电脑上用3,2可以用,在我的电脑上会出现
//freeglut(dll地址):unableto create OpenGL3.2 context(flags 0, profile 1)
//我改成3,1就可以了。不知道会不会是版本问题。这里用的是比较旧的版本freeglut。
glutInitContextProfile(GLUT_CORE_PROFILE);
glutCreateWindow(&Color Cube&);
glewExperimental =
glewInit();
int nGlutColorMenu1 = glutCreateMenu(ProcessMenu);
glutAddMenuEntry(&black&, 1);
glutAddMenuEntry(&blue&, 2);
glutAddMenuEntry(&magenta&, 3);
glutAddMenuEntry(&cyan&, 4);
int nGlutColorMenu2 = glutCreateMenu(ProcessMenu);
glutAddMenuEntry(&background1&, 21);
glutAddMenuEntry(&background2&, 22);
glutAddMenuEntry(&background3&, 23);
glutAddMenuEntry(&background4&, 24);
glutAddMenuEntry(&background5&, 25);
int nGlutColorMenu3 = glutCreateMenu(ProcessMenu);
glutAddMenuEntry(&return&, 100);
int nGlutColorMenu = glutCreateMenu(ProcessMenu);
glutAddSubMenu(&coclor&, nGlutColorMenu1);
glutAddSubMenu(&background&, nGlutColorMenu2);
glutAddSubMenu(&return&, nGlutColorMenu3);
glutAttachMenu(GLUT_RIGHT_BUTTON);
glutDisplayFunc(display);
glutSpecialFunc(SpecialKeys);
glutKeyboardFunc(keyboard);
//glutMouseFunc(mouse);
glutIdleFunc(idle);
glutMainLoop();
vshader.glsl
#version 150
uniform vec4
uniform vec3
void main()
// Compute the sines and cosines of theta for each of
the three axes in one computation.
vec3 angles = radians( theta );
vec3 c = cos( angles );
vec3 s = sin( angles );
// Remeber: thse matrices are column-major
mat4 rx = mat4( 1.0,
0.0, -s.x,
0.0, 1.0 );
mat4 ry = mat4( c.y, 0.0, -s.y, 0.0,
0.0, 1.0 );
// Workaround for bug in ATI driver
ry[1][0] = 0.0;
ry[1][1] = 1.0;
mat4 rz = mat4( c.z, s.z, 0.0, 0.0,
c.z, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0 );
// Workaround for bug in ATI driver
rz[2][2] = 1.0;
//color = vC
mat4 t=mat4(1.0,0.0,0.0,0.0,
0.0,1.0,0.0,0.0,
0.0,0.0,1.0,0.0,
athat,direct,0.0,1.0);
mat4 sf=mat4(ff,0.0,0,0,
0.0,ff,0.0,0.0,
0.0,0.0,ff,0.0,
0.0,0.0,0.0,1.0);
gl_Position =t*rx*rz*ry*sf*vP
fshader.glsl
#version 150
out vec4 fC
void main()
InitShader.cpp & & & & &
#include &Angel.h&
namespace Angel {
// Create a NULL-terminated string by reading the provided file
static char*
readShaderSource(const char* shaderFile)
//FILE* fp = fopen(shaderFile, &r&);
//由于vs甚么安全性的原因,不让使用fopen,用下面的fopen_s代替;
fopen_s(&fp, shaderFile, &r&);
if ( fp == NULL ) { return NULL; }
fseek(fp, 0L, SEEK_END);
long size = ftell(fp);
fseek(fp, 0L, SEEK_SET);
char* buf = new char[size + 1];
fread(buf, 1, size, fp);
buf[size] = '\0';
fclose(fp);
// Create a GLSL program object from vertex and fragment shader files
InitShader(const char* vShaderFile, const char* fShaderFile)
struct Shader {
const char*
shaders[2] = {
{ vShaderFile, GL_VERTEX_SHADER, NULL },
{ fShaderFile, GL_FRAGMENT_SHADER, NULL }
GLuint program = glCreateProgram();
for ( int i = 0; i & 2; ++i ) {
Shader& s = shaders[i];
s.source = readShaderSource( s.filename );
if ( shaders[i].source == NULL ) {
std::cerr && &Failed to read & && s.filename && std::
exit( EXIT_FAILURE );
GLuint shader = glCreateShader( s.type );
glShaderSource( shader, 1, (const GLchar**) &s.source, NULL );
glCompileShader( shader );
glGetShaderiv( shader, GL_COMPILE_STATUS, &compiled );
if ( !compiled ) {
std::cerr && s.filename && & failed to compile:& && std::
glGetShaderiv( shader, GL_INFO_LOG_LENGTH, &logSize );
char* logMsg = new char[logSize];
glGetShaderInfoLog( shader, logSize, NULL, logMsg );
std::cerr && logMsg && std::
delete [] logM
exit( EXIT_FAILURE );
delete [] s.
glAttachShader( program, shader );
and error check */
glLinkProgram(program);
glGetProgramiv( program, GL_LINK_STATUS, &linked );
if ( !linked ) {
std::cerr && &Shader program failed to link& && std::
glGetProgramiv( program, GL_INFO_LOG_LENGTH, &logSize);
char* logMsg = new char[logSize];
glGetProgramInfoLog( program, logSize, NULL, logMsg );
std::cerr && logMsg && std::
delete [] logM
exit( EXIT_FAILURE );
/* use program object */
glUseProgram(program);
// Close namespace Angel block
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:37148次
积分:2027
积分:2027
排名:第15280名
原创:167篇
(5)(8)(4)(11)(6)(9)(3)(3)(8)(3)(2)(2)(7)(67)(32)(2)(1)}

我要回帖

更多关于 keynote旋转立方体 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信