简体   繁体   中英

OpenGL/GLUT surface normals of cone

I created a cone with GL_TRIANGLE_FAN

// draw the upper part of the cone
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0, 0, height);
for (int angle = 0; angle < 360; angle++) {
    glVertex3f(sin(angle) * radius, cos(angle) * radius, 0);
}
glEnd();

// draw the base of the cone
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0, 0, 0);
for (int angle = 0; angle < 360; angle++) {
    // normal is just pointing down
    glNormal3f(0, -1, 0);
    glVertex3f(sin(angle) * radius, cos(angle) * radius, 0);
}
glEnd();

How do I get the surface normals? For the bottom am I right to say normal is just pointing down?

UPDATE

I tried using

for (int angle = 0; angle < 360; angle++) {
    glNormal3f(sin(angle), cos(angle), 0);
    glVertex3f(sin(angle) * radius, cos(angle) * radius, 0);
}

But it looks weird in some angles ...

在此输入图像描述

在此输入图像描述

2nd image looks like just 1 solid color?

Assuming your cone has height h and radius r and its as standing (say its tip points into +Y direction) the lateral face normal depends on two angles: the angle of the circular ground area and the angle of the cone's tip (lets call it cone angle or α). This cone angle in turn depends on the ratio of h and r .

Looking at the crossection of the cone we see basically a right angle triangle, whose one cathedus has length h and the other one r . Lets assume that the h cathetus goes straight up the Y axis from the origin and the r cathetus one does the same along the X axis. Now we want to calculate the normal of the hypothenuse point outwards.

角度校正和法线坐标

Doing some angle math on the triangle we can see that the normal of the hyponetuse has following form:

(cos(coneAngle), sin(coneAngle))

with

coneAngle = atan(r / h)

This is of course only in 2D and we need the 3D equivalent. At first we need the normal of a circle in the XZ plane. This can be written as

(cos(circleAngle), 0, sin(circleAngle))

And now we can combine these two to one normal equation. Our slope normal has a horizontal and a vertical part. The vertical part goes directly into the Y coordinate, while the horizontal part contributes to both horizontal direction (X and Z):

(cos(coneAngle) * cos(circleAngle), sin(coneAngle), cos(coneAngle) * sin(circleAngle))

Basically there are two vectors: The up vector which points to the tip of the cone and the horizontal vector, which is the one generated by the circle normal. These two vectors form a base and what I have done here is to apply a linear transformation from the XY 2D space (of the cone normal) into the space spanned by the circle normal and the up vector (Y axis). To do this transformation you multiply the components of the XY space vector with the respective base vectors of the other space and sum the result together, so you basically calculate:

cos(coneAngle) * (cos(circleAngle), 0, sin(circleAngle)) + sin(coneAngle) * (0, 1, 0)

Update

I just noticed that the two triangles in the hypothenuse normal image are similar, which means, that one can calculate the normal without trigonometric functions: Given the length of the hypothenuse c = sqrt(h * h + r * r) we know from the similarity of the triangles that:

n_x / 1 = n_x = h / c

and

n_y / 1 = n_y = r / c

Therefore, the hypothenuse normal is:

1/c * (h, r)

Incidentally, multiplying by the factor 1/c is a mere normalization of the vector (h, r) .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM