476 lines
14 KiB
C++
Executable File
476 lines
14 KiB
C++
Executable File
|
|
//
|
|
// Copyright (C) : Please refer to the COPYRIGHT file distributed
|
|
// with this source distribution.
|
|
//
|
|
// This program is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU General Public License
|
|
// as published by the Free Software Foundation; either version 2
|
|
// of the License, or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program; if not, write to the Free Software
|
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "GLStrokeRenderer.h"
|
|
|
|
//soc
|
|
// #include <qimage.h>
|
|
// #include <qfileinfo.h>
|
|
// #include <qgl.h>
|
|
// #include <qfile.h>
|
|
|
|
extern "C" {
|
|
#include "BLI_blenlib.h"
|
|
#include "IMB_imbuf.h"
|
|
#include "IMB_imbuf_types.h"
|
|
#include "MEM_guardedalloc.h"
|
|
}
|
|
|
|
#include "../system/StringUtils.h"
|
|
|
|
//#define glBlendEquation(x)
|
|
|
|
GLStrokeRenderer::GLStrokeRenderer()
|
|
:StrokeRenderer()
|
|
{
|
|
_textureManager = new GLTextureManager;
|
|
}
|
|
|
|
GLStrokeRenderer::~GLStrokeRenderer()
|
|
{
|
|
if(0 != _textureManager)
|
|
{
|
|
delete _textureManager;
|
|
_textureManager = 0;
|
|
}
|
|
}
|
|
|
|
float initialColor(float x, float avTex=0.5)
|
|
{
|
|
float y=(1-x)/avTex;
|
|
return (y>1 ? 1 : y);
|
|
}
|
|
//float complementColor(float x, float avTex=0.5)
|
|
//{
|
|
// float y=(1-x)/avTex-1;
|
|
// return (y<0 ? 0 : y);
|
|
//}
|
|
|
|
float complementColor(float x, float avTex=0.5)
|
|
{
|
|
float y=(1-x);///avTex-1;
|
|
return (y<0 ? 0 : y);
|
|
}
|
|
|
|
void GLStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const
|
|
{
|
|
glPushAttrib(GL_COLOR_BUFFER_BIT);
|
|
Stroke::MediumType strokeType = iStrokeRep->getMediumType();
|
|
// int averageTextureAlpha=0.5; //default value
|
|
// if (strokeType==OIL_STROKE)
|
|
// averageTextureAlpha=0.75;
|
|
// if (strokeType>=NO_BLEND_STROKE)
|
|
// averageTextureAlpha=1.0;
|
|
// if (strokeType<0)
|
|
// {
|
|
// renderNoTexture(iStrokeRep);
|
|
// return;
|
|
// }
|
|
//soc unused - int i;
|
|
glDisable(GL_CULL_FACE);
|
|
glDisable(GL_LIGHTING);
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
glShadeModel(GL_SMOOTH);
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
if(strokeType==Stroke::DRY_MEDIUM)
|
|
{
|
|
glBlendEquation(GL_MAX);
|
|
}
|
|
else if(strokeType==Stroke::OPAQUE_MEDIUM)
|
|
{
|
|
glBlendEquation(GL_ADD);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
}
|
|
else
|
|
{
|
|
glBlendEquation(GL_ADD);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
|
}
|
|
glEnable(GL_TEXTURE_2D);
|
|
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
|
//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
|
|
|
//first texture, basically the only one for lighter strokes
|
|
glBindTexture(GL_TEXTURE_2D, iStrokeRep->getTextureId());
|
|
|
|
vector<Strip*>& strips = iStrokeRep->getStrips();
|
|
for(vector<Strip*>::iterator s=strips.begin(), send=strips.end();
|
|
s!=send;
|
|
++s){
|
|
Strip::vertex_container& vertices = (*s)->vertices();
|
|
glBegin(GL_TRIANGLE_STRIP);
|
|
for(Strip::vertex_container::iterator v=vertices.begin(), vend=vertices.end();
|
|
v!=vend;
|
|
++v){
|
|
StrokeVertexRep * svRep = (*v);
|
|
Vec3r color = svRep->color();
|
|
real alpha = svRep->alpha();
|
|
glColor4f(complementColor(color[0]),
|
|
complementColor(color[1]),
|
|
complementColor(color[2]), alpha);
|
|
glTexCoord2f(svRep->texCoord()[0],svRep->texCoord()[1] );
|
|
glVertex2f(svRep->point2d()[0], svRep->point2d()[1]);
|
|
}
|
|
glEnd();
|
|
}
|
|
// if (strokeType>=NO_BLEND_STROKE) return;
|
|
// //return;
|
|
//
|
|
// //second texture, the complement, for stronger strokes
|
|
// glBindTexture(GL_TEXTURE_2D, _textureManager.getTextureIndex(2*strokeType+1));
|
|
// glBegin(GL_TRIANGLE_STRIP);
|
|
// for(i=0; i<_sizeStrip; i++)
|
|
// {
|
|
// glColor4f(complementColor(_color[i][0]),
|
|
// complementColor(_color[i][1]),
|
|
// complementColor(_color[i][2]), _alpha[i]);
|
|
// glTexCoord2f(_texCoord[i][0],_texCoord[i][1] );
|
|
// glVertex2f(_vertex[i][0], _vertex[i][1]);
|
|
// }
|
|
// glEnd();
|
|
|
|
glPopAttrib();
|
|
}
|
|
|
|
void GLStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
|
|
{
|
|
glPushAttrib(GL_COLOR_BUFFER_BIT);
|
|
//soc unused - Stroke::MediumType strokeType = iStrokeRep->getMediumType();
|
|
//soc unused - int i;
|
|
glDisable(GL_CULL_FACE);
|
|
glDisable(GL_LIGHTING);
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
glShadeModel(GL_SMOOTH);
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
glEnable(GL_TEXTURE_2D);
|
|
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
|
//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
|
|
|
//first texture, basically the only one for lighter strokes
|
|
glBindTexture(GL_TEXTURE_2D, iStrokeRep->getTextureId());
|
|
|
|
vector<Strip*>& strips = iStrokeRep->getStrips();
|
|
for(vector<Strip*>::iterator s=strips.begin(), send=strips.end();
|
|
s!=send;
|
|
++s){
|
|
Strip::vertex_container& vertices = (*s)->vertices();
|
|
glBegin(GL_TRIANGLE_STRIP);
|
|
for(Strip::vertex_container::iterator v=vertices.begin(), vend=vertices.end();
|
|
v!=vend;
|
|
++v){
|
|
StrokeVertexRep * svRep = (*v);
|
|
Vec3r color = svRep->color();
|
|
real alpha = svRep->alpha();
|
|
glColor4f(color[0],
|
|
color[1],
|
|
color[2], alpha);
|
|
glTexCoord2f(svRep->texCoord()[0],svRep->texCoord()[1] );
|
|
glVertex2f(svRep->point2d()[0], svRep->point2d()[1]);
|
|
}
|
|
glEnd();
|
|
}
|
|
glPopAttrib();
|
|
}
|
|
|
|
//No Texture
|
|
//void GLStrokeRenderer::renderNoTexture(StrokeRep *iStrokeRep) const
|
|
//{
|
|
// Stroke::MediumType strokeType = iStrokeRep->getMediumType();
|
|
// int sizeStrip = iStrokeRep->sizeStrip();
|
|
// const Vec3r *color = iStrokeRep->colors();
|
|
// const Vec2r *vertex = iStrokeRep->vertices();
|
|
// const float *alpha = iStrokeRep->alpha();
|
|
//
|
|
// glDisable(GL_LIGHTING);
|
|
// glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
// glShadeModel(GL_SMOOTH);
|
|
// glDisable(GL_DEPTH_TEST);
|
|
//
|
|
// //if (strokeType==NO_TEXTURE_STROKE)
|
|
// if(strokeType < 0)
|
|
// {
|
|
// glDisable(GL_BLEND);
|
|
// glDisable(GL_TEXTURE_2D);
|
|
// glBegin(GL_TRIANGLE_STRIP);
|
|
// for(int i=0; i<sizeStrip; i++)
|
|
// {
|
|
// glColor4f(complementColor(color[i][0]),
|
|
// complementColor(color[i][1]),
|
|
// complementColor(color[i][2]), alpha[i]);
|
|
// glVertex2f(vertex[i][0], vertex[i][1]);
|
|
// }
|
|
// glEnd();
|
|
// }
|
|
// else
|
|
// {
|
|
// //#ifdef WIN32
|
|
// //glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
|
|
// glBlendEquation(GL_ADD);
|
|
// //#endif
|
|
// glEnable(GL_BLEND);
|
|
// glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
|
// glDisable(GL_TEXTURE_2D);
|
|
// glBegin(GL_TRIANGLE_STRIP);
|
|
// for(int i=0; i<sizeStrip; i++)
|
|
// {
|
|
// glColor4f(complementColor(color[i][0]),
|
|
// complementColor(color[i][1]),
|
|
// complementColor(color[i][2]), alpha[i]);
|
|
// glVertex2f(vertex[i][0], vertex[i][1]);
|
|
// }
|
|
// glEnd();
|
|
// }
|
|
// // cerr<<"color="<<_color[1][0]<<", "<<_color[1][1]<<", "<<_color[1][2]<<") "<<endl;
|
|
//
|
|
//
|
|
//}
|
|
|
|
|
|
/**********************************/
|
|
/* */
|
|
/* */
|
|
/* GLTextureManager */
|
|
/* */
|
|
/* */
|
|
/**********************************/
|
|
|
|
//#define TEXTURES_DIR ROOT_DIR "/data/textures"
|
|
|
|
GLTextureManager::GLTextureManager ()
|
|
: TextureManager()
|
|
{
|
|
//_brushes_path = Config::getInstance()...
|
|
}
|
|
|
|
GLTextureManager::~GLTextureManager ()
|
|
{
|
|
}
|
|
|
|
void GLTextureManager::loadStandardBrushes()
|
|
{
|
|
// getBrushTextureIndex(TEXTURES_DIR "/brushes/charcoalAlpha.bmp", Stroke::HUMID_MEDIUM);
|
|
// getBrushTextureIndex(TEXTURES_DIR "/brushes/washbrushAlpha.bmp", Stroke::HUMID_MEDIUM);
|
|
// getBrushTextureIndex(TEXTURES_DIR "/brushes/oil.bmp", Stroke::HUMID_MEDIUM);
|
|
// getBrushTextureIndex(TEXTURES_DIR "/brushes/oilnoblend.bmp", Stroke::HUMID_MEDIUM);
|
|
// getBrushTextureIndex(TEXTURES_DIR "/brushes/charcoalAlpha.bmp", Stroke::DRY_MEDIUM);
|
|
// getBrushTextureIndex(TEXTURES_DIR "/brushes/washbrushAlpha.bmp", Stroke::DRY_MEDIUM);
|
|
// getBrushTextureIndex(TEXTURES_DIR "/brushes/opaqueDryBrushAlpha.bmp", Stroke::OPAQUE_MEDIUM);
|
|
// getBrushTextureIndex(TEXTURES_DIR "/brushes/opaqueBrushAlpha.bmp", Stroke::OPAQUE_MEDIUM);
|
|
_defaultTextureId = getBrushTextureIndex("smoothAlpha.bmp", Stroke::OPAQUE_MEDIUM);
|
|
}
|
|
|
|
|
|
unsigned
|
|
GLTextureManager::loadBrush(string sname, Stroke::MediumType mediumType)
|
|
{
|
|
GLuint texId;
|
|
glGenTextures(1, &texId);
|
|
bool found = false;
|
|
vector<string> pathnames;
|
|
string path; //soc
|
|
StringUtils::getPathName(TextureManager::Options::getBrushesPath(),
|
|
sname,
|
|
pathnames);
|
|
for (vector<string>::const_iterator j = pathnames.begin(); j != pathnames.end(); j++) {
|
|
path = j->c_str();
|
|
//soc if(QFile::exists(path)){
|
|
if( BLI_exists( const_cast<char *>(path.c_str()) ) ) {
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if(!found)
|
|
return 0;
|
|
// Brush texture
|
|
cout << "Loading brush texture..." << endl;
|
|
switch(mediumType){
|
|
case Stroke::DRY_MEDIUM:
|
|
//soc prepareTextureLuminance((const char*)path.toAscii(), texId);
|
|
prepareTextureLuminance(StringUtils::toAscii(path), texId);
|
|
break;
|
|
case Stroke::HUMID_MEDIUM:
|
|
case Stroke::OPAQUE_MEDIUM:
|
|
default:
|
|
//soc prepareTextureAlpha((const char*)path.toAscii(), texId);
|
|
prepareTextureAlpha(StringUtils::toAscii(path), texId);
|
|
break;
|
|
}
|
|
cout << "Done." << endl << endl;
|
|
|
|
return texId;
|
|
}
|
|
|
|
bool
|
|
GLTextureManager::prepareTextureAlpha (string sname, GLuint itexname)
|
|
{
|
|
//soc const char * name = sname.c_str();
|
|
char * name = (char *) sname.c_str();
|
|
|
|
//soc
|
|
ImBuf *qim = IMB_loadiffname(name, 0);
|
|
char filename[FILE_MAXFILE];
|
|
char *p = BLI_strdup(name);
|
|
BLI_splitdirstring(p, filename);
|
|
MEM_freeN(p);
|
|
|
|
//soc if (qim.isNull())
|
|
if (!qim) //soc
|
|
{
|
|
cerr << " Error: unable to read \"" << filename << "\"" << endl;
|
|
IMB_freeImBuf(qim);
|
|
return false;
|
|
}
|
|
|
|
if( qim->depth > 8) //soc
|
|
{
|
|
cerr<<" Error: \""<< filename <<"\" has "<< qim->depth <<" bits/pixel"<<endl; //soc
|
|
return false;
|
|
}
|
|
// qim=QGLWidget::convertToGLFormat( qimOri );
|
|
|
|
glBindTexture(GL_TEXTURE_2D, itexname);
|
|
//glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
|
|
GL_LINEAR);
|
|
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
|
|
// GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
|
GL_LINEAR);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, qim->x, qim->y, 0,
|
|
GL_ALPHA, GL_UNSIGNED_BYTE, qim->rect); //soc
|
|
|
|
//soc cout << " \"" << filename.toAscii().data() << "\" loaded with "<< qim.depth() << " bits per pixel" << endl;
|
|
cout << " \"" << filename << "\" loaded with 32 bits per pixel" << endl;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool
|
|
GLTextureManager::prepareTextureLuminance (string sname, GLuint itexname)
|
|
{
|
|
//soc const char * name = sname.c_str();
|
|
char * name = (char *) sname.c_str();
|
|
|
|
//soc
|
|
ImBuf *qim = IMB_loadiffname(name, 0);
|
|
char filename[FILE_MAXFILE];
|
|
char *p = BLI_strdup(name);
|
|
BLI_splitdirstring(p, filename);
|
|
MEM_freeN(p);
|
|
|
|
if (!qim) //soc
|
|
{
|
|
cerr << " Error: unable to read \"" << filename << "\"" << endl;
|
|
IMB_freeImBuf(qim);
|
|
return false;
|
|
}
|
|
if (qim->depth > 8) //soc
|
|
{
|
|
cerr<<" Error: \""<<filename<<"\" has "<<qim->depth <<" bits/pixel"<<endl;//soc
|
|
return false;
|
|
}
|
|
|
|
glBindTexture(GL_TEXTURE_2D, itexname);
|
|
//glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
|
|
GL_LINEAR);
|
|
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
|
|
// GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
|
GL_LINEAR);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, qim->x, qim->y, 0,
|
|
GL_LUMINANCE, GL_UNSIGNED_BYTE, qim->rect); //soc
|
|
|
|
//soc cout << " \"" << filename.toAscii().data() << "\" loaded with "<< qim.depth() << " bits per pixel" << endl;
|
|
cout << " \"" << filename << "\" loaded with "<< qim->depth << " bits per pixel" << endl;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool
|
|
GLTextureManager::prepareTextureLuminanceAndAlpha (string sname, GLuint itexname)
|
|
{
|
|
//soc const char * name = sname.c_str();
|
|
char * name = (char *) sname.c_str();
|
|
|
|
//soc
|
|
ImBuf *qim = IMB_loadiffname(name, 0);
|
|
char filename[FILE_MAXFILE];
|
|
char *p = BLI_strdup(name);
|
|
BLI_splitdirstring(p, filename);
|
|
MEM_freeN(p);
|
|
|
|
if (!qim) //soc
|
|
{
|
|
cerr << " Error: unable to read \"" << filename << "\"" << endl;
|
|
IMB_freeImBuf(qim);
|
|
return false;
|
|
}
|
|
|
|
if (qim->depth > 8) //soc
|
|
{
|
|
cerr<<" Error: \""<<filename<<"\" has "<< qim->depth <<" bits/pixel"<<endl; //soc
|
|
return false;
|
|
}
|
|
|
|
glBindTexture(GL_TEXTURE_2D, itexname);
|
|
//glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
|
|
GL_LINEAR);
|
|
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
|
|
// GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
|
GL_LINEAR);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, qim->x, qim->y, 0,
|
|
GL_LUMINANCE, GL_UNSIGNED_BYTE, qim->rect); //soc
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, qim->x, qim->y, 0,
|
|
GL_ALPHA, GL_UNSIGNED_BYTE, qim->rect); //soc
|
|
|
|
//soc cout << " \"" << filename.toAscii().data() << "\" loaded with "<< qim.depth() << " bits per pixel" << endl;
|
|
cout << " \"" << filename << "\" loaded with "<< qim->depth << " bits per pixel" << endl;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|