Hi,
This code uses interpolation to map a nurbs surface to the 3d model/point cloud, once compiled the controls are.
i - increase the values of the central points on the nurbs surface
d - decrease the values of the control points on the nurbs surface
g - Start Interpolation of the nurbs surface
c - Show the control points used to make up the surface (also shows the points in the point cloud of the model
This code is using a different method to the one we have used before and it appears to have a better effect, however this code makes a nurbs surface that has only 16 control points this leads to the lack of detail that you see in the compiled program, a possible solution to this would be to increase the number of control points in the nurbs surface without increasing the size of the surface, anyhow have a look and see what you think feel free to make changes where necessary and repost them here. Check that it compiles before posting though please.
- Code: Select all
#include <stdlib.h>
#include <stdio.h>
#include <GL/glut.h>
#include "glm/glm.h"
#ifndef CALLBACK
#define CALLBACK
#endif
GLfloat ctlpoints[8][8][3];
int showPoints = 0;
int add = 0;
int side = 0;
struct vertex {
GLfloat x;
GLfloat y;
GLfloat z;
};
GLUnurbsObj *theNurb;
GLMmodel* model = NULL;
vertex* Orderedvertices;
/*
* Initializes the control points of the surface to a small hill.
* The control points range from -3 to +3 in x, y, and z
*/
void init_surface(void)
{
int u, v;
for (u = 0; u < 8; u++) {
for (v = 0; v < 8; v++) {
ctlpoints[u][v][0] = (0.28*((GLfloat)u - 1.0))-0.75;
ctlpoints[u][v][1] = (0.28*((GLfloat)v - 1.0))-0.75;
if ( (u == 1 || u == 2) && (v == 1 || v == 2))
ctlpoints[u][v][2] = 0.1;
else
ctlpoints[u][v][2] = 0.1;
}
}
if (!model)
{
// this is the call that actualy reads the OBJ and creates the model object
model = glmReadOBJ("face2.obj");
if (!model) exit(0);
// This will rescale the object to fit into the unity matrix
// Depending on your project you might want to keep the original size and positions you had in 3DS Max or GMAX so you may have to comment this.
glmUnitize(model);
// These 2 functions calculate triangle and vertex normals from the geometry data.
// To be honest I had some problem with very complex models that didn't look to good because of how vertex normals were calculated
// So if you can export these directly from you modeling tool do it and comment these line
// 3DS Max can calculate these for you and GLM is perfectly capable of loading them
glmFacetNormals(model);
glmVertexNormals(model, 90.0);
//glmLinearTexture(model);
//GLfloat* twidth = &model->textures->width;
//GLfloat* theight = &model->textures->height;
//glmLoadTexture("textura_paralelipied.tga", false, false, false, false, twidth, theight);
}
Orderedvertices =(vertex*)malloc(sizeof(vertex) * (model->numvertices + 1));
for(int i = 0; i<model->numvertices; i++){
Orderedvertices[i].x = model->vertices[i*3];
Orderedvertices[i].y = model->vertices[i*3+1];
Orderedvertices[i].z = model->vertices[i*3+2];
}
/*for(int i = 0; i<50; i++){
points[i].x = 1.5*((GLfloat)i - 1.0);
points[i].y = 1.5*((GLfloat)i - 1.0);
points[i].z = i;
}*/
}
void Interpolate(){
int u, v;
GLfloat xc = 0, yc = 0, sx = 10000, sy = 10000, psz = 0,sz = 0;
for (u = 0; u < 8; u++) {
for (v = 0; v < 8; v++) {
for(int i = 0; i<model->numvertices; i++){
xc = Orderedvertices[i].x - ctlpoints[u][v][0];
yc = Orderedvertices[i].y - ctlpoints[u][v][1];
if(xc < 0)
xc = xc *-1;
if(yc < 0)
yc = yc *-1;
if(xc < 0.03 && yc < 0.03)
if(xc < sx && yc < sy){
sx = xc;
sy = yc;
if(Orderedvertices[i].z !=0)
sz = Orderedvertices[i].z;
printf("New Y = %f, X = %f", sy, sx);
//printf("New Z = %f\n", Orderedvertices[i].z);
//printf("New Yc = %d, Xc = %d\n", xc, yc);
}
}
if(sz < 0)
sz = sz *-1;
ctlpoints[u][v][2] = sz;
if(psz!=sz)
printf("New Z = %f\n", sz);
sx = 10000;
sy = 10000;
psz = sz;
}
}
}
void MoveCtlPoints(){
int u, v;
for (u = 0; u < 8; u++) {
for (v = 0; v < 8; v++) {
ctlpoints[u][v][0] = 2.0*((GLfloat)u - 1.0);
ctlpoints[u][v][1] = (side+2)*((GLfloat)v - 2.0);
if ( (u == 1 || u == 2) && (v == 1 || v == 2))
ctlpoints[u][v][2] = add;
else
ctlpoints[u][v][2] = -add;
}
}
}
void CALLBACK nurbsError(GLenum errorCode)
{
const GLubyte *estring;
estring = gluErrorString(errorCode);
fprintf (stderr, "Nurbs Error: %s\n", estring);
exit (0);
}
/* Initialize material property and depth buffer.
*/
void init(void)
{
GLfloat mat_diffuse[] = { 0.7, 0.7, 0.7, 1.0 };
GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat mat_shininess[] = { 100.0 };
glClearColor (0.0, 0.0, 0.0, 0.0);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_AUTO_NORMAL);
glEnable(GL_NORMALIZE);
init_surface();
theNurb = gluNewNurbsRenderer();
gluNurbsProperty(theNurb, GLU_SAMPLING_TOLERANCE, 25.0);
gluNurbsProperty(theNurb, GLU_DISPLAY_MODE, GLU_FILL);
gluNurbsCallback(theNurb, GLU_ERROR,
(GLvoid (__stdcall *) ())nurbsError);
}
void display(void)
{
GLfloat knots[16] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0 , 1.0, 1.0, 1.0, 1.0};
int i, j;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glRotatef(330.0, 1.,0.,0.);
glScalef (0.5, 0.5, 0.5);
gluBeginSurface(theNurb);
gluNurbsSurface(theNurb,
16, knots, 16, knots,
8 * 3, 3, &ctlpoints[0][0][0],
8, 8, GL_MAP2_VERTEX_3);
gluEndSurface(theNurb);
if (showPoints) {
glPointSize(5.0);
glDisable(GL_LIGHTING);
glColor3f(1.0, 1.0, 0.0);
glBegin(GL_POINTS);
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
glVertex3f(ctlpoints[i][j][0],
ctlpoints[i][j][1], ctlpoints[i][j][2]);
}
}
glColor3f(1.0, 1.0, 1.0);
for(int i = 0; i<model->numvertices; i++){
glVertex3f(Orderedvertices[i].x,
Orderedvertices[i].y, Orderedvertices[i].z);
}
glEnd();
glEnable(GL_LIGHTING);
}
glPopMatrix();
glFlush();
}
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective (45.0, (GLdouble)w/(GLdouble)h, 3.0, 8.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef (0.0, 0.0, -5.0);
}
void keyboard(unsigned char key, int x, int y)
{
switch (key) {
case 'c':
case 'C':
showPoints = !showPoints;
glutPostRedisplay();
break;
case 'i':
case 'I':
add++;
MoveCtlPoints();
glutPostRedisplay();
break;
case 'd':
case 'D':
add--;
MoveCtlPoints();
glutPostRedisplay();
break;
case 'a':
case 'A':
side++;
MoveCtlPoints();
glutPostRedisplay();
break;
case 'g':
case 'G':
Interpolate();
glutPostRedisplay();
break;
case 27:
exit(0);
break;
default:
break;
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize (500, 500);
glutInitWindowPosition (100, 100);
glutCreateWindow(argv[0]);
init();
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutKeyboardFunc (keyboard);
glutMainLoop();
return 0;
}