Hello,
I'm trying to build some program under Microsoft Visual C++ 6.0 using externals functions
contained in the "libjpeg.h" library and I can't make the link edit to generate the executable
module after compilation of source without error. The message errors I've seem like this :
"terrain.obj : error LNK2001 : unresolved external symbol" for the functions below :
01 - _jpeg_std_error; 02 - _jpeg_CreateDecompress
03- _jpeg_stdio_src 04 - _jpeg_read_header
05- _jpeg_start_decompress 06 - _jpeg_read_scanlines
07- _jpeg_finish_decompress 08 - _jpeg_destroy_decompress
and after I have this message : "Debug/terrain.exe fatal error LNK1120 8 unresolved externals"
I don't know what happen under Windows XP... With OpenGL under Linux, the same program is
running very well.
Please help...
CJMN
N.B. you have the program source below :
/*************************************************************/
/* terrain.c */
/*************************************************************/
/* Génération de terrain à partir d'uneimage JPEG */
/*************************************************************/
/* inclusion des fichiers d'entête Glut */
#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <jpeglib.h>
#include <jerror.h>
#define NB_SUBDIV_INIT 32
#define NB_SUBDIV_MAX 64
#define ECHELLE_VERT_INIT 0.3
#define ECHELLE_VERT_MAX 1.0
#define DISTANCE_INIT 4.0
#define DISTANCE_MAX 15.0
/* Variables globales */
unsigned char image[256][256]; /* l'imagedu terrain */
unsigned char afficheRepere = TRUE; /* Affichage du repère */
unsigned char faceArriere = FALSE; /* Affichage des faces arrieres de polygones */
unsigned char areteTransv = FALSE; /* Affichage de l'arêtetransversale */
int repere, terrain; /* Identifiants des listes d'affichage */
int nbSubdiv = NB_SUBDIV_INIT; /* Nombre de subdivision du maillage */
float echelleVert = ECHELLE_VERT_INIT; /* echelle verticale du relief */
char b_gauche = 0, b_droit = 0; /* bouton de souris presse ? */
int theta = -30, phi = 300; /* Position de l'observateur */
int xprec, yprec; /* sauvegarde de la position de la souris */
float distance = DISTANCE_INIT; /* distance de l'observateurà l'origine*/
/* Prototype des fonctions */
void init();
void affichage(void);
void clavier(unsigned char touche, int x, int y);
void souris(int bouton, int etat, int x, int y);
void mouvement(int x, int y);
void redim(int l, int h);
void creeRepere();
void creeTerrain();
float elevation(int i, int j);
void loadJpegImage(char *filename);
/* **********************************************/
/* int main(int argc, char **argv */
/************************************************/
/* fonction principale */
/************************************************/
int main(int argc, char **argv)
{
/* initialisation de glut et creation
de la fenetre OpenGL */
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutInitWindowSize(500, 500);
glutCreateWindow(argv[0]);
/* initialisation d'OpenGL */
init();
loadJpegImage(argv[1]);
/* Creation des objets */
creeRepere();
creeTerrain();
/* Entrée dans la boucle principale glut */
glutMainLoop();
return 0;
}
/********************************************************/
/* void init() */
/********************************************************/
/* Fonction d'nitialisationd'OpenGL */
/********************************************************/
void init()
{
glClearColor(0.8, 0.8, 0.8, 1.0);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glCullFace(GL_BACK);
if (faceArriere)
glDisable(GL_CULL_FACE);
else
glEnable(GL_CULL_FACE);
/* Mise en place de la perspective */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, 1.0, 0.1, 20.0);
glMatrixMode(GL_MODELVIEW);
/* Mise en place des fonctions de rappel glut */
glutDisplayFunc(affichage);
glutKeyboardFunc(clavier);
glutMouseFunc(souris);
glutMotionFunc(mouvement);
glutReshapeFunc(redim);
}
/********************************************************/
/* void affichage() */
/********************************************************/
/* fonction de rappel pour l'affichage */
/********************************************************/
void affichage()
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
gluLookAt(0.0, 0.0, distance, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glRotatef(phi, 1.0, 0.0, 0.0);
glRotatef(theta, 0.0, 0.0, 1.0);
glCallList(terrain);
//
if (afficheRepere)
glCallList(repere);
/* On echange les buffers ou zones tampons */
glutSwapBuffers();
}
/********************************************************/
/* void clavier() */
/********************************************************/
/* fonction de rappel clavier */
/********************************************************/
void clavier(unsigned char touche, int x, int y)
{
switch (touche)
{
case 27: /* touche 'ESC' pour quitter */
exit(0);
case '+': /* augmentation du nombre de subdivisions */
nbSubdiv++;
if (nbSubdiv > NB_SUBDIV_MAX)
nbSubdiv = NB_SUBDIV_MAX;
creeTerrain();
glutPostRedisplay();
break;
case '-': /* dimunition du nombre de subdivisions */
nbSubdiv--;
if (nbSubdiv < 1)
nbSubdiv = 1;
creeTerrain();
glutPostRedisplay();
break;
case 'p': /* augmentation de l'echelleverticale */
echelleVert += 0.2;
if (echelleVert > ECHELLE_VERT_MAX)
echelleVert = ECHELLE_VERT_MAX;
creeTerrain();
glutPostRedisplay();
break;
case 'o': /* diminution de l'echelleverticale */
echelleVert -= 0.2;
if (echelleVert < -ECHELLE_VERT_MAX)
echelleVert = -ECHELLE_VERT_MAX;
creeTerrain();
glutPostRedisplay();
break;
case 'r': /* Affichage du repere ON/OFF */
afficheRepere = 1 - afficheRepere;
glutPostRedisplay();
break;
case 'c': /* affichage des faces arrières ON/OFF */
faceArriere = 1 - faceArriere;
if (faceArriere)
glDisable(GL_CULL_FACE);
else
glEnable(GL_CULL_FACE);
glutPostRedisplay();
break;
case 't': /* Affichage des aretes transversales */
areteTransv = 1 - areteTransv;
creeTerrain();
glutPostRedisplay();
break;
}
}
/********************************************************/
/* void souris(int bouton, int etat, int x, int y) */
/********************************************************/
/* fonction de rappel pour l'appuisur bouton de souris */
/********************************************************/
void souris(int bouton, int etat, int x, int y)
{
if (bouton == GLUT_LEFT_BUTTON &&etat == GLUT_DOWN)
{
b_gauche = 1; /* le booleen presse passe à 1 (vrai) */
xprec = x; /* on sauvegarde la position de la souris */
yprec = y;
}
if (bouton == GLUT_LEFT_BUTTON &&etat == GLUT_UP)
b_gauche = 0; /* le booleen presse passe à 0 (faux) */
if (bouton == GLUT_RIGHT_BUTTON &&etat == GLUT_DOWN)
{
b_droit = 1; /* le booleen presse passe à 1 (vrai) */
yprec = y;
}
if (bouton == GLUT_RIGHT_BUTTON &&etat == GLUT_UP)
b_droit = 0; /* le booleen presse passe à 0 (faux) */
}
/********************************************************/
/* void mouvement(int x, int y) */
/********************************************************/
/* fonction de rappel pour les mouvements de souris */
/********************************************************/
void mouvement(int x, int y)
{
/* si le bouton gauche est pressé */
if (b_gauche)
{
theta += x - xprec;
//
if (theta >= 360)
while (theta >360)
theta -= 360;
phi += y - yprec;
//
if (phi < 0)
while (phi < 0)
phi += 360;
//
xprec = x; /* sauvegarde des valeurs courantes de la position de la souris */
yprec = y;
//
glutPostRedisplay(); /* on demande un rafraichissement de l'affichage*/
}
/* si le bouton droit est pressé */
if (b_droit)
{
distance += ((float)(y - yprec))/10.0;
if (distance < 1.0)
distance = 1.0;
if (distance > DISTANCE_MAX)
distance = DISTANCE_MAX;
glutPostRedisplay(); /* on demande un rafraichissement de l'affichage*/
yprec = y;
}
}
/****************************************************************/
/* void redim(int l, int h) */
/****************************************************************/
/* fonction de rappel pour le redimensinnement de la fenêtre */
/****************************************************************/
void redim(int l, int h)
{
if (l < h)
glViewport(0, (h-l)/2, l, l);
else
glViewport((l-h)/2, 0, h, h);
}
/********************************************************/
/* void inactif */
/********************************************************/
/* fonction de rappel pour l'inactivité(idle) */
/********************************************************/
/*
void inactif()
{
/* increment du decalage */
/*
decalage += 0.1;
if (decalage > 2*PI);
decalage -= 2*PI;
/* rechargement de la texture */
/*
chargeTextureProc(IdTex[1]);
glutPostRedisplay();
}
*/
/********************************************************/
/* void creeRepere() */
/********************************************************/
/* chréation de la liste d'affichagepour */
/* le repere */
/********************************************************/
void creeRepere()
{
repere = glGenLists(1);
glNewList(repere, GL_COMPILE);
glLineWidth(2.0);
//
glBegin(GL_LINES);
glColor3f (1.0, 0.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.3, 0.0, 0.0);
glColor3f (0.0, 1.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.0, 0.3, 0.0);
glColor3f (0.0, 0.0, 1.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.0, 0.0, 0.3);
glEnd();
//
glEndList();
}
/********************************************************/
/* void creeTerrain */
/********************************************************/
/* Création de la liste d'affichagepour */
/* le terrain */
/********************************************************/
void creeTerrain()
{
int i, j;
float pas = 2.0 / nbSubdiv;
float P1[3], P2[3], P3[3], P4[3];
/* Liste pour l'objetterrain */
if (glIsList(terrain))
glDeleteLists(terrain, 1);
terrain = glGenLists(1);
//
glNewList(terrain, GL_COMPILE);
glColor3f(0.0, 0.0, 0.0);
glLineWidth(1.0);
//
for (i = 0; i < nbSubdiv; i++)
for (j = 0; j < nbSubdiv; j++)
{
P1[0] =- 1.0 + i*pas; P1[1] =- 1.0 + j*pas; P1[2] = elevation(i, j);
P2[0] =- 1.0 + (i + 1)*pas; P2[1] =- 1.0 + j*pas; P2[2] = elevation(i + 1, j);
P3[0] =- 1.0 + (i + 1)*pas; P3[1] =- 1.0 + (j + 1)*pas; P3[2] = elevation(i + 1, j + 1);
P4[0] =- 1.0 + i*pas; P4[1] =- 1.0 + (j + 1)*pas; P4[2] = elevation(i, j + 1);
//
glBegin(GL_TRIANGLES);
//
/* triangle 1 */
//
glEdgeFlag(TRUE);
glVertex3fv(P1);
glVertex3fv(P2);
//
if (!areteTransv)
glEdgeFlag(FALSE);
glVertex3fv(P3);
//
/* triangle 2 */
//
glVertex3fv(P1);
//
if (!areteTransv)
glEdgeFlag(TRUE);
glVertex3fv(P3);
glVertex3fv(P4);
glEnd();
}
glEndList();
}
/********************************************************/
/* Calcul de la hauteur d'unpoint */
/********************************************************/
float elevation(int i, int j)
{
int valeur = image[(int) ((float)i / nbSubdiv*255)][(int)((float)j / nbSubdiv*255)];
return ((float)valeur / 128.0 - 1.0)*echelleVert;
}
/********************************************************/
/* void loadJpegImage(char *filename) */
/********************************************************/
/* Chargement d'uneimage jpeg */
/********************************************************/
void loadJpegImage(char *filename)
{
FILE *file;
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
unsigned char *im = (unsigned char *)image, *ligne;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
/* On met en place une image par défaut si filename = NULL */
if (filename == NULL)
{
filename = (char *)malloc(128);
strcpy(filename, "terrain.jpg");
}
//
if (!(file = fopen(filename, "rb")))
{
fprintf(stderr, "Erreur : impossible d'ouvrir%s\n", filename);
exit(1);
}
jpeg_stdio_src(&cinfo, file);
jpeg_read_header(&cinfo, TRUE);
//
if ((cinfo.image_width != 256) || (cinfo.image_height != 256))
{
fprintf(stderr, "Erreur : l'imagedoit être de taille 256 x 256 \n");
exit(1);
}
jpeg_start_decompress(&cinfo);
// ligne = image;
while (cinfo.output_scanline < 256)
{
ligne = im + 256*cinfo.output_scanline;
jpeg_read_scanlines(&cinfo, &ligne, 1);
}
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
}
|