Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: 05c48a334a
Fetching contributors…

Cannot retrieve contributors at this time

759 lines (655 sloc) 23.927 kb
/******************************************************************************
* $id: mapoglrenderer.cpp 7725 2011-04-09 15:56:58Z toby $
*
* Project: MapServer
* Purpose: Various template processing functions.
* Author: Steve Lime and the MapServer team.
*
******************************************************************************
* Copyright (c) 1996-2008 Regents of the University of Minnesota.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies of this Software or works derived from this Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
****************************************************************************/
#ifdef USE_OGL
#include <algorithm>
#include <fstream>
#include "mapserver.h"
#include "maperror.h"
#include "mapoglrenderer.h"
using namespace std;
double OglRenderer::SIZE_RES = 100.0 / 72.0;
ms_uint32 OglRenderer::OUTLINE_WIDTH = 2;
ms_uint32 OglRenderer::FONT_SIZE = 20;
ms_uint32 OglRenderer::FONT_RES = 200;
double OglRenderer::OGL_PI = 3.14159265;
ms_uint32 OglRenderer::SHAPE_CIRCLE_RES = 10;
double OglRenderer::SHAPE_CIRCLE_RADIUS = 10.0;
OglRenderer::fontCache_t OglRenderer::fontCache = OglRenderer::fontCache_t();
OglRenderer::dashCache_t OglRenderer::dashCache = OglRenderer::dashCache_t();
std::vector<GLuint> OglRenderer::shapes = std::vector<GLuint>();
GLvoid CALLBACK beginCallback(GLenum which);
GLvoid CALLBACK errorCallback(GLenum errorCode);
GLvoid CALLBACK endCallback(void);
GLvoid CALLBACK combineDataCallback(GLdouble coords[3], GLdouble* vertex_data[4], GLfloat weight[4], void** dataOut, void* polygon_data);
GLvoid CALLBACK vertexCallback(GLdouble *vertex);
OglRenderer::OglRenderer(ms_uint32 width, ms_uint32 height, colorObj* color)
: width(width), height(height), texture(NULL), transparency(1.0), valid(false)
{
context = new OglContext(width, height);
if (!context->isValid()) return;
if (!context->makeCurrent()) return;
int viewPort[4];
glGetIntegerv(GL_VIEWPORT ,viewPort);
viewportX = viewPort[0];
viewportY = viewPort[1];
viewportWidth = viewPort[2];
viewportHeight = viewPort[3];
glPushMatrix();
// set read/write context to pbuffer
glEnable(GL_MULTISAMPLE_ARB);
glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST);
glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glDisable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
// draw & read the front buffer of pbuffer
glDrawBuffer(GL_FRONT);
glReadBuffer(GL_FRONT);
if (!(tess = gluNewTess())) {
msSetError(MS_OGLERR, "P-buffer Error: Unable to create tessalotor",
"OglRenderer");
return;
}
gluTessCallback(tess, GLU_TESS_VERTEX, (void (CALLBACK*)(void)) vertexCallback);
gluTessCallback(tess, GLU_TESS_BEGIN, (void(CALLBACK*)(void)) beginCallback);
gluTessCallback(tess, GLU_TESS_END, (void(CALLBACK*)(void)) endCallback);
gluTessCallback(tess, GLU_TESS_ERROR, (void(CALLBACK*)(void)) errorCallback);
gluTessCallback(tess, GLU_TESS_COMBINE_DATA, (void(CALLBACK*)(void)) combineDataCallback);
if (color) {
glClearColor((double) color->red / 255,
(double) color->green / 255,
(double) color->blue / 255,
(double)color->alpha / 100);
} else {
glClearColor(0.0, 0.0, 0.0, 0.0);
}
glClear(GL_COLOR_BUFFER_BIT);
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, width, 0.0, height, -3.0, 3.0);
createShapes();
valid = true;
}
OglRenderer::~OglRenderer()
{
makeCurrent();
glViewport(viewportX, viewportY, viewportWidth, viewportHeight);
glPopMatrix();
delete context;
}
OglCachePtr OglRenderer::getTexture()
{
if (!texture) {
makeCurrent();
texture = new OglCache();
texture->texture = createTexture(0,0);//TEXTURE_BORDER/2, TEXTURE_BORDER/2);
texture->width = this->width;
texture->height = this->height;
}
return texture;
}
GLuint OglRenderer::createTexture(ms_uint32 offsetX, ms_uint32 offsetY)
{
GLuint texture = 0;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
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_GENERATE_MIPMAP, GL_TRUE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST);
if (OglContext::MAX_ANISOTROPY != 0) {
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, OglContext::MAX_ANISOTROPY);
}
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, offsetX, offsetY, context->getWidth(), context->getHeight(), 0);
glBindTexture(GL_TEXTURE_2D,0);
return texture;
}
bool OglRenderer::getStringBBox(char *font, double size, char *string, rectObj *rect, double** advances)
{
FTFont* face = getFTFont(font, size);
if (!face) {
msSetError(MS_OGLERR, "Failed to load font (%s).", "OglRenderer::getStringBBox()", font);
return false;
}
float llx =0.0f, lly=0.0f, llz=0.0f, urx=0.0f, ury=0.0f, urz=0.0f;
glPushAttrib( GL_ALL_ATTRIB_BITS );
FTBBox boundingBox = face->BBox(string);
glPopAttrib();
rect->minx = boundingBox.Lower().X();
rect->maxx = boundingBox.Upper().X();
rect->miny = -boundingBox.Upper().Y();
rect->maxy = -boundingBox.Lower().Y();
if (advances) {
int length = strlen(string);
*advances = new double[length];
for (int i = 0; i < length; ++i) {
(*advances)[i] = face->Advance(&string[i], 1);
}
}
return true;
}
void OglRenderer::initializeRasterBuffer(rasterBufferObj * rb, int width, int height, bool useAlpha)
{
unsigned char* buffer = new unsigned char[4 * width * height];
rb->data.rgba.pixels = buffer;
rb->data.rgba.r = &buffer[2];
rb->data.rgba.g = &buffer[1];
rb->data.rgba.b = &buffer[0];
if (useAlpha) rb->data.rgba.a = &buffer[3];
rb->type =MS_BUFFER_BYTE_RGBA;
rb->data.rgba.row_step = 4*width;
rb->data.rgba.pixel_step = 4;
rb->width = width;
rb->height = height;
}
void OglRenderer::readRasterBuffer(rasterBufferObj * rb)
{
makeCurrent();
unsigned char* buffer = new unsigned char[4 * width * height];
glReadPixels(0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, buffer);
rb->type =MS_BUFFER_BYTE_RGBA;
rb->data.rgba.pixels = buffer;
rb->data.rgba.row_step = 4*width;
rb->data.rgba.pixel_step = 4;
rb->width = width;
rb->height = height;
rb->data.rgba.r = &buffer[2];
rb->data.rgba.g = &buffer[1];
rb->data.rgba.b = &buffer[0];
rb->data.rgba.a = NULL;
}
void OglRenderer::drawRasterBuffer(rasterBufferObj *overlay, double opacity, int srcX, int srcY, int dstX, int dstY, int width, int height)
{
// todo to support all alpha and srcx/y this needs to be done by creating a texture
makeCurrent();
glDrawPixels(width, height, GL_BGRA, GL_UNSIGNED_BYTE, overlay->data.rgba.pixels);
}
void OglRenderer::setTransparency(double transparency)
{
this->transparency = transparency;
}
void OglRenderer::setColor(colorObj *color)
{
if (color && MS_VALID_COLOR(*color)) {
glColor4d((double) color->red / 255, (double) color->green / 255, (double) color->blue / 255, transparency);
} else {
glColor4d(0.0, 0.0, 0.0, 1.0);
}
}
void OglRenderer::drawVectorLineStrip(symbolObj *symbol, double width)
{
glPushMatrix();
glLineWidth(width);
glBegin(GL_LINE_STRIP);
for (int i = 0; i < symbol->numpoints; i++) {
if (symbol->points[i].x < 0 && symbol->points[i].y < 0) {
glEnd();
glBegin(GL_LINE_STRIP);
} else {
glVertex2d(symbol->points[i].x, symbol->points[i].y);
}
}
glEnd();
glPopMatrix();
}
double OglRenderer::drawTriangles(pointObj* p1, pointObj* p2, double width, double tilelength, double textureStart)
{
double dx = p1->x - p2->x;
double dy = p1->y - p2->y;
double dist = sqrt(dx * dx + dy * dy);
double theta;
if (dx != 0)
theta = atan(dy / dx);
else
theta = (dy > 0 ? 1 : -1) * OGL_PI / 2;
double xw = sin(theta) * width / 2;
double yw = cos(theta) * width / 2;
double textureEnd = dist / tilelength;
glTexCoord2d(textureStart, 1);
glVertex2d(p1->x + xw, p1->y - yw); // Bottom Left Of The Texture and Quad
glTexCoord2d(textureStart, 0);
glVertex2d(p1->x - xw, p1->y + yw); // Bottom Right Of The Texture and Quad
glTexCoord2d(textureStart + textureEnd, 1);
glVertex2d(p2->x + xw, p2->y - yw); // Top Right Of The Texture and Quad
glTexCoord2d(textureStart + textureEnd, 0);
glVertex2d(p2->x - xw, p2->y + yw); // Top Left Of The Texture and Quad
return dist;
}
double OglRenderer::drawQuad(pointObj* p1, pointObj* p2, double width, double tilelength, double textureStart)
{
double dx = p1->x - p2->x;
double dy = p1->y - p2->y;
double dist = sqrt(dx * dx + dy * dy);
double theta;
if (dx)
theta = atan(dy / dx);
else
theta = (dy > 0 ? 1 : -1) * OGL_PI / 2;
glPushMatrix();
glTranslated(p1->x, p1->y, 0);
glRotated((p1->x < p2->x ? 0 : 180) + theta * (180 / OGL_PI), 0, 0, 1);
glTranslated(-p1->x, -p1->y, 0);
glBegin(GL_QUADS);
glTexCoord2d(textureStart, 1);
glVertex2d(p1->x, p1->y - width / 2); // Bottom Left Of The Texture and Quad
glTexCoord2d(textureStart + (dist / tilelength), 1);
glVertex2d(p1->x + dist, p1->y - width / 2); // Bottom Right Of The Texture and Quad
glTexCoord2d(textureStart + (dist / tilelength), 0);
glVertex2d(p1->x + dist, p1->y + width / 2); // Top Right Of The Texture and Quad
glTexCoord2d(textureStart, 0);
glVertex2d(p1->x, p1->y + width / 2); // Top Left Of The Texture and Quad
glEnd();
glPopMatrix();
return dist;
}
void OglRenderer::renderTile(const OglCachePtr& tile, double x, double y, double angle)
{
makeCurrent();
glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);
glBindTexture(GL_TEXTURE_2D, tile->texture);
glPushMatrix();
glTranslated(x, y, 0);
if (angle) {
glRotated(angle, 0, 0, 1);
}
glTranslated(-x, -y, 0);
glBegin(GL_QUADS);
glTexCoord2d(0, 1);
glVertex2d( x-(tile->width/2), y+(tile->height/2)); // Bottom Left Of The Texture and Quad
glTexCoord2d(1, 1);
glVertex2d( x+(tile->width/2), y+(tile->height/2)); // Bottom Right Of The Texture and Quad
glTexCoord2d(1, 0);
glVertex2d( x+(tile->width/2), y-(tile->height/2)); // Top Right Of The Texture and Quad
glTexCoord2d(0, 0);
glVertex2d( x-(tile->width/2), y-(tile->height/2)); // Top Left Of The Texture and Quad
glEnd();
glPopMatrix();
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);
}
void OglRenderer::renderPolylineTile(shapeObj *shape, const OglCachePtr& tile)
{
makeCurrent();
glBindTexture(GL_TEXTURE_2D, tile->texture); // Select Our Texture
glBegin(GL_TRIANGLE_STRIP);
double place = 0.0;
for (int i = 0; i < shape->numlines; i++) {
for (int j = 0; j < shape->line[i].numpoints - 1; j++) {
double dist = drawTriangles(&shape->line[i].point[j], &shape->line[i].point[j + 1], tile->height, tile->width, place / tile->width);
place = (place + dist);
while (place >= tile->width) place -= tile->width;
}
}
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
}
void OglRenderer::renderVectorSymbol(double x, double y, symbolObj *symbol, double scale, double angle, colorObj *c, colorObj *oc, double ow)
{
makeCurrent();
glPushMatrix();
glTranslated(x, y, 0);
glRotated(angle, 0, 0, 1);
glScaled(scale, scale, 0);
glTranslated(-symbol->sizex/2, -symbol->sizey/2, 0.0);
if (oc != NULL && MS_VALID_COLOR(*oc) && ow > 0) {
setColor(oc);
drawVectorLineStrip(symbol, ow);
}
if (c != NULL && MS_VALID_COLOR(*c) && ow > 0) {
setColor(c);
drawVectorLineStrip(symbol, ow);
}
glPopMatrix();
}
void OglRenderer::renderPolyline(shapeObj *p, colorObj *c, double width,
int patternlength, double* pattern, int lineCap, int joinStyle,
colorObj *outlinecolor, double outlinewidth)
{
makeCurrent();
if (outlinecolor) {
glEnable(GL_DEPTH_TEST);
glPushMatrix();
glTranslated(0, 0, 1);
}
setColor(c);
if (patternlength > 0) {
if (p->renderer_cache == NULL) {
loadLine(p, width, patternlength, pattern);
}
/* FIXME */
if (p->renderer_cache == NULL)
return;
OglCache* cache = (OglCache*) p->renderer_cache;
GLuint texture = cache->texture;
if (cache->patternDistance > 0) {
glBindTexture(GL_TEXTURE_2D, texture);
double place = 0;
glBegin(GL_TRIANGLE_STRIP);
for (int j = 0; j < p->numlines; j++) {
for (int i = 0; i < p->line[j].numpoints - 1; i++) {
double dist = drawTriangles(&p->line[j].point[i],
&p->line[j].point[i + 1], width,
cache->patternDistance, place
/ cache->patternDistance);
place = (place + dist);
while (place >= cache->patternDistance)
place -= cache->patternDistance; // better than mod, no rounding
}
}
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
}
} else {
float widthRange[2];
glGetFloatv(GL_LINE_WIDTH_RANGE, widthRange);
bool quads = !(width >= widthRange[0] && width <= widthRange[1]);
double circleScale = width / SHAPE_CIRCLE_RADIUS / 2;
glLineWidth(width);
if (quads || (width > 1.0 && (lineCap == MS_CJC_ROUND || joinStyle == MS_CJC_ROUND))) {
for (int j = 0; j < p->numlines; j++) {
for (int i = 0; i < p->line[j].numpoints; i++) {
if (i != p->line[j].numpoints - 1) {
if (quads) {
drawQuad(&p->line[j].point[i], &p->line[j].point[i
+ 1], width);
} else {
glBegin(GL_LINES);
glVertex2f(p->line[j].point[i].x, p->line[j].point[i].y);
glVertex2f(p->line[j].point[i + 1].x,p->line[j].point[i + 1].y);
glEnd();
}
}
if ((lineCap == MS_CJC_ROUND && (i == 0 || i == p->line[j].numpoints - 1)) ||
(joinStyle == MS_CJC_ROUND && (i > 0 && i < p->line[j].numpoints - 1))) {
glPushMatrix();
glTranslated(p->line[j].point[i].x, p->line[j].point[i].y, 0);
glScaled(circleScale, circleScale, 0);
glCallList(shapes[circle]);
glPopMatrix();
}
}
}
} else {
for (int j = 0; j < p->numlines; j++) {
glBegin(GL_LINE_STRIP);
for (int i = 0; i < p->line[j].numpoints; i++) {
glVertex2f(p->line[j].point[i].x, p->line[j].point[i].y);
}
glEnd();
}
}
}
if (outlinecolor != NULL && MS_VALID_COLOR(*outlinecolor)) {
glPopMatrix();
double owidth = MS_MAX(width + OUTLINE_WIDTH, outlinewidth);
glPushMatrix();
glTranslated(0, 0, -1);
renderPolyline(p, outlinecolor, owidth, patternlength, pattern, lineCap, joinStyle);
glPopMatrix();
glDisable(GL_DEPTH_TEST);
}
}
void OglRenderer::renderPolygon(shapeObj *p, colorObj *color, colorObj *outlinecolor, double outlinewidth, const OglCachePtr& tile, int lineCap, int joinStyle)
{
/*
OpenGL cannot draw complex polygons so we need to use a Tessallator to draw the polygon using a GL_TRIANGLE_FAN
ISSUE: There's a problem here. It would seem that changing the dimensions or bounding box area breaks the code.
Reports need for a combine callback.
*/
makeCurrent();
std::vector<GLdouble*> pointers;
double texWidth = 0;
double texHeight = 0;
if (tile) {
glBindTexture(GL_TEXTURE_2D, tile->texture); // Select Our Texture
texWidth = tile->width;
texHeight = tile->height;
}
setColor(color);
gluTessBeginPolygon(tess, NULL );
for (int j = 0; j < p->numlines; j++) {
gluTessBeginContour(tess);
for (int i = 0; i < p->line[j].numpoints; i++) {
// create temp array and place
GLdouble* dbls = new GLdouble[5];
pointers.push_back(dbls);
dbls[0] = p->line[j].point[i].x;
dbls[1] = p->line[j].point[i].y;
dbls[2] = 0.0;
dbls[3] = texWidth;
dbls[4] = texHeight;
gluTessVertex(tess, dbls, dbls);
}
gluTessEndContour(tess);
}
gluTessEndPolygon(tess);
// destroy temp arrays
for (std::vector<GLdouble*>::iterator iter = pointers.begin(); iter
!= pointers.end(); iter++) {
delete[] *iter;
}
glBindTexture(GL_TEXTURE_2D, 0); // Select Our Texture
if (outlinecolor != NULL && MS_VALID_COLOR(*outlinecolor) && outlinewidth > 0) {
renderPolyline(p, outlinecolor, outlinewidth, 0, NULL, lineCap,
joinStyle);
}
}
void OglRenderer::renderGlyphs(double x, double y, colorObj *color,
colorObj *outlinecolor, double size, const char* font, char *thechars, double angle,
colorObj *shadowcolor, double shdx, double shdy)
{
makeCurrent();
FTFont* face = getFTFont(font, size);
if (!face) {
msSetError(MS_OGLERR, "Failed to load font (%s).", "OglRenderer::renderGlyphs()", font);
return;
}
glPushAttrib(GL_ALL_ATTRIB_BITS);
glPushMatrix();
glTranslated(floor(x), floor(y), 0);
glScaled(1.0, -1.0, 1);
glRotated(angle * (180 / OGL_PI), 0, 0, 1);
if (outlinecolor && MS_VALID_COLOR(*outlinecolor)) {
setColor(outlinecolor);
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
if (i || j) {
glPushMatrix();
glTranslated(i, j, 0);
face->Render(thechars);
glPopMatrix();
}
}
}
}
if (color != NULL && MS_VALID_COLOR(*color)) {
setColor(color);
face->Render(thechars);
}
glPopMatrix();
glPopAttrib();
}
void OglRenderer::renderPixmap(symbolObj *symbol, double x, double y,
double angle, double scale)
{
makeCurrent();
float zoomX, zoomY;
glGetFloatv(GL_ZOOM_X, &zoomX);
glGetFloatv(GL_ZOOM_Y, &zoomY);
GLubyte* imgdata = symbol->pixmap_buffer->data.rgba.pixels;
glPixelZoom(zoomX*scale, zoomY*scale);
glRasterPos2d(x-symbol->pixmap_buffer->width/2, y-symbol->pixmap_buffer->height/2);
glDrawPixels(symbol->pixmap_buffer->width, symbol->pixmap_buffer->height, GL_BGRA, GL_UNSIGNED_BYTE, imgdata);
glPixelZoom(zoomX, zoomY);
}
void OglRenderer::renderEllipse(double x, double y, double angle, double width, double height,
colorObj *color, colorObj *outlinecolor, double outlinewidth = 1.0)
{
makeCurrent();
if (outlinecolor && MS_VALID_COLOR(*outlinecolor)) {
glEnable(GL_DEPTH_TEST);
glPushMatrix();
glTranslated(0, 0, 1);
}
setColor(color);
glPushMatrix();
if (angle) {
glRotated(angle, 0, 0, 1);
}
glTranslated(x, y, 0);
glScaled(width / SHAPE_CIRCLE_RADIUS / 2, height / SHAPE_CIRCLE_RADIUS / 2, 1);
glCallList(shapes[circle]);
glPopMatrix();
if (outlinecolor != NULL && MS_VALID_COLOR(*outlinecolor)) {
glPopMatrix();
glPushMatrix();
glTranslated(0, 0, -1);
renderEllipse(x, y, angle, width + outlinewidth, height, outlinecolor, NULL, 0);
glPopMatrix();
glDisable(GL_DEPTH_TEST);
}
}
bool OglRenderer::loadLine(shapeObj* shape, double width, int patternlength,
double* pattern)
{
/* OglCache* cache = (OglCache*) shape->renderer_cache;
if (cache->patternDistance == 0)
{
for (int i = 0; i < patternlength; i++)
{
cache->patternDistance += pattern[i];
}
}
GLubyte imgdata[TEX_SIZE * TEX_SIZE * 4];
int pow2length = min(max(NextPowerOf2(cache->patternDistance), MIN_TEX_SIZE), TEX_SIZE);
int pow2width = min(max(NextPowerOf2(width), MIN_TEX_SIZE), TEX_SIZE);
double lengthScale = (double) pow2length / cache->patternDistance;
glColor3d(0, 0, 0);
double place = 0;
double xRadii = width / 2 * lengthScale;
double yRadii = pow2width / 2;
for (int i = 0; i < patternlength; i++)
{
double next = pattern[i] * lengthScale;
if (i % 2 == 0)
{
glPushMatrix();
glTranslated(place + xRadii, yRadii, 0);
glScaled(xRadii / SHAPE_CIRCLE_RADIUS,
yRadii / SHAPE_CIRCLE_RADIUS, 0);
glCallList(shapes[circle]);
glPopMatrix();
glBegin(GL_QUADS);
glVertex2d(place + pow2width / 2, 0);
glVertex2d(place + next - pow2width / 2, 0);
glVertex2d(place + next - pow2width / 2, pow2width);
glVertex2d(place + pow2width / 2, pow2width);
glEnd();
glPushMatrix();
glTranslated(place + next - xRadii, yRadii, 0);
glScaled(xRadii / SHAPE_CIRCLE_RADIUS,
yRadii / SHAPE_CIRCLE_RADIUS, 0);
glCallList(shapes[circle]);
glPopMatrix();
}
place += next;
}
glReadPixels(0, 0, pow2length, pow2width, GL_RGBA, GL_UNSIGNED_BYTE,
imgdata);
//createTexture(pow2length, pow2width, GL_ALPHA, imgdata);*/
return true;
}
FTFont* OglRenderer::getFTFont(const char* font, double size)
{
FTFont** face = &fontCache[font][size];
if (*face == NULL && ifstream(font)) {
*face = new FTGLTextureFont( font );
if (*face) {
(*face)->UseDisplayList(true);
(*face)->FaceSize(size*SIZE_RES);
}
}
return *face;
}
GLvoid CALLBACK beginCallback(GLenum which)
{
glBegin(which);
}
GLvoid CALLBACK errorCallback(GLenum errorCode)
{
const GLubyte *estring;
estring = gluErrorString(errorCode);
fprintf(stderr, "Tessellation Error: %d %s\n", errorCode, estring);
exit(0);
}
GLvoid CALLBACK endCallback(void)
{
glEnd();
}
GLvoid CALLBACK combineDataCallback(GLdouble coords[3], GLdouble* vertex_data[4],
GLfloat weight[4], void** dataOut, void* polygon_data)
{
GLdouble *vertex;
vertex = (GLdouble *) malloc(5 * sizeof(GLdouble));
vertex[0] = coords[0];
vertex[1] = coords[1];
vertex[2] = coords[2];
vertex[3] = vertex_data[0][3];
vertex[4] = vertex_data[0][4];
*dataOut = vertex;
}
GLvoid CALLBACK vertexCallback(GLdouble *vertex)
{
if (vertex[3] > 0) glTexCoord2d(vertex[0]/vertex[3], vertex[1]/vertex[4]);
glVertex3dv(vertex);
}
void OglRenderer::createShapes()
{
double da = MS_MIN(OGL_PI / 2, OGL_PI / SHAPE_CIRCLE_RES);
GLuint circle = glGenLists(1);
glNewList(circle, GL_COMPILE);
glBegin(GL_TRIANGLE_FAN);
glVertex2d(0, 0);
for (double a = 0.0; a <= 2 * OGL_PI; a += da) {
glVertex2d(0 + cos(a) * SHAPE_CIRCLE_RADIUS, 0 + sin(a) * SHAPE_CIRCLE_RADIUS);
}
glVertex2d(0 + SHAPE_CIRCLE_RADIUS, 0);
glEnd();
glEndList();
shapes.push_back(circle);
}
void OglRenderer::makeCurrent()
{
context->makeCurrent();
}
#endif
Jump to Line
Something went wrong with that request. Please try again.