soc-2008-mxcurioni: towards Freestyle compilation, removing Qt's QString and QImage...
[blender-staging.git] / source / blender / freestyle / intern / rendering / GLStrokeRenderer.cpp
1
2 //
3 //  Copyright (C) : Please refer to the COPYRIGHT file distributed 
4 //   with this source distribution. 
5 //
6 //  This program is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU General Public License
8 //  as published by the Free Software Foundation; either version 2
9 //  of the License, or (at your option) any later version.
10 //
11 //  This program is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //  GNU General Public License for more details.
15 //
16 //  You should have received a copy of the GNU General Public License
17 //  along with this program; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19 //
20 ///////////////////////////////////////////////////////////////////////////////
21
22 #include <qimage.h>
23 #include <qfileinfo.h>
24 #include <qgl.h>
25 #include <qfile.h>
26 #include "GLStrokeRenderer.h"
27
28 #ifdef WIN32
29 # include "extgl.h"
30 #endif // WIN32
31
32 //#define glBlendEquation(x)
33
34 GLStrokeRenderer::GLStrokeRenderer()
35 :StrokeRenderer()
36 {
37   _textureManager = new GLTextureManager;
38 }
39
40 GLStrokeRenderer::~GLStrokeRenderer()
41 {
42   if(0 != _textureManager)
43   {
44     delete _textureManager;
45     _textureManager = 0;
46   }
47 }
48
49 float initialColor(float x, float avTex=0.5)
50 {
51   float y=(1-x)/avTex;
52   return (y>1 ? 1 : y);
53 }
54 //float complementColor(float x, float avTex=0.5)
55 //{
56 //  float y=(1-x)/avTex-1;
57 //  return (y<0 ? 0 : y);
58 //}
59
60 float complementColor(float x, float avTex=0.5)
61 {
62   float y=(1-x);///avTex-1;
63   return (y<0 ? 0 : y);
64 }
65
66 void GLStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const
67 {
68   glPushAttrib(GL_COLOR_BUFFER_BIT);
69   Stroke::MediumType strokeType = iStrokeRep->getMediumType();
70   // int averageTextureAlpha=0.5; //default value
71   // if (strokeType==OIL_STROKE)
72     // averageTextureAlpha=0.75; 
73   // if (strokeType>=NO_BLEND_STROKE)
74     // averageTextureAlpha=1.0; 
75   // if (strokeType<0)
76     // {
77       // renderNoTexture(iStrokeRep);
78       // return;
79     // }
80   int i;
81   glDisable(GL_CULL_FACE);
82   glDisable(GL_LIGHTING);
83   glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
84   glShadeModel(GL_SMOOTH);
85   glDisable(GL_DEPTH_TEST);
86     
87   glEnable(GL_BLEND);
88
89   if(strokeType==Stroke::DRY_MEDIUM)
90     {
91       glBlendEquation(GL_MAX);
92     }
93   else if(strokeType==Stroke::OPAQUE_MEDIUM)
94     {
95       glBlendEquation(GL_ADD);
96       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
97     }
98   else
99     {
100       glBlendEquation(GL_ADD);
101       glBlendFunc(GL_SRC_ALPHA, GL_ONE);
102     }
103   glEnable(GL_TEXTURE_2D);
104   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
105   //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
106
107   //first texture, basically the only one for lighter strokes
108   glBindTexture(GL_TEXTURE_2D, iStrokeRep->getTextureId()); 
109   //glBindTexture(GL_TEXTURE_2D, _textureManager.getPaperTextureIndex()); 
110   
111   vector<Strip*>& strips = iStrokeRep->getStrips();
112   for(vector<Strip*>::iterator s=strips.begin(), send=strips.end();
113   s!=send;
114   ++s){
115     Strip::vertex_container& vertices = (*s)->vertices();
116     glBegin(GL_TRIANGLE_STRIP);
117     for(Strip::vertex_container::iterator v=vertices.begin(), vend=vertices.end();
118     v!=vend;
119     ++v){
120       StrokeVertexRep * svRep = (*v);
121       Vec3r color = svRep->color();
122       real alpha = svRep->alpha();
123       glColor4f(complementColor(color[0]), 
124       complementColor(color[1]), 
125       complementColor(color[2]), alpha);
126       glTexCoord2f(svRep->texCoord()[0],svRep->texCoord()[1] );
127       glVertex2f(svRep->point2d()[0], svRep->point2d()[1]);
128     }  
129     glEnd();
130   }
131 //  if (strokeType>=NO_BLEND_STROKE) return;
132   //  //return;
133   //
134   //  //second texture, the complement, for stronger strokes
135   //  glBindTexture(GL_TEXTURE_2D, _textureManager.getTextureIndex(2*strokeType+1)); 
136   //  glBegin(GL_TRIANGLE_STRIP);
137   //  for(i=0; i<_sizeStrip; i++)
138   //  {
139   //    glColor4f(complementColor(_color[i][0]), 
140   //      complementColor(_color[i][1]), 
141   //      complementColor(_color[i][2]), _alpha[i]);
142   //    glTexCoord2f(_texCoord[i][0],_texCoord[i][1] );
143   //    glVertex2f(_vertex[i][0], _vertex[i][1]);
144   //  }
145   //  glEnd();
146
147   glPopAttrib();
148 }
149
150 void GLStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
151 {
152   glPushAttrib(GL_COLOR_BUFFER_BIT);
153   Stroke::MediumType strokeType = iStrokeRep->getMediumType();
154   int i;
155   glDisable(GL_CULL_FACE);
156   glDisable(GL_LIGHTING);
157   glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
158   glShadeModel(GL_SMOOTH);
159   glDisable(GL_DEPTH_TEST);
160     
161   glEnable(GL_BLEND);
162
163   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
164   glEnable(GL_TEXTURE_2D);
165   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
166   //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
167
168   //first texture, basically the only one for lighter strokes
169   glBindTexture(GL_TEXTURE_2D, iStrokeRep->getTextureId()); 
170   //glBindTexture(GL_TEXTURE_2D, _textureManager.getPaperTextureIndex()); 
171   
172   vector<Strip*>& strips = iStrokeRep->getStrips();
173   for(vector<Strip*>::iterator s=strips.begin(), send=strips.end();
174   s!=send;
175   ++s){
176     Strip::vertex_container& vertices = (*s)->vertices();
177     glBegin(GL_TRIANGLE_STRIP);
178     for(Strip::vertex_container::iterator v=vertices.begin(), vend=vertices.end();
179     v!=vend;
180     ++v){
181       StrokeVertexRep * svRep = (*v);
182       Vec3r color = svRep->color();
183       real alpha = svRep->alpha();
184       glColor4f(color[0], 
185               color[1], 
186               color[2], alpha);
187       glTexCoord2f(svRep->texCoord()[0],svRep->texCoord()[1] );
188       glVertex2f(svRep->point2d()[0], svRep->point2d()[1]);
189     }  
190     glEnd();
191   }
192   glPopAttrib();
193 }
194
195 //No Texture
196 //void GLStrokeRenderer::renderNoTexture(StrokeRep *iStrokeRep) const
197 //{
198 //  Stroke::MediumType strokeType = iStrokeRep->getMediumType();
199 //  int sizeStrip = iStrokeRep->sizeStrip();
200 //  const Vec3r *color = iStrokeRep->colors();
201 //  const Vec2r *vertex = iStrokeRep->vertices();
202 //  const float *alpha = iStrokeRep->alpha();
203 //  
204 //  glDisable(GL_LIGHTING);
205 //  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
206 //  glShadeModel(GL_SMOOTH);
207 //  glDisable(GL_DEPTH_TEST);
208 //
209 //  //if (strokeType==NO_TEXTURE_STROKE)
210 //  if(strokeType < 0)
211 //    {
212 //      glDisable(GL_BLEND);
213 //      glDisable(GL_TEXTURE_2D);
214 //      glBegin(GL_TRIANGLE_STRIP);
215 //      for(int i=0; i<sizeStrip; i++)
216 //      { 
217 //        glColor4f(complementColor(color[i][0]), 
218 //                  complementColor(color[i][1]), 
219 //                  complementColor(color[i][2]), alpha[i]);
220 //        glVertex2f(vertex[i][0], vertex[i][1]);
221 //      } 
222 //      glEnd();
223 //    } 
224 //  else
225 //    {
226 //      //#ifdef WIN32
227 //      //glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
228 //      glBlendEquation(GL_ADD);
229 //      //#endif
230 //      glEnable(GL_BLEND);
231 //      glBlendFunc(GL_SRC_ALPHA, GL_ONE);
232 //      glDisable(GL_TEXTURE_2D);
233 //      glBegin(GL_TRIANGLE_STRIP);
234 //      for(int i=0; i<sizeStrip; i++)
235 //      { 
236 //        glColor4f(complementColor(color[i][0]), 
237 //                  complementColor(color[i][1]), 
238 //                  complementColor(color[i][2]), alpha[i]);
239 //        glVertex2f(vertex[i][0], vertex[i][1]);
240 //      } 
241 //      glEnd();
242 //    }
243 //  //  cerr<<"color="<<_color[1][0]<<", "<<_color[1][1]<<", "<<_color[1][2]<<") "<<endl;
244 //      
245 //      
246 //}
247
248
249 /**********************************/
250 /*                                */
251 /*                                */
252 /*         GLTextureManager         */
253 /*                                */
254 /*                                */
255 /**********************************/
256
257 //#define TEXTURES_DIR ROOT_DIR "/data/textures"
258
259 GLTextureManager::GLTextureManager ()
260 : TextureManager()
261 {
262   //_brushes_path = Config::getInstance()...
263 }
264
265 GLTextureManager::~GLTextureManager ()
266 {
267 }
268
269 void
270 GLTextureManager::loadPapers ()
271 {
272   unsigned size = _papertextures.size();
273   _papertexname = new unsigned[size];
274   GLuint *tmp = new GLuint[size];
275   glGenTextures(size, tmp);
276   for(int i=0;i<size;++i){
277     _papertexname[i] = tmp[i];
278   }
279   delete [] tmp;
280
281   // Papers textures
282   cout << "Loading papers textures..." << endl;
283
284   for (unsigned i = 0; i < size; i++)
285     preparePaper(_papertextures[i].c_str(), _papertexname[i]);
286
287   cout << "Done." << endl << endl;
288 }
289
290 void GLTextureManager::loadStandardBrushes()
291 {
292   //  getBrushTextureIndex(TEXTURES_DIR "/brushes/charcoalAlpha.bmp", Stroke::HUMID_MEDIUM);
293   //  getBrushTextureIndex(TEXTURES_DIR "/brushes/washbrushAlpha.bmp", Stroke::HUMID_MEDIUM);
294   //  getBrushTextureIndex(TEXTURES_DIR "/brushes/oil.bmp", Stroke::HUMID_MEDIUM);
295   //  getBrushTextureIndex(TEXTURES_DIR "/brushes/oilnoblend.bmp", Stroke::HUMID_MEDIUM);
296   //  getBrushTextureIndex(TEXTURES_DIR "/brushes/charcoalAlpha.bmp", Stroke::DRY_MEDIUM);
297   //  getBrushTextureIndex(TEXTURES_DIR "/brushes/washbrushAlpha.bmp", Stroke::DRY_MEDIUM);
298   //  getBrushTextureIndex(TEXTURES_DIR "/brushes/opaqueDryBrushAlpha.bmp", Stroke::OPAQUE_MEDIUM);
299   //  getBrushTextureIndex(TEXTURES_DIR "/brushes/opaqueBrushAlpha.bmp", Stroke::OPAQUE_MEDIUM);
300   _defaultTextureId = getBrushTextureIndex("smoothAlpha.bmp", Stroke::OPAQUE_MEDIUM);
301 }
302
303
304 unsigned
305 GLTextureManager::loadBrush(string sname, Stroke::MediumType mediumType)
306 {
307   GLuint texId;
308   glGenTextures(1, &texId);
309   bool found = false;
310   vector<string> pathnames;
311   QString path;
312   StringUtils::getPathName(TextureManager::Options::getBrushesPath(),
313   sname,
314   pathnames);
315   for (vector<string>::const_iterator j = pathnames.begin(); j != pathnames.end(); j++) {
316     path = j->c_str();
317     if(QFile::exists(path)){
318       found = true;
319       break;
320     }
321   }
322   if(!found)
323     return 0;
324   // Brush texture
325   cout << "Loading brush texture..." << endl;
326   switch(mediumType){
327   case Stroke::DRY_MEDIUM:
328     prepareTextureLuminance((const char*)path.toAscii(), texId);
329     break;
330   case Stroke::HUMID_MEDIUM:
331   case Stroke::OPAQUE_MEDIUM:
332   default:
333     prepareTextureAlpha((const char*)path.toAscii(), texId);
334     break;
335   }
336   cout << "Done." << endl << endl;
337
338   return texId;
339 }
340
341 bool 
342 GLTextureManager::prepareTextureAlpha (string sname, GLuint itexname)
343 {
344   const char * name = sname.c_str();
345   QImage qim(name);
346   QFileInfo fi(name);
347   QString filename = fi.fileName();
348   if (qim.isNull()) 
349     {
350       cerr << "  Error: unable to read \"" << name << "\"" << endl;
351       return false;
352     }
353   if (qim.depth()>8)
354     {
355       cerr<<"  Error: \""<< name <<"\" has "<<qim.depth()<<" bits/pixel"<<endl;
356       return false;
357     }
358   //            qim=QGLWidget::convertToGLFormat( qimOri );
359
360   glBindTexture(GL_TEXTURE_2D, itexname);
361   //glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
362         
363   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
364   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
365   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
366                   GL_LINEAR);
367   //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
368   //          GL_NEAREST);
369   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
370                   GL_LINEAR);     
371
372   glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, qim.width(), qim.height(), 0, 
373                GL_ALPHA, GL_UNSIGNED_BYTE, qim.bits()); 
374
375   cout << "  \"" << filename.toAscii().data() << "\" loaded with "<< qim.depth() << " bits per pixel" << endl;
376
377   return true;
378
379 }
380
381 bool 
382 GLTextureManager::prepareTextureLuminance (string sname, GLuint itexname)
383 {
384   const char * name = sname.c_str();
385   QImage qim(name);
386   QFileInfo fi(name);
387   QString filename = fi.fileName();
388   if (qim.isNull()) 
389     {
390       cerr << "  Error: unable to read \"" << name << "\"" << endl;
391       return false;
392     }
393   if (qim.depth() > 8)
394     {
395       cerr<<"  Error: \""<<name<<"\" has "<<qim.depth()<<" bits/pixel"<<endl;
396       return false;
397     }
398
399   glBindTexture(GL_TEXTURE_2D, itexname);
400   //glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
401         
402   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
403   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
404   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
405                   GL_LINEAR);
406   //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
407   //          GL_NEAREST);
408   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
409                   GL_LINEAR);     
410
411   glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, qim.width(), qim.height(), 0, 
412                GL_LUMINANCE, GL_UNSIGNED_BYTE, qim.bits());     
413
414   cout << "  \"" << filename.toAscii().data() << "\" loaded with "<< qim.depth() << " bits per pixel" << endl;
415
416   return true;
417
418 }
419
420 bool 
421 GLTextureManager::prepareTextureLuminanceAndAlpha (string sname, GLuint itexname)
422 {
423   const char * name = sname.c_str();
424   QImage qim(name);
425   QFileInfo fi(name);
426   QString filename = fi.fileName();
427   if (qim.isNull()) 
428     {
429       cerr << "  Error: unable to read \"" << name << "\"" << endl;
430       return false;
431     }
432   if (qim.depth() > 8)
433     {
434       cerr<<"  Error: \""<<name<<"\" has "<<qim.depth()<<" bits/pixel"<<endl;
435       return false;
436     }
437                                            
438   glBindTexture(GL_TEXTURE_2D, itexname);
439   //glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
440                                              
441   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
442   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
443   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
444                   GL_LINEAR);
445   //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
446   //          GL_NEAREST);
447   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
448                   GL_LINEAR);     
449                                                      
450   glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, qim.width(), qim.height(), 0, 
451                GL_LUMINANCE, GL_UNSIGNED_BYTE, qim.bits());     
452   glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, qim.width(), qim.height(), 0, 
453                GL_ALPHA, GL_UNSIGNED_BYTE, qim.bits()); 
454                                                          
455   cout << "  \"" << filename.toAscii().data() << "\" loaded with "<< qim.depth() << " bits per pixel" << endl;                                             
456
457   return true;
458                                                              
459 }
460
461 bool 
462 GLTextureManager::preparePaper (const char *name, GLuint itexname)
463 {
464   QImage qim(name);
465   QFileInfo fi(name);
466   QString filename = fi.fileName();
467   if (qim.isNull()) 
468     {
469       cerr << "  Error: unable to read \"" << name << "\"" << endl;
470       return false;
471     }
472   if (qim.depth()!=32)
473     {
474       cerr<<"  Error: \""<<name<<"\" has "<<qim.depth()<<" bits/pixel"<<endl;
475       return false;
476     }
477   QImage qim2=QGLWidget::convertToGLFormat( qim );
478
479   glBindTexture(GL_TEXTURE_2D, itexname);
480         
481   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
482   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
483   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
484                   GL_LINEAR);
485   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
486                   GL_LINEAR);     
487
488   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, qim.width(), qim.height(), 0, 
489                GL_RGBA, GL_UNSIGNED_BYTE, qim2.bits()); 
490
491   cout << "  \"" << filename.toAscii().data() << "\" loaded with "<< qim.depth() << " bits per pixel" << endl;
492
493   return true;
494 }
495