diff options
author | Marius Kintel <marius@kintel.net> | 2011-07-31 01:12:27 (GMT) |
---|---|---|
committer | Marius Kintel <marius@kintel.net> | 2011-07-31 01:12:27 (GMT) |
commit | 2b0035175dd3bc5c66a3350cab6e9f7f7b8f01d4 (patch) | |
tree | 5bfb1c7f9f37c04d5717c3eec62bd4fb45e947b8 | |
parent | 6882228058d313bb7b98fddd90239bdb1a3e25ef (diff) |
One step further on a Qt-free offscreen renderer
-rw-r--r-- | tests/CMakeLists.txt | 22 | ||||
-rw-r--r-- | tests/OffscreenContext.h | 13 | ||||
-rw-r--r-- | tests/OffscreenContext.mm | 198 | ||||
-rw-r--r-- | tests/OffscreenView.cc | 232 | ||||
-rw-r--r-- | tests/OffscreenView.h | 34 | ||||
-rw-r--r-- | tests/cgaltest.cc | 16 | ||||
-rw-r--r-- | tests/opencsgtest.cc | 169 |
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(); |