1
我在場景中加載了一個.obj立方體,我想在每個頂點(頂點+原點)上繪製一個球體。OpenGL:在.obj頂點繪製球體
##
## Three-D Library generated .obj file
## cube
##
mtllib cube.mtl
usemtl red
# 0 materials
v -1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 1.000000 -1.000000
v 1.000000 -1.000000 -1.000000
# 8 vertices
在我的draw()函數:
if(spheres){
i=0, j=0;
while (1){
printf("%d : %f %f %f\n", j, model->vertices[i], model->vertices[i+1], model->vertices[i+2]);
glTranslatef(model->vertices[i], model->vertices[i+1], model->vertices[i+2]);
glColor3f(0.0, 0.0, 1.0);
glutSolidSphere(0.4, 5, 5);
if(j >= model->numvertices)
break;
i=i+3;
j++;
}
}
其中 '模式' 是
GLMmodel* model; /* glm model data structure */
http://www.teina.org/TER_3DModeler/glm_8h-source.html
但是當我畫他們,他們是不是在正確的位置。
在上圖中我 「手動」 吸引他們:
glTranslatef(-1.000000, -1.000000, 1.000000);
glColor3f(0.0, 0.0, 1.0);
glutSolidSphere(0.3, 5, 5);
glTranslatef(-1.000000, 1.000000, 1.000000);
glColor3f(0.0, 0.0, 1.0);
glutSolidSphere(0.3, 5, 5);
沒有成功。
所有代碼:
/*
gc_smooth.c
Nate Robins, 1998
Giulio Casciola, 2008
Model viewer program. Exercises the glm library.
*/
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdarg.h>
#include <GL/glut.h>
#include "gltb.h"
#include "glm.h"
#include "dirent32.h"
#pragma comment(linker, "/entry:\"mainCRTStartup\"") // set the entry point to be main()
#define DATA_DIR "data/"
#define NUM_FRAMES 5
char* model_file = NULL; /* name of the obect file */
GLuint model_list = 0; /* display list for object */
GLMmodel* model; /* glm model data structure */
GLfloat scale; /* original scale factor */
GLfloat smoothing_angle = 90.0; /* smoothing angle */
GLfloat weld_distance = 0.00001; /* epsilon for welding vertices */
GLboolean facet_normal = GL_FALSE; /* draw with facet normal? */
GLboolean bounding_box = GL_FALSE; /* bounding box on? */
GLboolean spheres = GL_FALSE;
GLboolean performance = GL_FALSE; /* performance counter on? */
GLboolean stats = GL_FALSE; /* statistics on? */
GLuint material_mode = 0; /* 0=none, 1=color, 2=material, 3=texture */
GLint entries = 0; /* entries in model menu */
GLdouble pan_x = 0.0;
GLdouble pan_y = 0.0;
GLdouble pan_z = 0.0;
char texnames[1][64] = {"foto_rgb.ppm"};
//char texnames[1][64] = {"grid.ppm"};
GLint w,h;
GLubyte* texture;
#define CLK_TCK 1000
#if defined(_WIN32)
#include <sys/timeb.h>
#else
#include <limits.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/times.h>
#endif
float elapsed(void){
static long begin = 0;
static long finish, difference;
#if defined(_WIN32)
static struct timeb tb;
ftime(&tb);
finish = tb.time*1000+tb.millitm;
#else
static struct tms tb;
finish = times(&tb);
#endif
difference = finish - begin;
begin = finish;
return (float)difference/(float)CLK_TCK;
}
void shadowtext(int x, int y, char* s) {
int lines;
char* p;
glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0, glutGet(GLUT_WINDOW_WIDTH),
0, glutGet(GLUT_WINDOW_HEIGHT), -1, 1);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glColor3ub(0, 0, 0);
glRasterPos2i(x+1, y-1);
for(p = s, lines = 0; *p; p++) {
if (*p == '\n') {
lines++;
glRasterPos2i(x+1, y-1-(lines*18));
}
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, *p);
}
glColor3ub(0, 128, 255);
glRasterPos2i(x, y);
for(p = s, lines = 0; *p; p++) {
if (*p == '\n') {
lines++;
glRasterPos2i(x, y-(lines*18));
}
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, *p);
}
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glEnable(GL_DEPTH_TEST);
}
void lists(void){
GLfloat ambient[] = { 0.2, 0.2, 0.2, 1.0 };
GLfloat diffuse[] = { 0.8, 0.8, 0.8, 1.0 };
GLfloat specular[] = { 0.0, 0.0, 0.0, 1.0 };
GLfloat shininess = 65.0;
glMaterialfv(GL_FRONT, GL_AMBIENT, ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, specular);
glMaterialf(GL_FRONT, GL_SHININESS, shininess);
if (model_list)
glDeleteLists(model_list, 1);
glDisable(GL_TEXTURE_2D);
/* generate a list */
switch (material_mode)
{
case 0:
if (facet_normal)
model_list = glmList(model, GLM_FLAT);
else
model_list = glmList(model, GLM_SMOOTH);
break;
case 1:
if (facet_normal)
model_list = glmList(model, GLM_FLAT | GLM_COLOR);
else
model_list = glmList(model, GLM_SMOOTH | GLM_COLOR);
break;
case 2:
if (facet_normal)
model_list = glmList(model, GLM_FLAT | GLM_MATERIAL);
else
model_list = glmList(model, GLM_SMOOTH | GLM_MATERIAL);
break;
case 3:
glEnable(GL_TEXTURE_2D);
model_list = glmList(model, GLM_TEXTURE);
// glDisable(GL_TEXTURE_2D);
break;
}
}
void init(void){
gltbInit(GLUT_LEFT_BUTTON);
/* read in the model */
model = glmReadOBJ(model_file);
scale = glmUnitize(model);
glmFacetNormals(model);
glmVertexNormals(model, smoothing_angle);
if (model->nummaterials > 0)
material_mode = 2;
/* create new display lists */
lists();
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
glEnable(GL_DEPTH_TEST);
}
void reshape(int width, int height){
gltbReshape(width, height);
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (GLfloat)height/(GLfloat)width, 1.0, 128.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -3.0);
}
void display(void){
static char s[256], t[32];
static char* p;
static int frames = 0;
int i=0,j=0;
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glTranslatef(pan_x, pan_y, 0.0);
gltbMatrix();
#if 0 /* glmDraw() performance test */
swith(material_mode)
{
case 0:
if (facet_normal)
glmDraw(model, GLM_FLAT);
else
glmDraw(model, GLM_SMOOTH);
break;
case 1:
if (facet_normal)
glmDraw(model, GLM_FLAT | GLM_COLOR);
else
glmDraw(model, GLM_SMOOTH | GLM_COLOR);
break;
case 2:
if (facet_normal)
glmDraw(model, GLM_FLAT | GLM_MATERIAL);
else
glmDraw(model, GLM_SMOOTH | GLM_MATERIAL);
break;
case 3:
glEnable(GL_TEXTURE_2D);
glmDraw(model, GLM_TEXTURE);
// glDisable(GL_TEXTURE_2D);
break;
}
#else
glCallList(model_list);
#endif
glDisable(GL_LIGHTING);
if (bounding_box) {
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glEnable(GL_CULL_FACE);
glColor4f(1.0, 0.0, 0.0, 0.25);
glutSolidCube(2.0);
glDisable(GL_BLEND);
}
if(spheres){
//i=0, j=0;
//while (1){
printf("%d : %f %f %f\n", j, model->vertices[i], model->vertices[i+1], model->vertices[i+2]);
glTranslatef(-1.000000, -1.000000, 1.000000);
glColor3f(0.0, 0.0, 1.0);
glutSolidSphere(0.3, 5, 5);
glTranslatef(-1.000000, 1.000000, 1.000000);
glColor3f(0.0, 0.0, 1.0);
glutSolidSphere(0.3, 5, 5);
//if(j >= model->numvertices)
// break;
//i=i+3;
//j++;
//}
}
glPopMatrix();
if (stats) {
/* XXX - this could be done a _whole lot_ faster... */
int height = glutGet(GLUT_WINDOW_HEIGHT);
glColor3ub(0, 0, 0);
sprintf(s, "%s\n%d vertices\n%d triangles\n%d normals\n"
"%d texcoords\n%d groups\n%d materials",
model->pathname, model->numvertices, model->numtriangles,
model->numnormals, model->numtexcoords, model->numgroups,
model->nummaterials);
shadowtext(5, height-(5+18*1), s);
}
/* spit out frame rate. */
frames++;
if (frames > NUM_FRAMES) {
sprintf(t, "%g fps", frames/elapsed());
frames = 0;
}
if (performance) {
shadowtext(5, 5, t);
}
glutSwapBuffers();
glEnable(GL_LIGHTING);
}
void keyboard(unsigned char key, int x, int y){
GLint params[2];
switch (key) {
case 'h':
printf("help\n\n");
printf("w - Toggle wireframe/filled\n");
printf("c - Toggle culling\n");
printf("n - Toggle facet/smooth normal\n");
printf("b - Toggle bounding box\n");
printf("r - Reverse polygon winding\n");
printf("m - Toggle color/material/none/texture mode\n");
printf("p - Toggle performance indicator\n");
printf("s/S - Scale model smaller/larger\n");
printf("t - Show model stats\n");
printf("o - Weld vertices in model\n");
printf("+/- - Increase/decrease smoothing angle\n");
printf("W - Write model to file (out.obj)\n");
printf("q/escape - Quit\n\n");
break;
case 't':
stats = !stats;
break;
case 'p':
performance = !performance;
break;
case 'm':
material_mode++;
if (material_mode > 3)
material_mode = 0;
printf("material_mode = %d\n", material_mode);
lists();
break;
case 'd':
glmDelete(model);
init();
lists();
break;
case 'w':
glGetIntegerv(GL_POLYGON_MODE, params);
if (params[0] == GL_FILL)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
else
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
break;
case 'c':
if (glIsEnabled(GL_CULL_FACE))
glDisable(GL_CULL_FACE);
else
glEnable(GL_CULL_FACE);
break;
case 'b':
bounding_box = !bounding_box;
break;
case 'n':
facet_normal = !facet_normal;
lists();
break;
case 'r':
glmReverseWinding(model);
lists();
break;
case 's':
glmScale(model, 0.8);
lists();
break;
case 'S':
glmScale(model, 1.25);
lists();
break;
case 'o':
//printf("Welded %d\n", glmWeld(model, weld_distance));
glmVertexNormals(model, smoothing_angle);
lists();
break;
case 'O':
weld_distance += 0.01;
printf("Weld distance: %.2f\n", weld_distance);
glmWeld(model, weld_distance);
glmFacetNormals(model);
glmVertexNormals(model, smoothing_angle);
lists();
break;
case '-':
smoothing_angle -= 1.0;
printf("Smoothing angle: %.1f\n", smoothing_angle);
glmVertexNormals(model, smoothing_angle);
lists();
break;
case '+':
smoothing_angle += 1.0;
printf("Smoothing angle: %.1f\n", smoothing_angle);
glmVertexNormals(model, smoothing_angle);
lists();
break;
case 'W':
glmScale(model, 1.0/scale);
glmWriteOBJ(model, "out.obj", GLM_SMOOTH | GLM_MATERIAL);
break;
case 'R':
{
GLuint i;
GLfloat swap;
for (i = 1; i <= model->numvertices; i++) {
swap = model->vertices[3 * i + 1];
model->vertices[3 * i + 1] = model->vertices[3 * i + 2];
model->vertices[3 * i + 2] = -swap;
}
glmFacetNormals(model);
lists();
break;
}
case 'v':
{
spheres = !spheres;
/*printf("Il modello ha %u vertici \n", model->numvertices);
int i=0, j=0;
while (1){
printf("%d : %f %f %f\n", j, model->vertices[i], model->vertices[i+1], model->vertices[i+2]);
if(j >= model->numvertices)
break;
i=i+3;
j++;
}*/
break;
}
case 27:
exit(0);
break;
}
glutPostRedisplay();
}
void menu(int item){
int i = 0;
DIR* dirp;
char* name;
struct dirent* direntp;
if (item > 0) {
keyboard((unsigned char)item, 0, 0);
} else {
dirp = opendir(DATA_DIR);
while ((direntp = readdir(dirp)) != NULL) {
if (strstr(direntp->d_name, ".obj")) {
i++;
if (i == -item)
break;
}
}
if (!direntp)
return;
name = (char*)malloc(strlen(direntp->d_name) + strlen(DATA_DIR) + 1);
strcpy(name, DATA_DIR);
strcat(name, direntp->d_name);
model = glmReadOBJ(name);
scale = glmUnitize(model);
glmFacetNormals(model);
glmVertexNormals(model, smoothing_angle);
if (model->nummaterials > 0)
material_mode = 2;
else
material_mode = 0;
lists();
free(name);
glutPostRedisplay();
}
}
static GLint mouse_state;
static GLint mouse_button;
void mouse(int button, int state, int x, int y){
GLdouble model[4*4];
GLdouble proj[4*4];
GLint view[4];
/* fix for two-button mice -- left mouse + shift = middle mouse */
if (button == GLUT_LEFT_BUTTON && glutGetModifiers() & GLUT_ACTIVE_SHIFT)
button = GLUT_MIDDLE_BUTTON;
gltbMouse(button, state, x, y);
mouse_state = state;
mouse_button = button;
if (state == GLUT_DOWN && button == GLUT_MIDDLE_BUTTON) {
glGetDoublev(GL_MODELVIEW_MATRIX, model);
glGetDoublev(GL_PROJECTION_MATRIX, proj);
glGetIntegerv(GL_VIEWPORT, view);
gluProject((GLdouble)x, (GLdouble)y, 0.0,
model, proj, view,
&pan_x, &pan_y, &pan_z);
gluUnProject((GLdouble)x, (GLdouble)y, pan_z,
model, proj, view,
&pan_x, &pan_y, &pan_z);
pan_y = -pan_y;
}
glutPostRedisplay();
}
void motion(int x, int y){
GLdouble model[4*4];
GLdouble proj[4*4];
GLint view[4];
gltbMotion(x, y);
if (mouse_state == GLUT_DOWN && mouse_button == GLUT_MIDDLE_BUTTON) {
glGetDoublev(GL_MODELVIEW_MATRIX, model);
glGetDoublev(GL_PROJECTION_MATRIX, proj);
glGetIntegerv(GL_VIEWPORT, view);
gluProject((GLdouble)x, (GLdouble)y, 0.0,
model, proj, view,
&pan_x, &pan_y, &pan_z);
gluUnProject((GLdouble)x, (GLdouble)y, pan_z,
model, proj, view,
&pan_x, &pan_y, &pan_z);
pan_y = -pan_y;
}
glutPostRedisplay();
}
/* ppmRead: read a PPM raw (type P6) file. The PPM file has a header
that should look something like:
P6
# comment
width height max_value
rgbrgbrgb...
where "P6" is the magic cookie which identifies the file type and
should be the only characters on the first line followed by a
carriage return. Any line starting with a # mark will be treated
as a comment and discarded. After the magic cookie, three integer
values are expected: width, height of the image and the maximum
value for a pixel (max_value must be < 256 for PPM raw files). The
data section consists of width*height rgb triplets (one byte each)
in binary format (i.e., such as that written with fwrite() or
equivalent).
The rgb data is returned as an array of unsigned chars (packed
rgb). The malloc()'d memory should be free()'d by the caller. If
an error occurs, an error message is sent to stderr and NULL is
returned.
*/
unsigned char*
ppmRead(char* filename, int* width, int* height)
{
FILE* fp;
int i, w, h, d;
unsigned char* image;
char head[70]; /* max line <= 70 in PPM (per spec). */
fp = fopen(filename, "rb");
if (!fp) {
perror(filename);
return NULL;
}
/* grab first two chars of the file and make sure that it has the
correct magic cookie for a raw PPM file. */
fgets(head, 70, fp);
if (strncmp(head, "P6", 2)) {
fprintf(stderr, "%s: Not a raw PPM file\n", filename);
return NULL;
}
/* grab the three elements in the header (width, height, maxval). */
i = 0;
while(i < 3) {
fgets(head, 70, fp);
if (head[0] == '#') /* skip comments. */
continue;
if (i == 0)
i += sscanf(head, "%d %d %d", &w, &h, &d);
else if (i == 1)
i += sscanf(head, "%d %d", &h, &d);
else if (i == 2)
i += sscanf(head, "%d", &d);
}
/* grab all the image data in one fell swoop. */
image = (unsigned char*)malloc(sizeof(unsigned char)*w*h*3);
fread(image, sizeof(unsigned char), w*h*3, fp);
fclose(fp);
*width = w;
*height = h;
return image;
}
textures(void)
{
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
/* XXX - RE bug - must enable texture before bind. */
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 1);
texture = (GLubyte*)ppmRead(texnames[0], &w, &h);
// glTexImage2D(GL_TEXTURE_2D, 0, 3, w, h, 0,
// GL_RGB, GL_UNSIGNED_BYTE, texture);
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, w, h,
GL_RGB, GL_UNSIGNED_BYTE, texture);
free(texture);
/* XXX - RE bug - must enable texture before bind. */
glDisable(GL_TEXTURE_2D);
}
int main(int argc, char** argv){
int buffering = GLUT_DOUBLE;
struct dirent* direntp;
DIR* dirp;
int models;
glutInitWindowSize(512, 512);
glutInit(&argc, argv);
while (--argc) {
if (strcmp(argv[argc], "-sb") == 0)
buffering = GLUT_SINGLE;
else
model_file = argv[argc];
}
if (!model_file) {
// model_file = "data/dolphins.obj";
model_file = "data/boeing_2.obj";
}
glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | buffering);
glutCreateWindow("Smooth");
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutMouseFunc(mouse);
glutMotionFunc(motion);
/* Image data packed tightly. */
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
textures();
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
// glEnable(GL_TEXTURE_2D);
models = glutCreateMenu(menu);
dirp = opendir(DATA_DIR);
if (!dirp) {
fprintf(stderr, "%s: can't open data directory.\n", argv[0]);
} else {
while ((direntp = readdir(dirp)) != NULL) {
if (strstr(direntp->d_name, ".obj")) {
entries++;
glutAddMenuEntry(direntp->d_name, -entries);
}
}
closedir(dirp);
}
glutCreateMenu(menu);
glutAddMenuEntry("Smooth", 0);
glutAddMenuEntry("", 0);
glutAddSubMenu("Models", models);
glutAddMenuEntry("", 0);
glutAddMenuEntry("[w] Toggle wireframe/filled", 'w');
glutAddMenuEntry("[c] Toggle culling on/off", 'c');
glutAddMenuEntry("[n] Toggle face/smooth normals", 'n');
glutAddMenuEntry("[b] Toggle bounding box on/off", 'b');
glutAddMenuEntry("[p] Toggle frame rate on/off", 'p');
glutAddMenuEntry("[t] Toggle model statistics", 't');
glutAddMenuEntry("[m] Toggle color/material/none/texture mode", 'm');
glutAddMenuEntry("[r] Reverse polygon winding", 'r');
glutAddMenuEntry("[s] Scale model smaller", 's');
glutAddMenuEntry("[S] Scale model larger", 'S');
glutAddMenuEntry("[o] Weld redundant vertices", 'o');
glutAddMenuEntry("[+] Increase smoothing angle", '+');
glutAddMenuEntry("[-] Decrease smoothing angle", '-');
glutAddMenuEntry("[W] Write model to file (out.obj)", 'W');
glutAddMenuEntry("", 0);
glutAddMenuEntry("[Esc] Quit", 27);
glutAttachMenu(GLUT_RIGHT_BUTTON);
init();
glutMainLoop();
return 0;
}
哦,這是真的!謝謝 ;) – Davide