Bonjour,
j'ai un problème qui en fait n'en est pas un!
En fait j'essaye d'utiliser OpenGL avec wxWidgets via un wxGLCanvas.
Je charge une image à l'aide de la classe wxImage, et j'essaye d'en faire une texture affichable à l'aide d'OpenGL.
Pour se faire j'ai donc utilisé le tutoriel trouvé sur le wiki de wxWidgets, que j'ai adapté un petit peu.
Le problème c'est que ça fonctionne parfaitement sur MacOSX, mais sur Windows XP quand j'essaye d'afficher j'ai une violente erreur et ça plante directement. J'ai réussi à isoler la ligne qui bloque le tout sur windows, du coup ça affiche une image blanche sans la texture donc.
J'ai isolé d'où viens le problème, c'est la ligne suivante :
Code GLSprite.cpp à la ligne 58 : Sélectionner tout - Visualiser dans une fenêtre à part glBindTexture(GL_TEXTURE_2D, image->getID()[0]);
J'ai bien vérifié dans la classe GLImage si l'image était bien chargée, et c'est le cas, la taille est bien prise etc. Donc je ne sais pas trop d'où viens le problème puisque ça s'affiche au poil sur OS X.
Voila le code :
Code GLImage.h : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 #ifndef __GLImage #define __GLImage #ifdef __WXMAC__ #include "OpenGL/glu.h" #include "OpenGL/gl.h" #include "GLUT/glut.h" #else #include <wx/glcanvas.h> #endif #include <wx/wx.h> #include <wx/image.h> #include <cmath> namespace Graphics { /** * GLImage contains an OpenGL representation of an image (i.e. a texture) wich * is dedicated to be rendered in an OpenGL scene. * The asset of this class is to provide a convenient way to load image via wxImage * to an OpenGL representation wich can be directly rendered. */ class GLImage { private: GLuint* ID; public: int width, height, textureWidth, textureHeight; float textureCoordX, textureCoordY; GLuint* getID(); GLImage(); GLImage(wxString path); ~GLImage(); int getWidth(); void load(wxString path); GLuint* loadImage(wxString imagePath, int* imageWidth, int* imageHeight, int* textureWidth, int* textureHeight); }; } #endif
Code GLImage.cpp : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169 #include "GLImage.h" #define HAS_ALPHA (img->HasAlpha() ? 4 : 3) #define IS_RGBA (img->HasAlpha() ? GL_RGBA : GL_RGB) using Graphics::GLImage; using namespace std; /** * Default constructor. */ GLImage::GLImage() { } /** * Constructor from the path to the image to load. * @param imagePath path to the image to load */ GLImage::GLImage(wxString imagePath) { this->load(imagePath); } /** * Load an image. * @param imagePath path to the image to load */ void GLImage::load(wxString imagePath) { ID = loadImage(imagePath, &width, &height, &textureWidth, &textureHeight); textureCoordX = width / (float)textureWidth; textureCoordY = height / (float)textureHeight; } /** * Get the OpenGL texture identifiant. * @return the OpenGL texture identifiant */ GLuint* GLImage::getID() { return ID; } /** * Get the texture width. * @return the width of the texture */ int GLImage::getWidth() { return width; } /** * Destructor */ GLImage::~GLImage() { glDeleteTextures(1, ID); } /** * Load an image into it's OpenGL representation * @param imagePath the path to the image to load * @param imageWidth variable where the image's width is stored * @param imageHeight variable where the image's heigth is stored * @param textureWidth variable where the texture's width is stored * @param textureHeight variable where the texture's width is stored * @return the OpenGL texture representation of the image. */ GLuint* GLImage::loadImage(wxString imagePath, int* imageWidth, int* imageHeight, int* textureWidth, int* textureHeight) { wxImage * img = new wxImage(imagePath); GLuint* ID = new GLuint[1]; glGenTextures(1, ID); glBindTexture(GL_TEXTURE_2D, *ID); // init image handlers static bool firstRun = true; if ( firstRun ) { wxInitAllImageHandlers(); firstRun = false; } *imageWidth = img->GetWidth(); *imageHeight = img->GetHeight(); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); float correctWidth = log((float)*imageWidth) / log(2.0); float correctHeight = log((float)*imageHeight) / log(2.0); // check if image dimensions are a power of two if ( (int)correctWidth == correctWidth && (int)correctHeight == correctHeight) { glTexImage2D(GL_TEXTURE_2D, 0, HAS_ALPHA, *imageWidth, *imageHeight, 0, IS_RGBA, GL_UNSIGNED_BYTE, img->GetData()); *textureWidth = *imageWidth; *textureHeight = *imageHeight; } else // resize the texture to match a power of 2 { int newWidth = (int)pow(2.0, (int)ceil(correctWidth)); int newHeight = (int)pow(2.0, (int)ceil(correctHeight)); GLubyte *bitmapData = img->GetData(); GLubyte *alphaData = img->GetAlpha(); GLubyte *imageData; int old_bytesPerPixel = 3; int bytesPerPixel = HAS_ALPHA; int imageSize = newWidth * newHeight * bytesPerPixel; imageData = (GLubyte *)malloc(imageSize); int rev_val = *imageHeight - 1; for (int y = 0; y < newHeight; ++y) { for (int x = 0; x < newWidth; ++x) { if ( x < *imageWidth && y < *imageHeight ) { imageData[(x + y * newWidth) * bytesPerPixel] = bitmapData[(x + (rev_val-y) * *imageWidth) * old_bytesPerPixel]; imageData[(x+y*newWidth) * bytesPerPixel + 1] = bitmapData[(x + (rev_val-y) * *imageWidth) * old_bytesPerPixel + 1]; imageData[(x+y*newWidth) * bytesPerPixel + 2] = bitmapData[(x + (rev_val-y) * *imageWidth) * old_bytesPerPixel + 2]; if (bytesPerPixel == 4) imageData[(x + y * newWidth) * bytesPerPixel + 3] = alphaData[x + (rev_val-y) * *imageWidth]; } else { imageData[(x + y * newWidth) * bytesPerPixel] = 0; imageData[(x + y * newWidth) * bytesPerPixel + 1] = 0; imageData[(x + y * newWidth) * bytesPerPixel + 2] = 0; if (bytesPerPixel == 4) imageData[(x + y * newWidth) * bytesPerPixel + 3] = 0; } } } glTexImage2D(GL_TEXTURE_2D, 0, HAS_ALPHA, newWidth, newHeight, 0, IS_RGBA, GL_UNSIGNED_BYTE, imageData); *textureWidth = newWidth; *textureHeight = newHeight; delete imageData; } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 0);//GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 0);//GL_CLAMP_TO_EDGE); wxMessageBox(wxString::Format(wxT("id : %d"), *ID)); return ID; }
Code GLSprite.h : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 #ifndef __GLSprite #define __GLSprite #ifdef __WXMAC__ #include "OpenGL/gl.h" #else #include <wx/glcanvas.h> #endif #include "wx/wx.h" #include "GLImage.h" namespace Graphics { class GLSprite { private: GLImage* image; int x, y, angle, hotSpotX, hotSpotY; float xScale, yScale; bool xFlip, yFlip; public: GLSprite(GLImage* img); ~GLSprite(); /* des fonctions pour rotation etc... */ void setImage(GLImage* image); GLImage* getImage(); void render(); }; } #endif
Code GLSprite.cpp : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75 #include "GLSprite.h" using Graphics::GLSprite; using Graphics::GLImage; /** * This is a simple class built on top of OpenGL that manages drawing images in a higher-level and quicker way. */ GLSprite::GLSprite(GLImage* img) { x = y = hotSpotX = hotSpotY = angle = 0; xScale = yScale = 1; xFlip = yFlip = false; if (img != NULL) this->setImage(img); else image = NULL; } GLSprite::~GLSprite() { delete image; } void GLSprite::setImage(GLImage* image) { this->image = image; } Graphics::GLImage* GLSprite::getImage() { return this->image; } void GLSprite::render() { if (image == NULL) { wxMessageBox(wxT("image vide")); exit(1); } glLoadIdentity(); glTranslatef(x, y, 0); if (xScale != 1 || yScale != 1) glScalef(xScale, yScale, 1); if (angle) glRotatef(angle, 0,0,1); if (image->getID() == NULL) { wxMessageBox(wxT("ID vide")); exit(1); } glBindTexture(GL_TEXTURE_2D, image->getID()[0]); glBegin(GL_QUADS); glTexCoord2f(xFlip? image->textureCoordX : 0, yFlip? 0 : image->textureCoordY); glVertex2f(-hotSpotX, -hotSpotY); glTexCoord2f(xFlip? 0 : image->textureCoordX, yFlip? 0 : image->textureCoordY); glVertex2f(image->width - hotSpotX, -hotSpotY); glTexCoord2f(xFlip? 0 : image->textureCoordX, yFlip? image->textureCoordY : 0); glVertex2f(image->width - hotSpotX, image->height - hotSpotY); glTexCoord2f(xFlip? image->textureCoordX : 0, yFlip? image->textureCoordY : 0); glVertex2f(-hotSpotX, image->height - hotSpotY); glEnd(); }
Et finalement j'affiche l'image comme ceci :
J'ai fait une recherche mais je n'ai pas trouvé de réponse pour le moment, donc si vous pouviez m'aider ça serait très sympathique
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 Graphics::GLSPrite * sprite = new Graphics::GLSprite(new Graphics::GLImage("sprite.bmp")); sprite->render();
Merci d'avance !
Partager