2
높이 맵 데이터의 법선을 찾고 싶습니다. gl_triangles 내 코드에서 인덱스를 사용하고 있습니다. 이것에 대한 법선을 어떻게 찾을 수 있습니까?높이 맵 데이터의 법선
높이 맵 데이터의 법선을 찾고 싶습니다. gl_triangles 내 코드에서 인덱스를 사용하고 있습니다. 이것에 대한 법선을 어떻게 찾을 수 있습니까?높이 맵 데이터의 법선
주어진 삼각형 (vert1, vert2, vert3)
은 정상인 ((vert2 - vert1).cross(vert3 - vert1)).normalize()
입니다.
부드럽고 버텍스가 많은 법선의 경우 : Foreach 버텍스, 버텍스가 포함 된 각 삼각형의면 노멀을 합친 다음 합계를 정규화합니다.
편집 : 예 :
#include <GL/glut.h>
#include <vector>
#include <cmath>
#include <Eigen/Core>
#include <Eigen/Geometry>
using namespace std;
using namespace Eigen;
typedef Matrix< Vector3f, Dynamic, Dynamic > VecMat;
// given a matrix of heights returns a matrix of vertices
VecMat GetVerts(const MatrixXf& hm)
{
VecMat verts(hm.rows(), hm.cols());
for(int col = 0; col < hm.cols(); ++col)
for(int row = 0; row < hm.rows(); ++row)
verts(row, col) = Vector3f(col, row, hm(row, col));
return verts;
}
VecMat GetNormals(const VecMat& hm)
{
VecMat normals(hm);
for(int col = 0; col < hm.cols(); ++col)
for(int row = 0; row < hm.rows(); ++row)
{
Vector3f sum(Vector3f::Zero());
const Vector3f& cur = hm(row, col);
if(row+1 < hm.rows() && col+1 < hm.cols())
sum += (hm(row+0, col+1) - cur).cross(hm(row+1, col+0) - cur).normalized();
if(row+1 < hm.rows() && col > 0)
sum += (hm(row+1, col+0) - cur).cross(hm(row+0, col-1) - cur).normalized();
if(row > 0 && col > 0)
sum += (hm(row+0, col-1) - cur).cross(hm(row-1, col+0) - cur).normalized();
if(row > 0 && col+1 < hm.cols())
sum += (hm(row-1, col+0) - cur).cross(hm(row+0, col+1) - cur).normalized();
normals(row, col) = sum.normalized();
}
return normals;
}
// returns an index array for a GL_TRIANGLES heightmap
vector< unsigned int > GetIndices(int rows, int cols)
{
vector< unsigned int > indices;
for(int col = 1; col < cols; ++col)
for(int row = 1; row < rows; ++row)
{
// Eigen default storage order is column-major
// lower triangle
indices.push_back((col-1) * rows + (row-1));
indices.push_back((col-0) * rows + (row-1));
indices.push_back((col-1) * rows + (row-0));
// upper triangle
indices.push_back((col-1) * rows + (row-0));
indices.push_back((col-0) * rows + (row-1));
indices.push_back((col-0) * rows + (row-0));
}
return indices;
}
VecMat heightmap;
VecMat normals;
vector< unsigned int > indices;
void init()
{
// wavy heightmap
MatrixXf hm(64, 64);
for(int col = 1; col < hm.cols(); ++col)
for(int row = 1; row < hm.rows(); ++row)
{
float x = (col - (hm.cols()/2.0f))/2.0f;
float y = (row - (hm.rows()/2.0f))/2.0f;
hm(row, col) = cos(sqrt(x * x + y * y));
}
heightmap = GetVerts(hm);
heightmap.array() -= Vector3f(hm.cols()/2.0f, hm.rows()/2.0f, 0);
for(int col = 0; col < hm.cols(); ++col)
for(int row = 0; row < hm.rows(); ++row)
heightmap(row, col).array() *= Vector3f(1/4.0f, 1/4.0f, 1.0f).array();
normals = GetNormals(heightmap);
indices = GetIndices(heightmap.rows(), heightmap.cols());
}
void display()
{
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glShadeModel(GL_SMOOTH);
glEnable(GL_LIGHTING);
GLfloat global_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, global_ambient);
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
double w = glutGet(GLUT_WINDOW_WIDTH);
double h = glutGet(GLUT_WINDOW_HEIGHT);
gluPerspective(60, w/h, 1, 100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(8, 8, 8, 0, 0, 0, 0, 0, 1);
// spinning light
glEnable(GL_LIGHT0);
float angle = 20 * (glutGet(GLUT_ELAPSED_TIME)/1000.0f) * (3.14159f/180.0f);
float x = cos(-angle) * 6;
float y = sin(-angle) * 6;
GLfloat light_position[] = { x, y, 2, 1.0 };
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glDisable(GL_LIGHTING);
glPointSize(5);
glBegin(GL_POINTS);
glColor3ub(255, 255, 255);
glVertex3fv(light_position);
glEnd();
glEnable(GL_LIGHTING);
glColor3ub(255,0,0);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glVertexPointer(3, GL_FLOAT, sizeof(Vector3f), heightmap(0,0).data());
glNormalPointer(GL_FLOAT, sizeof(Vector3f), normals(0,0).data());
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, &indices[0]);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glutSwapBuffers();
}
void timer(int extra)
{
glutPostRedisplay();
glutTimerFunc(16, timer, 0);
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowSize(640, 480);
glutCreateWindow("Heightmap");
init();
glutDisplayFunc(display);
glutTimerFunc(0, timer, 0);
glutMainLoop();
return 0;
}