summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarius Kintel <marius@kintel.net>2011-07-31 01:12:27 (GMT)
committerMarius Kintel <marius@kintel.net>2011-07-31 01:12:27 (GMT)
commit2b0035175dd3bc5c66a3350cab6e9f7f7b8f01d4 (patch)
tree5bfb1c7f9f37c04d5717c3eec62bd4fb45e947b8
parent6882228058d313bb7b98fddd90239bdb1a3e25ef (diff)
One step further on a Qt-free offscreen renderer
-rw-r--r--tests/CMakeLists.txt22
-rw-r--r--tests/OffscreenContext.h13
-rw-r--r--tests/OffscreenContext.mm198
-rw-r--r--tests/OffscreenView.cc232
-rw-r--r--tests/OffscreenView.h34
-rw-r--r--tests/cgaltest.cc16
-rw-r--r--tests/opencsgtest.cc169
7 files changed, 522 insertions, 162 deletions
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index c5c1104..74d3df2 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -12,6 +12,11 @@ endif()
# Build test apps
#
+# Mac OS X
+if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+ FIND_LIBRARY(COCOA_LIBRARY Cocoa)
+endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+
# Qt4
find_package(OpenGL)
find_package(Qt4 COMPONENTS QtCore QtGui QtOpenGL REQUIRED)
@@ -98,7 +103,7 @@ set(COMMON_SOURCES
../src/progress.cc
../src/nodedumper.cc
../src/traverser.cc
- ../src/PolySetRenderer.cc
+ ../src/PolySetEvaluator.cc
../src/Tree.cc
${FLEX_OpenSCADlexer_OUTPUTS}
${BISON_OpenSCADparser_OUTPUTS})
@@ -118,7 +123,7 @@ target_link_libraries(csgtexttest ${QT_LIBRARIES} ${OPENGL_LIBRARY})
#
# csgtermtest
#
-add_executable(csgtermtest csgtermtest.cc ../src/CSGTermRenderer.cc ${COMMON_SOURCES})
+add_executable(csgtermtest csgtermtest.cc ../src/CSGTermEvaluator.cc ${COMMON_SOURCES})
target_link_libraries(csgtermtest ${QT_LIBRARIES} ${OPENGL_LIBRARY})
if (NOT $ENV{MACOSX_DEPLOY_DIR} STREQUAL "")
@@ -131,8 +136,8 @@ include_directories(${CGAL_INCLUDE_DIRS})
#
# cgaltest
#
-add_executable(cgaltest cgaltest.cc ../src/CSGTermRenderer.cc ../src/CGALRenderer.cc
- ../src/PolySetCGALRenderer.cc ../src/qhash.cc ../src/nef2dxf.cc
+add_executable(cgaltest cgaltest.cc ../src/CSGTermEvaluator.cc ../src/CGALEvaluator.cc
+ ../src/PolySetCGALEvaluator.cc ../src/qhash.cc ../src/nef2dxf.cc
../src/cgaladv_minkowski2.cc ../src/cgaladv_minkowski3.cc ${COMMON_SOURCES})
set_target_properties(cgaltest PROPERTIES COMPILE_FLAGS "-DENABLE_CGAL ${CGAL_CXX_FLAGS_INIT}")
target_link_libraries(cgaltest ${CGAL_LIBRARY} ${CGAL_3RD_PARTY_LIBRARIES} ${QT_LIBRARIES} ${OPENGL_LIBRARY})
@@ -140,14 +145,13 @@ target_link_libraries(cgaltest ${CGAL_LIBRARY} ${CGAL_3RD_PARTY_LIBRARIES} ${QT_
#
# opencsgtest
#
-QT4_WRAP_CPP(MOC_SRC_opencsgtest ../src/GLView.h)
-add_executable(opencsgtest opencsgtest.cc ${MOC_SRC_opencsgtest} ../src/glview.cc
- ../src/render-opencsg.cc ../src/CSGTermRenderer.cc ../src/CGALRenderer.cc
- ../src/PolySetCGALRenderer.cc ../src/qhash.cc ../src/nef2dxf.cc
+add_executable(opencsgtest opencsgtest.cc OffscreenView.cc OffscreenContext.mm
+ ../src/opencsgrenderer.cc ../src/CSGTermEvaluator.cc ../src/CGALEvaluator.cc
+ ../src/PolySetCGALEvaluator.cc ../src/qhash.cc ../src/nef2dxf.cc
../src/cgaladv_minkowski2.cc ../src/cgaladv_minkowski3.cc
${COMMON_SOURCES})
set_target_properties(opencsgtest PROPERTIES COMPILE_FLAGS "-DENABLE_OPENCSG -DENABLE_CGAL ${CGAL_CXX_FLAGS_INIT}")
-target_link_libraries(opencsgtest ${CGAL_LIBRARY} ${CGAL_3RD_PARTY_LIBRARIES} ${QT_LIBRARIES} ${OPENCSG_LIBRARY} ${GLEW_LIBRARY} ${OPENGL_LIBRARY})
+target_link_libraries(opencsgtest ${CGAL_LIBRARY} ${CGAL_3RD_PARTY_LIBRARIES} ${QT_LIBRARIES} ${OPENCSG_LIBRARY} ${GLEW_LIBRARY} ${COCOA_LIBRARY} ${OPENGL_LIBRARY})
#
# This functions adds cmd-line tests given files.
diff --git a/tests/OffscreenContext.h b/tests/OffscreenContext.h
new file mode 100644
index 0000000..59b6e2d
--- /dev/null
+++ b/tests/OffscreenContext.h
@@ -0,0 +1,13 @@
+#ifndef OFFSCREENCONTEXT_H_
+#define OFFSCREENCONTEXT_H_
+
+#include <OpenGL/OpenGL.h>
+#include <iostream> // for error output
+
+#define REPORTGLERROR(task) { GLenum tGLErr = glGetError(); if (tGLErr != GL_NO_ERROR) { std::cout << "OpenGL error " << tGLErr << " while " << task << "\n"; } }
+
+struct OffscreenContext *create_offscreen_context(int w, int h);
+bool teardown_offscreen_context(OffscreenContext *ctx);
+bool save_framebuffer(OffscreenContext *ctx, const char *filename);
+
+#endif
diff --git a/tests/OffscreenContext.mm b/tests/OffscreenContext.mm
new file mode 100644
index 0000000..7ff7772
--- /dev/null
+++ b/tests/OffscreenContext.mm
@@ -0,0 +1,198 @@
+#include "OffscreenContext.h"
+
+#import <OpenGL/OpenGL.h>
+#import <OpenGL/glu.h> // for gluCheckExtension
+#import <AppKit/AppKit.h> // for NSOpenGL...
+
+// Simple error reporting macros to help keep the sample code clean
+#define REPORT_ERROR_AND_EXIT(desc) { std::cout << desc << "\n"; return false; }
+#define NULL_ERROR_EXIT(test, desc) { if (!test) REPORT_ERROR_AND_EXIT(desc); }
+
+struct OffscreenContext
+{
+ NSOpenGLContext *openGLContext;
+ NSAutoreleasePool *pool;
+ int width;
+ int height;
+};
+
+
+OffscreenContext *create_offscreen_context(int w, int h)
+{
+ OffscreenContext *ctx = new OffscreenContext;
+ ctx->width = w;
+ ctx->height = h;
+
+ ctx->pool = [NSAutoreleasePool new];
+
+ /*
+ * Create an OpenGL context just so that OpenGL calls will work. I'm not
+ using it for actual rendering.
+ */
+
+ NSOpenGLPixelFormatAttribute attributes[] = {
+ NSOpenGLPFAPixelBuffer,
+ NSOpenGLPFANoRecovery,
+ NSOpenGLPFAAccelerated,
+ NSOpenGLPFADepthSize, 24,
+ (NSOpenGLPixelFormatAttribute) 0
+ };
+ NSOpenGLPixelFormat* pixFormat = [[[NSOpenGLPixelFormat
+ alloc] initWithAttributes:attributes] autorelease];
+ // Create the OpenGL context to render with (with color and depth buffers)
+ ctx->openGLContext = [[NSOpenGLContext alloc] initWithFormat:pixFormat
+ shareContext:nil];
+ NULL_ERROR_EXIT(ctx->openGLContext, "Unable to create NSOpenGLContext");
+
+ [ctx->openGLContext makeCurrentContext];
+
+ /*
+ * Test if framebuffer objects are supported
+ */
+ const GLubyte* strExt = glGetString(GL_EXTENSIONS);
+ GLboolean fboSupported = gluCheckExtension((const GLubyte*)"GL_EXT_framebuffer_object", strExt);
+ if (!fboSupported)
+ REPORT_ERROR_AND_EXIT("Your system does not support framebuffer extension - unable to render scene");
+ /*
+ * Create an FBO
+ */
+ GLuint renderBuffer = 0;
+ GLuint depthBuffer = 0;
+ // Depth buffer to use for depth testing - optional if you're not using depth testing
+ glGenRenderbuffersEXT(1, &depthBuffer);
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthBuffer);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, w, h);
+ REPORTGLERROR("creating depth render buffer");
+
+ // Render buffer to use for imaging
+ glGenRenderbuffersEXT(1, &renderBuffer);
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderBuffer);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, w, h);
+ REPORTGLERROR("creating color render buffer");
+ GLuint fbo = 0;
+ glGenFramebuffersEXT(1, &fbo);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
+ REPORTGLERROR("binding framebuffer");
+
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+ GL_RENDERBUFFER_EXT, renderBuffer);
+ REPORTGLERROR("specifying color render buffer");
+
+ if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) !=
+ GL_FRAMEBUFFER_COMPLETE_EXT)
+ REPORT_ERROR_AND_EXIT("Problem with OpenGL framebuffer after specifying color render buffer.");
+
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
+ GL_RENDERBUFFER_EXT, depthBuffer);
+ REPORTGLERROR("specifying depth render buffer");
+
+ if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) !=
+ GL_FRAMEBUFFER_COMPLETE_EXT)
+ REPORT_ERROR_AND_EXIT("Problem with OpenGL framebuffer after specifying depth render buffer.");
+
+ return ctx;
+}
+
+bool teardown_offscreen_context(OffscreenContext *ctx)
+{
+ // "un"bind my FBO
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+
+ /*
+ * Cleanup
+ */
+ [ctx->openGLContext clearDrawable];
+ [ctx->openGLContext release];
+
+ [ctx->pool release];
+ return true;
+}
+
+bool save_framebuffer(OffscreenContext *ctx, const char *filename)
+{
+ /*
+ * Extract the resulting rendering as an image
+ */
+
+ int samplesPerPixel = 4; // R, G, B and A
+ int rowBytes = samplesPerPixel * ctx->width;
+ char* bufferData = (char*)malloc(rowBytes * ctx->height);
+ if (!bufferData) {
+ std::cerr << "Unable to allocate buffer for image extraction.";
+ return 1;
+ }
+ glReadPixels(0, 0, ctx->width, ctx->height, GL_BGRA, GL_UNSIGNED_BYTE,
+ bufferData);
+ REPORTGLERROR("reading pixels from framebuffer");
+
+ // Flip it vertically - images read from OpenGL buffers are upside-down
+ char* flippedBuffer = (char*)malloc(rowBytes * ctx->height);
+ if (!flippedBuffer) {
+ std::cout << "Unable to allocate flipped buffer for corrected image.";
+ return 1;
+ }
+ for (int i = 0 ; i < ctx->height ; i++) {
+ bcopy(bufferData + i * rowBytes, flippedBuffer + (ctx->height - i - 1) *
+ rowBytes, rowBytes);
+ }
+
+ /*
+ * Output the image to a file
+ */
+ CGColorSpaceRef colorSpace =
+ CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+ CGBitmapInfo bitmapInfo = kCGImageAlphaNoneSkipFirst |
+ kCGBitmapByteOrder32Little; // XRGB Little Endian
+ int bitsPerComponent = 8;
+ CGContextRef contextRef = CGBitmapContextCreate(flippedBuffer,
+ ctx->width, ctx->height, bitsPerComponent, rowBytes,
+ colorSpace, bitmapInfo);
+ if (!contextRef) {
+ std::cerr << "Unable to create CGContextRef.";
+ return false;
+ }
+
+ CGImageRef imageRef = CGBitmapContextCreateImage(contextRef);
+ if (!imageRef) {
+ std::cerr << "Unable to create CGImageRef.";
+ return false;
+ }
+ Boolean isDirectory = false;
+ CFStringRef fname = CFStringCreateWithCString(kCFAllocatorDefault, filename, kCFStringEncodingUTF8);
+ CFURLRef fileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
+ fname, kCFURLPOSIXPathStyle, isDirectory);
+ if (!fileURL) {
+ std::cerr << "Unable to create file URL ref.";
+ return false;
+ }
+ CFIndex fileImageIndex = 1;
+ CFMutableDictionaryRef fileDict = NULL;
+ CFStringRef fileUTType = kUTTypeJPEG;
+ // Create an image destination opaque reference for authoring an image file
+ CGImageDestinationRef imageDest = CGImageDestinationCreateWithURL(fileURL,
+ fileUTType,
+ fileImageIndex,
+ fileDict);
+ if (!imageDest) {
+ std::cerr << "Unable to create CGImageDestinationRef.";
+ return false;
+ }
+ CFIndex capacity = 1;
+ CFMutableDictionaryRef imageProps =
+ CFDictionaryCreateMutable(kCFAllocatorDefault,
+ capacity,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ CGImageDestinationAddImage(imageDest, imageRef, imageProps);
+ CGImageDestinationFinalize(imageDest);
+
+ free(flippedBuffer);
+ free(bufferData);
+ CFRelease(imageDest);
+ CFRelease(fileURL);
+ CFRelease(fname);
+ CFRelease(imageProps);
+ CGColorSpaceRelease( colorSpace );
+ CGImageRelease(imageRef);
+ return true;
+}
diff --git a/tests/OffscreenView.cc b/tests/OffscreenView.cc
new file mode 100644
index 0000000..b7ee8c7
--- /dev/null
+++ b/tests/OffscreenView.cc
@@ -0,0 +1,232 @@
+#include <GL/glew.h>
+#include "OffscreenView.h"
+#include "Renderer.h"
+#include "OffscreenContext.h"
+#include <math.h>
+
+#define FAR_FAR_AWAY 100000.0
+
+OffscreenView::OffscreenView(size_t width, size_t height)
+ : orthomode(false), showaxes(false), showfaces(false), showedges(false), viewer_distance(500)
+{
+ this->ctx = create_offscreen_context(width, height);
+ initializeGL();
+ resizeGL(width, height);
+}
+
+OffscreenView::~OffscreenView()
+{
+ teardown_offscreen_context(this->ctx);
+}
+
+void OffscreenView::setRenderer(Renderer* r)
+{
+ this->renderer = r;
+}
+
+void OffscreenView::initializeGL()
+{
+ glEnable(GL_DEPTH_TEST);
+ glDepthRange(-FAR_FAR_AWAY, +FAR_FAR_AWAY);
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ GLfloat light_diffuse[] = {1.0, 1.0, 1.0, 1.0};
+ GLfloat light_position0[] = {-1.0, -1.0, +1.0, 0.0};
+ GLfloat light_position1[] = {+1.0, +1.0, -1.0, 0.0};
+
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
+ glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
+ glEnable(GL_LIGHT0);
+ glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse);
+ glLightfv(GL_LIGHT1, GL_POSITION, light_position1);
+ glEnable(GL_LIGHT1);
+ glEnable(GL_LIGHTING);
+ glEnable(GL_NORMALIZE);
+
+ glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
+ glEnable(GL_COLOR_MATERIAL);
+
+#ifdef ENABLE_OPENCSG
+ const char *openscad_disable_gl20_env = getenv("OPENSCAD_DISABLE_GL20");
+ if (openscad_disable_gl20_env && !strcmp(openscad_disable_gl20_env, "0"))
+ openscad_disable_gl20_env = NULL;
+ if (glewIsSupported("GL_VERSION_2_0") && openscad_disable_gl20_env == NULL)
+ {
+ const char *vs_source =
+ "uniform float xscale, yscale;\n"
+ "attribute vec3 pos_b, pos_c;\n"
+ "attribute vec3 trig, mask;\n"
+ "varying vec3 tp, tr;\n"
+ "varying float shading;\n"
+ "void main() {\n"
+ " vec4 p0 = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
+ " vec4 p1 = gl_ModelViewProjectionMatrix * vec4(pos_b, 1.0);\n"
+ " vec4 p2 = gl_ModelViewProjectionMatrix * vec4(pos_c, 1.0);\n"
+ " float a = distance(vec2(xscale*p1.x/p1.w, yscale*p1.y/p1.w), vec2(xscale*p2.x/p2.w, yscale*p2.y/p2.w));\n"
+ " float b = distance(vec2(xscale*p0.x/p0.w, yscale*p0.y/p0.w), vec2(xscale*p1.x/p1.w, yscale*p1.y/p1.w));\n"
+ " float c = distance(vec2(xscale*p0.x/p0.w, yscale*p0.y/p0.w), vec2(xscale*p2.x/p2.w, yscale*p2.y/p2.w));\n"
+ " float s = (a + b + c) / 2.0;\n"
+ " float A = sqrt(s*(s-a)*(s-b)*(s-c));\n"
+ " float ha = 2.0*A/a;\n"
+ " gl_Position = p0;\n"
+ " tp = mask * ha;\n"
+ " tr = trig;\n"
+ " vec3 normal, lightDir;\n"
+ " normal = normalize(gl_NormalMatrix * gl_Normal);\n"
+ " lightDir = normalize(vec3(gl_LightSource[0].position));\n"
+ " shading = abs(dot(normal, lightDir));\n"
+ "}\n";
+
+ const char *fs_source =
+ "uniform vec4 color1, color2;\n"
+ "varying vec3 tp, tr, tmp;\n"
+ "varying float shading;\n"
+ "void main() {\n"
+ " gl_FragColor = vec4(color1.r * shading, color1.g * shading, color1.b * shading, color1.a);\n"
+ " if (tp.x < tr.x || tp.y < tr.y || tp.z < tr.z)\n"
+ " gl_FragColor = color2;\n"
+ "}\n";
+
+ GLuint vs = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vs, 1, (const GLchar**)&vs_source, NULL);
+ glCompileShader(vs);
+
+ GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fs, 1, (const GLchar**)&fs_source, NULL);
+ glCompileShader(fs);
+
+ GLuint edgeshader_prog = glCreateProgram();
+ glAttachShader(edgeshader_prog, vs);
+ glAttachShader(edgeshader_prog, fs);
+ glLinkProgram(edgeshader_prog);
+
+ shaderinfo[0] = edgeshader_prog;
+ shaderinfo[1] = glGetUniformLocation(edgeshader_prog, "color1");
+ shaderinfo[2] = glGetUniformLocation(edgeshader_prog, "color2");
+ shaderinfo[3] = glGetAttribLocation(edgeshader_prog, "trig");
+ shaderinfo[4] = glGetAttribLocation(edgeshader_prog, "pos_b");
+ shaderinfo[5] = glGetAttribLocation(edgeshader_prog, "pos_c");
+ shaderinfo[6] = glGetAttribLocation(edgeshader_prog, "mask");
+ shaderinfo[7] = glGetUniformLocation(edgeshader_prog, "xscale");
+ shaderinfo[8] = glGetUniformLocation(edgeshader_prog, "yscale");
+
+ GLenum err = glGetError();
+ if (err != GL_NO_ERROR) {
+ fprintf(stderr, "OpenGL Error: %s\n", gluErrorString(err));
+ }
+
+ GLint status;
+ glGetProgramiv(edgeshader_prog, GL_LINK_STATUS, &status);
+ if (status == GL_FALSE) {
+ int loglen;
+ char logbuffer[1000];
+ glGetProgramInfoLog(edgeshader_prog, sizeof(logbuffer), &loglen, logbuffer);
+ fprintf(stderr, "OpenGL Program Linker Error:\n%.*s", loglen, logbuffer);
+ } else {
+ int loglen;
+ char logbuffer[1000];
+ glGetProgramInfoLog(edgeshader_prog, sizeof(logbuffer), &loglen, logbuffer);
+ if (loglen > 0) {
+ fprintf(stderr, "OpenGL Program Link OK:\n%.*s", loglen, logbuffer);
+ }
+ glValidateProgram(edgeshader_prog);
+ glGetProgramInfoLog(edgeshader_prog, sizeof(logbuffer), &loglen, logbuffer);
+ if (loglen > 0) {
+ fprintf(stderr, "OpenGL Program Validation results:\n%.*s", loglen, logbuffer);
+ }
+ }
+ }
+#endif /* ENABLE_OPENCSG */
+}
+
+void OffscreenView::resizeGL(int w, int h)
+{
+#ifdef ENABLE_OPENCSG
+ shaderinfo[9] = w;
+ shaderinfo[10] = h;
+#endif
+ glViewport(0, 0, w, h);
+ w_h_ratio = sqrt((double)w / (double)h);
+ setupPerspective();
+}
+
+void OffscreenView::setupPerspective()
+{
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum(-w_h_ratio, +w_h_ratio, -(1/w_h_ratio), +(1/w_h_ratio), +10.0, +FAR_FAR_AWAY);
+}
+
+void OffscreenView::setupOrtho(double distance, bool offset)
+{
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ if(offset)
+ glTranslated(-0.8, -0.8, 0);
+ double l = distance/10;
+ glOrtho(-w_h_ratio*l, +w_h_ratio*l,
+ -(1/w_h_ratio)*l, +(1/w_h_ratio)*l,
+ -FAR_FAR_AWAY, +FAR_FAR_AWAY);
+}
+
+void OffscreenView::paintGL()
+{
+ glEnable(GL_LIGHTING);
+
+ if (orthomode)
+ setupOrtho(viewer_distance);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glClearColor(1.0, 1.0, 0.92, 0.0);
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+ gluLookAt(0.0, -viewer_distance, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
+
+// glTranslated(object_trans_x, object_trans_y, object_trans_z);
+
+ // glRotated(object_rot_x, 1.0, 0.0, 0.0);
+ // glRotated(object_rot_y, 0.0, 1.0, 0.0);
+ // glRotated(object_rot_z, 0.0, 0.0, 1.0);
+
+ // Large gray axis cross inline with the model
+ // FIXME: This is always gray - adjust color to keep contrast with background
+ if (showaxes)
+ {
+ glLineWidth(1);
+ glColor3d(0.5, 0.5, 0.5);
+ glBegin(GL_LINES);
+ double l = viewer_distance/10;
+ glVertex3d(-l, 0, 0);
+ glVertex3d(+l, 0, 0);
+ glVertex3d(0, -l, 0);
+ glVertex3d(0, +l, 0);
+ glVertex3d(0, 0, -l);
+ glVertex3d(0, 0, +l);
+ glEnd();
+ }
+
+ glDepthFunc(GL_LESS);
+ glCullFace(GL_BACK);
+ glDisable(GL_CULL_FACE);
+
+ glLineWidth(2);
+ glColor3d(1.0, 0.0, 0.0);
+
+ if (this->renderer) {
+#if defined(ENABLE_MDI) && defined(ENABLE_OPENCSG)
+ // FIXME: This belongs in the OpenCSG renderer, but it doesn't know about this ID yet
+ OpenCSG::setContext(this->opencsg_id);
+#endif
+ this->renderer->draw(showfaces, showedges);
+ }
+}
+
+bool OffscreenView::save(const char *filename)
+{
+ return save_framebuffer(this->ctx, filename);
+}
diff --git a/tests/OffscreenView.h b/tests/OffscreenView.h
new file mode 100644
index 0000000..6531bcf
--- /dev/null
+++ b/tests/OffscreenView.h
@@ -0,0 +1,34 @@
+#ifndef OFFSCREENVIEW_H_
+#define OFFSCREENVIEW_H_
+
+#include "OffscreenContext.h"
+#include <stdint.h>
+
+class OffscreenView
+{
+public:
+ OffscreenView(size_t width, size_t height);
+ ~OffscreenView();
+ void setRenderer(class Renderer* r);
+
+ void initializeGL();
+ void resizeGL(int w, int h);
+ void setupPerspective();
+ void setupOrtho(double distance,bool offset=false);
+ void paintGL();
+ bool save(const char *filename);
+
+ GLint shaderinfo[11];
+private:
+ Renderer *renderer;
+ class OffscreenContext *ctx;
+ double w_h_ratio;
+
+ bool orthomode;
+ bool showaxes;
+ bool showfaces;
+ bool showedges;
+ float viewer_distance;
+};
+
+#endif
diff --git a/tests/cgaltest.cc b/tests/cgaltest.cc
index 1466837..df03a43 100644
--- a/tests/cgaltest.cc
+++ b/tests/cgaltest.cc
@@ -32,8 +32,8 @@
#include "export.h"
#include "builtin.h"
#include "Tree.h"
-#include "CGALRenderer.h"
-#include "PolySetCGALRenderer.h"
+#include "CGALEvaluator.h"
+#include "PolySetCGALEvaluator.h"
#include <QApplication>
#include <QFile>
@@ -72,9 +72,9 @@ void cgalTree(Tree &tree)
{
assert(tree.root());
- CGALRenderer renderer(cache, tree);
- Traverser render(renderer, *tree.root(), Traverser::PRE_AND_POSTFIX);
- render.execute();
+ CGALEvaluator evaluator(cache, tree);
+ Traverser evaluate(evaluator, *tree.root(), Traverser::PRE_AND_POSTFIX);
+ evaluate.execute();
}
int main(int argc, char **argv)
@@ -163,10 +163,10 @@ int main(int argc, char **argv)
Tree tree(root_node);
QHash<std::string, CGAL_Nef_polyhedron> cache;
- CGALRenderer cgalrenderer(cache, tree);
- PolySetCGALRenderer psrenderer(cgalrenderer);
+ CGALEvaluator cgalevaluator(cache, tree);
+ PolySetCGALEvaluator psevaluator(cgalevaluator);
- CGAL_Nef_polyhedron N = cgalrenderer.renderCGALMesh(*root_node);
+ CGAL_Nef_polyhedron N = cgalevaluator.evaluateCGALMesh(*root_node);
QDir::setCurrent(original_path.absolutePath());
QTextStream outstream(stdout);
diff --git a/tests/opencsgtest.cc b/tests/opencsgtest.cc
index 9381c54..4d69650 100644
--- a/tests/opencsgtest.cc
+++ b/tests/opencsgtest.cc
@@ -5,15 +5,15 @@
#include "module.h"
#include "polyset.h"
#include "Tree.h"
-#include "CSGTermRenderer.h"
-#include "CGALRenderer.h"
-#include "PolySetCGALRenderer.h"
+#include "CSGTermEvaluator.h"
+#include "CGALEvaluator.h"
+#include "PolySetCGALEvaluator.h"
+
+#include "OpenCSGRenderer.h"
#include "csgterm.h"
-#include "render-opencsg.h"
#include <GL/glew.h>
-#include "GLView.h"
-#include "mainwindow.h"
+#include "OffscreenView.h"
#include <QApplication>
#include <QFile>
@@ -56,130 +56,9 @@ struct CsgInfo
CSGChain *highlights_chain;
std::vector<CSGTerm*> background_terms;
CSGChain *background_chain;
- GLView *glview;
+ OffscreenView *glview;
};
-static void renderGLThrownTogetherChain(CSGChain *chain, bool highlight, bool background, bool fberror)
-{
- glDepthFunc(GL_LEQUAL);
- QHash<QPair<PolySet*,double*>,int> polySetVisitMark;
- bool showEdges = false;
- for (int i = 0; i < chain->polysets.size(); i++) {
- if (polySetVisitMark[QPair<PolySet*,double*>(chain->polysets[i], chain->matrices[i])]++ > 0)
- continue;
- double *m = chain->matrices[i];
- glPushMatrix();
- glMultMatrixd(m);
- int csgmode = chain->types[i] == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL;
- if (highlight) {
- chain->polysets[i]->render_surface(PolySet::COLORMODE_HIGHLIGHT, PolySet::csgmode_e(csgmode + 20), m);
- if (showEdges) {
- glDisable(GL_LIGHTING);
- chain->polysets[i]->render_edges(PolySet::COLORMODE_HIGHLIGHT, PolySet::csgmode_e(csgmode + 20));
- glEnable(GL_LIGHTING);
- }
- } else if (background) {
- chain->polysets[i]->render_surface(PolySet::COLORMODE_BACKGROUND, PolySet::csgmode_e(csgmode + 10), m);
- if (showEdges) {
- glDisable(GL_LIGHTING);
- chain->polysets[i]->render_edges(PolySet::COLORMODE_BACKGROUND, PolySet::csgmode_e(csgmode + 10));
- glEnable(GL_LIGHTING);
- }
- } else if (fberror) {
- if (highlight) {
- chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode + 20), m);
- } else if (background) {
- chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode + 10), m);
- } else {
- chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode), m);
- }
- } else if (m[16] >= 0 || m[17] >= 0 || m[18] >= 0 || m[19] >= 0) {
- glColor4d(m[16], m[17], m[18], m[19]);
- chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode), m);
- if (showEdges) {
- glDisable(GL_LIGHTING);
- glColor4d((m[16]+1)/2, (m[17]+1)/2, (m[18]+1)/2, 1.0);
- chain->polysets[i]->render_edges(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode));
- glEnable(GL_LIGHTING);
- }
- } else if (chain->types[i] == CSGTerm::TYPE_DIFFERENCE) {
- chain->polysets[i]->render_surface(PolySet::COLORMODE_CUTOUT, PolySet::csgmode_e(csgmode), m);
- if (showEdges) {
- glDisable(GL_LIGHTING);
- chain->polysets[i]->render_edges(PolySet::COLORMODE_CUTOUT, PolySet::csgmode_e(csgmode));
- glEnable(GL_LIGHTING);
- }
- } else {
- chain->polysets[i]->render_surface(PolySet::COLORMODE_MATERIAL, PolySet::csgmode_e(csgmode), m);
- if (showEdges) {
- glDisable(GL_LIGHTING);
- chain->polysets[i]->render_edges(PolySet::COLORMODE_MATERIAL, PolySet::csgmode_e(csgmode));
- glEnable(GL_LIGHTING);
- }
- }
- glPopMatrix();
- }
-}
-
-static void renderGLThrownTogether(void *vp)
-{
- CsgInfo *csgInfo = (CsgInfo *)vp;
- if (csgInfo->root_chain) {
- glEnable(GL_CULL_FACE);
- glCullFace(GL_BACK);
- renderGLThrownTogetherChain(csgInfo->root_chain, false, false, false);
- glCullFace(GL_FRONT);
- glColor3ub(255, 0, 255);
- renderGLThrownTogetherChain(csgInfo->root_chain, false, false, true);
- glDisable(GL_CULL_FACE);
- }
- if (csgInfo->background_chain)
- renderGLThrownTogetherChain(csgInfo->background_chain, false, true, false);
- if (csgInfo->highlights_chain)
- renderGLThrownTogetherChain(csgInfo->highlights_chain, true, false, false);
-}
-
-static void renderGLviaOpenCSG(void *vp)
-{
- CsgInfo *csgInfo = (CsgInfo *)vp;
-
- if (csgInfo->root_chain) {
- glEnable(GL_CULL_FACE);
- glCullFace(GL_BACK);
- glDepthFunc(GL_LEQUAL);
- QHash<QPair<PolySet*,double*>,int> polySetVisitMark;
- bool showEdges = false;
- int i = 1;
- double *m = csgInfo->root_chain->matrices[i];
- glPushMatrix();
- glMultMatrixd(m);
- int csgmode = csgInfo->root_chain->types[i] == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL;
- csgInfo->root_chain->polysets[i]->render_surface(PolySet::COLORMODE_MATERIAL, PolySet::csgmode_e(csgmode), m);
- glPopMatrix();
- }
-
- // static bool glew_initialized = false;
- // if (!glew_initialized) {
- // glew_initialized = true;
- // glewInit();
- // }
-#ifdef ENABLE_MDI
- OpenCSG::setContext(csgInfo->glview->opencsg_id);
-#endif
- if (csgInfo->root_chain) {
- renderCSGChainviaOpenCSG(csgInfo->root_chain, NULL, false, false);
- GLint *shaderinfo = csgInfo->glview->shaderinfo;
- if (!shaderinfo[0]) shaderinfo = NULL;
- renderCSGChainviaOpenCSG(csgInfo->root_chain, NULL, false, false);
- if (csgInfo->background_chain) {
- renderCSGChainviaOpenCSG(csgInfo->background_chain, NULL, false, true);
- }
- if (csgInfo->highlights_chain) {
- renderCSGChainviaOpenCSG(csgInfo->highlights_chain, NULL, true, false);
- }
- }
-}
-
int main(int argc, char *argv[])
{
if (argc != 2) {
@@ -267,10 +146,10 @@ int main(int argc, char *argv[])
Tree tree(root_node);
QHash<std::string, CGAL_Nef_polyhedron> cache;
- CGALRenderer cgalrenderer(cache, tree);
- PolySetCGALRenderer psrenderer(cgalrenderer);
- CSGTermRenderer renderer(tree);
- CSGTerm *root_raw_term = renderer.renderCSGTerm(*root_node, NULL, NULL);
+ CGALEvaluator cgalevaluator(cache, tree);
+ PolySetCGALEvaluator psevaluator(cgalevaluator);
+ CSGTermEvaluator evaluator(tree);
+ CSGTerm *root_raw_term = evaluator.evaluateCSGTerm(*root_node, NULL, NULL);
if (!root_raw_term) {
cerr << "Error: CSG generation failed! (no top level object found)\n";
@@ -328,12 +207,7 @@ int main(int argc, char *argv[])
QDir::setCurrent(original_path.absolutePath());
- QGLFormat fmt = QGLFormat::defaultFormat();
-// fmt.setDirectRendering(false);
-// fmt.setDoubleBuffer(false);
-
- csgInfo.glview = new GLView(fmt, NULL);
- csgInfo.glview->makeCurrent();
+ csgInfo.glview = new OffscreenView(256, 256);
glewInit();
cout << "GLEW version " << glewGetString(GLEW_VERSION) << "\n";
@@ -352,14 +226,19 @@ int main(int argc, char *argv[])
cout << "EXT_packed_depth_stencil\n";
}
-// csgInfo.glview->setRenderFunc(renderGLThrownTogether, &csgInfo);
- csgInfo.glview->setRenderFunc(renderGLviaOpenCSG, &csgInfo);
- csgInfo.glview->show();
- csgInfo.glview->hide();
+ OpenCSGRenderer opencsgRenderer(csgInfo.root_chain, csgInfo.highlights_chain, csgInfo.background_chain, csgInfo.glview->shaderinfo);
+// csgInfo.glview->setRenderFunc(thrownTogetherRenderer);
+ csgInfo.glview->setRenderer(&opencsgRenderer);
+
+ csgInfo.glview->paintGL();
+
+ csgInfo.glview->save("out.png");
+
+// FIXME: Render & Grab buffer
- QImage img = csgInfo.glview->grabFrameBuffer();
- cout << "Image: " << img.width() << "x" << img.height() << " " << img.format() << "\n";
- img.save("out.png");
+ // QImage img = csgInfo.glview->grabFrameBuffer();
+ // cout << "Image: " << img.width() << "x" << img.height() << " " << img.format() << "\n";
+ // img.save("out.png");
destroy_builtin_functions();
destroy_builtin_modules();
contact: Jan Huwald // Impressum