Dave Akers (dla@sgi.com)
Fri, 10 Sep 1999 10:09:06 -0700
  The lookup table provided with Volumizer isn't specific to textures used with
Volumizer. Internally it uses the glColorTableSGI function to set up a LUT that
applies to _all_ textures. If you just want your object to appear in its own colors
(without a LUT translation), then you need to temporarily disable the lookup table
before you draw the object, then re-enable it to render the volume.  This can be
done with the methods voLookupTable::disable() and voLookupTable::enable(). I've
tested this with your example code, and it works just fine..
-Dave
ballard andrews wrote:
> Dave,
>
> I have a problem rendering textured objects with "volumes":
> The volume's color table overides the objects.
> The attached program reuses the demo code.
>
> The first image shows the window when it is first opened.
> voglBasic ${DATAFILE} -sc 1 1 3.2
>
> The second shows that the geometry's texture
> is modified when the volume's grayscale is adjusted.
>
> The third shows that the volume's LUT is applied to the object
> voglBasic ${DATAFILE} -sc 1 1 3.2 -color -lutFile
> ${DATAPATH}/tables/CT1.table
>
> This is probably an OpenGL issue and not a bug in Volumizer -
> tables can be loaded just before the bind operation in the render
> callback using the voLookup::load() method, but how do you get/set
> the objects' texture table?
>
> I attach the file voglMain.cxx which can be compiled
> with the other demo code (add myImage.o).
>
> cheers,
>
> -ba
>
> --
> Dr. A. Ballard Andrews
> Schlumberger Doll Research
> Old Quarry Road
> Ridgefield, CT 06877
> tel: 203-431-5522 fax: 5521
>
>   ------------------------------------------------------------------------
>  [Image]  [Image]  [Image]
>
>   ------------------------------------------------------------------------
> /**
>  * (c) Copyright 1996, 1997, 1998 Silicon Graphics, Inc.
>  * ALL RIGHTS RESERVED
>  * Permission to use, copy, modify, and distribute this software for
>  * any purpose and without fee is hereby granted, provided that the above
>  * copyright notice appear in all copies and that both the copyright notice
>  * and this permission notice appear in supporting documentation, and that
>  * the name of Silicon Graphics, Inc. not be used in advertising
>  * or publicity pertaining to distribution of the software without specific,
>  * written prior permission.
>  *
>  * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
>  * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
>  * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
>  * FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL SILICON
>  * GRAPHICS, INC.  BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
>  * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
>  * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
>  * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
>  * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC.  HAS BEEN
>  * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
>  * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
>  * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
>  *
>  * US Government Users Restricted Rights
>  * Use, duplication, or disclosure by the Government is subject to
>  * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
>  * (c)(1)(ii) of the Rights in Technical Data and Computer Software
>  * clause at DFARS 252.227-7013 and/or in similar or successor
>  * clauses in the FAR or the DOD or NASA FAR Supplement.
>  * Unpublished-- rights reserved under the copyright laws of the
>  * United States.  Contractor/manufacturer is Silicon Graphics,
>  * Inc., 2011 N.  Shoreline Blvd., Mountain View, CA 94039-7311.
>  *
>  * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
>  */
>
> /*
> @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
> \\\\\\\\\\\\\\\\\\\\  -------------------------------   ////////////////////
>
>      Main routine and GUI for Volumizer demos.
>
>      Many of the demos in this directory have a similar structure.  For
>    example, voglBasic and voglRaw provide identical functionality.  The only
>    difference between them is that voglBasic takes a single 3D TIFF file as
>    a command line argument, while voglRaw takes a list of 2D images.  Once the
>    volume is read in, all the other aspects of their behavior is identical.
>    Therefore, voglBasic and voglRaw share the same display routine (namely,
>    my_DrawVolume()), but each provides its own implementation of the volume
>    construction routine (my_InitAppearance()).  On the other hand, voglBasic
>    and voglCache construct the volume in the same way, but display it
>    differently (voglBasic repolygonizes the model for every frame, while
>    voglCache will try to reuse the polygonization from the previous frames
>    if possible).  Thus, voglBasic and voglCache share all the code but
>    my_DrawVolume().
>
>    The elements of the shared structure include:
>
>      my_InitAppearance() read in voxel data and create a BrickSetCollection
>      my_InitGeometry() construct a tetrahedral model of the volume (e.g., cube)
>      my_InitTransient() allocate storage for sampling polygons
>      my_InitGfx() initialize graphics objects (e.g., luts and texture objects)
>      my_DrawVolume() render the volumetric model
>
>    In addition to sharing the structure, the demos refer to a single global
>    instance of my_DataType object, which is used to maintain the state.
>
>    While maintaining similar structure and sharing global data facilitates
>    development and maintenance of the demo code base it does introduce
>    a certain element of coupling between unrelated componenets.
>    Consult voglSimple for example that is free of such dependecies (albeit
>    at the expense of limited functionality).
>
> \\\\\\\\\\\\\\\\\\\\  -------------------------------   ////////////////////
> @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
> */
>
> #include <X11/X.h>
> #include <X11/Intrinsic.h>
> #include <X11/keysym.h>
> #include <Xm/Xm.h>
> #include <GL/gl.h>
> #ifdef SOLARIS_251
> #include <GLw/GLwMDrawA.h>
> #else
> #include <GL/GLwMDrawA.h>
> #endif
> #include <iostream.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <math.h>
>
> #include <vo/AppearanceActions.h>
> #include <vo/GeometryActions.h>
>
> #include "voglDemos.h"
> #include "trackball.h"
>
> GLuint floorTextureObjectId[1];
> unsigned int* read_texture(const char *, int *, int *, int *);
> void drawfloor(GLfloat );
> char *floorFileName;
> unsigned *floortex;
> int texcomps, texwid, texht;
>
> my_DataType my_Data = {
>   voRenderingModeScope::MONOCHROME,     // renderingMode
>   voInterpolationTypeScope::DEFAULT,    // interpolationType
>   voInterleavedArrayTypeScope::V3F,     // interleavedArrayFormat
>   {  64.0,  64.0,  32.0 },              // modelCentroid
>   { 128.0, 128.0, 128.0 },              // modelSize
>   {   1.0,   1.0,   1.0 },              // modelScale
>   -1.0, -1.0,                           // dataRangeLo, dataRangeHi
>   256, 0,                               // lutLength, lutSupplied
>   127, 255, NULL,                       // lutCenter, lutWidth, lutFileName
>   1.0,                                  // samplingRate
>   VO_TRUE,                              // wireframe
>   256,                                  // maxSamplesNumber
>   1,                                    // maxBrickCount
>   NULL,                                 // allVertexData
>   NULL,                                 // aPolygonSetArray
>   8, 40.0, 255.0,                       // tesselation Size MinValue, MaxValue
>   NULL,                                 // aTransientGeometryCache
>   0.75,                                 // transient geometry cache threshold
>   VO_FALSE,                             // report fill rate flag
>   NULL,                                 // aButton3CallbackPtr routine
>   NULL,                                 // volume's geometry
>   NULL,                                 // volume's appearance
>   NULL,                                 // for voglSpaceleap: aSpaceLeapState
> };
>
> // BEGIN LOCAL GUI STATE
>
> static int buttonReleased;
> static float cumulativeQuaternion[4], deltaQuaternion[4];
> static int windowSizeX = 400, windowSizeY = 400;
>
> // END LOCAL GUI STATE
>
> enum myProjectionType { myORTHO, myPERSPECTIVE };
>
> void
> GinitCB(Widget w, XtPointer /* clientData */ , XtPointer /* cal */ )
> {
>     Arg arg;
>     XVisualInfo *vip;
>     GLXContext glCtxt;
>
>     XtSetArg(arg, GLwNvisualInfo, &vip);
>     XtGetValues(w, &arg, 1);
>     glCtxt = glXCreateContext(XtDisplay(w), vip, NULL, GL_TRUE);
>     glXMakeCurrent(XtDisplay(w), XtWindow(w), glCtxt);
>
>     my_InitGfx(my_Data.aTetraSet, my_Data.aVolume);
>
> }
>
> void
> Draw(Widget widget)
> {
>
>     glEnable(GL_DEPTH_TEST);
>
>     glClearColor(0.0, 0.0, 0.0, 1.0);
>     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
>
>     float m[4][4];
>     build_rotmatrix(m, cumulativeQuaternion);
>     glMatrixMode(GL_MODELVIEW);
>     glLoadIdentity();
>     glMultMatrixf(&(m[0][0]));
>     glRotatef(180, 0, 1, 0);  // initial rotations
>     glRotatef( 90, 1, 0, 0);  // initial rotations
>
>     drawfloor(0.5f); /* draw the floor */
>
>     /* draw the volume */
>     glScalef(
>       my_Data.modelScale[0], my_Data.modelScale[1], my_Data.modelScale[2]);
>     glTranslatef(
>       -my_Data.modelCentroid[0],
>       -my_Data.modelCentroid[1],
>       -my_Data.modelCentroid[2]);
>
>     my_DrawVolume(my_Data.aTetraSet, my_Data.aVolume);
>
>     GLwDrawingAreaSwapBuffers(widget);
>
> }
>
> void
> SetUpProjection(myProjectionType type, int width, int height)
> {
>
>   glViewport(0,0,width,height);
>
>   switch( type ) {
>     case myPERSPECTIVE:
>       glMatrixMode(GL_PROJECTION);
>       glLoadIdentity();
>       glFrustum(
>         -0.0025, 0.0025, -0.0025, 0.0025, 0.01, my_Data.modelSize[2]*4);
>       glTranslatef(0, 0, -my_Data.modelSize[2]*3);
>       glMatrixMode(GL_MODELVIEW);
>       break;
>     case myORTHO:
>       glMatrixMode(GL_PROJECTION);
>       glLoadIdentity();
>       glOrtho(
>         -my_Data.modelSize[0] * 0.8, my_Data.modelSize[0] * 0.8,
>         -my_Data.modelSize[1] * 0.8, my_Data.modelSize[1] * 0.8,
>         -my_Data.modelSize[2] * 0.8, my_Data.modelSize[2] * 0.8);
>       glMatrixMode(GL_MODELVIEW);
>       break;
>   }
>
> }
>
> void
> ExposeCB(Widget widget, XtPointer /* clientData */ , XtPointer cal)
> {
>     GLwDrawingAreaCallbackStruct *csp = (GLwDrawingAreaCallbackStruct *) cal;
>
>     SetUpProjection(myPERSPECTIVE,csp->width, csp->height);
>
>     Draw(widget);
>
> }
>
> void
> ResizeCB(Widget widget, XtPointer /* clientData */ , XtPointer cal)
> {
>     GLwDrawingAreaCallbackStruct *csp = (GLwDrawingAreaCallbackStruct *) cal;
>
>     SetUpProjection(myPERSPECTIVE,csp->width, csp->height);
>
>     Draw(widget);
>
>     windowSizeX = csp->width;
>     windowSizeY = csp->height;
>
> }
>
> void
> KeybdInput(XKeyEvent * keyEvent)
> {
>     const float DELTA = 0.1;
>     KeySym keySym;
>     char buf[32];
>
>     XLookupString(keyEvent, buf, 32, &keySym, NULL);
>
>     switch (keySym) {
>     case XK_o:  // use orthographics projection
>         SetUpProjection(myORTHO,windowSizeX, windowSizeY);
>         break;
>     case XK_p:  // use perspective projection
>         SetUpProjection(myPERSPECTIVE,windowSizeX, windowSizeY);
>         break;
>     case XK_h:  // reset to initial view (home)
>         trackball(cumulativeQuaternion, 0.0, 0.0, 0.0, 0.0);
>         break;
>     case XK_w:
>         my_Data.wireframe = my_Data.wireframe ^ 1;
>         break;
>     case XK_Right:
>         trackball(deltaQuaternion,0.0,0.0,DELTA,0.0);
>         add_quats(deltaQuaternion, cumulativeQuaternion, cumulativeQuaternion);
>         break;
>     case XK_Left:
>         trackball(deltaQuaternion,0.0,0.0,-DELTA,0.0);
>         add_quats(deltaQuaternion, cumulativeQuaternion, cumulativeQuaternion);
>         break;
>     case XK_Up:
>         trackball(deltaQuaternion,0.0,0.0,0.0,DELTA);
>         add_quats(deltaQuaternion, cumulativeQuaternion, cumulativeQuaternion);
>         break;
>     case XK_Down:
>         trackball(deltaQuaternion,0.0,0.0,0.0,-DELTA);
>         add_quats(deltaQuaternion, cumulativeQuaternion, cumulativeQuaternion);
>         break;
>     case XK_Escape:
>         my_Cleanup(my_Data.aTetraSet,my_Data.aVolume);
>         exit(0);
>     }
> }
>
> void
> MotionInput(XMotionEvent * motionEvent)
> {
>     static int prevX = 0, prevY=0;
>     static int currX = 0, currY=0;
>
>     switch ( motionEvent->state ) {
>
>       case Button1MotionMask:
>         prevX = currX;
>         prevY = currY;
>         currX = motionEvent->x;
>         currY = motionEvent->y;
>
>         if( ! buttonReleased ) {
>           prevX = motionEvent->x;
>           prevY = motionEvent->y;
>           buttonReleased = 1;
>         }
>
>         trackball(deltaQuaternion,
>           (2.0*prevX-windowSizeX)/(float)windowSizeX,
>           (windowSizeY-2.0*prevY)/(float)windowSizeY,
>           (2.0*currX-windowSizeX)/(float)windowSizeX,
>           (windowSizeY-2.0*currY)/(float)windowSizeY);
>
>         add_quats(deltaQuaternion, cumulativeQuaternion, cumulativeQuaternion);
>
>         break;
>       case Button2MotionMask:
>         my_Button2Callback(motionEvent->x, motionEvent->y, my_Data.aVolume);
>         break;
>       case Button3MotionMask:
>         if( my_Data.aButton3CallbackPtr )
>           (*my_Data.aButton3CallbackPtr)(
>             motionEvent->x, motionEvent->y, my_Data.aVolume);
>         break;
>       default:
>         break;
>
>     }
>
> }
>
> void
> InputCB(Widget widget, XtPointer /* clientData */ , XtPointer callData)
> {
>     XmDrawingAreaCallbackStruct *dacs = (XmDrawingAreaCallbackStruct *)callData;
>
>     switch (dacs->event->type) {
>     case ButtonPress:
>         buttonReleased = 0;
>         break;
>     case ButtonRelease:
>         return;
>     case MotionNotify:
>         MotionInput((XMotionEvent *) dacs->event);
>         break;
>     case KeyPress:
>         KeybdInput((XKeyEvent *) dacs->event);
>         break;
>     case KeyRelease:
>         return;  // do not redraw on key release
>     default:
>         break;
>     }
>
>     Draw(widget);
>
> }
>
> void
> main(int argc, char **argv)
> {
>     fprintf(stderr,"%s\n",voVersion());
>
>     fprintf(stderr,
>       "\nLeft mouse button to rotate, right to adjust lookup table.\n\n");
>
>     myParseArgs(argc, argv);
>
>     voError::setDebugLevel( my_Data.reportFillRateFlag == VO_TRUE ? 2 : 1);
>
>     /* load pattern for current 2d texture */
>
>     floorFileName = "plank.rgb";
>     floortex = read_texture("plank.rgb", &texwid, &texht, &texcomps);
>     if (floortex == NULL) {
>         printf("Bad file name.\n");
>         exit(1);
>     }
>
>
>     my_Data.aVolume = my_InitAppearance(argc, argv);
>     my_Data.aTetraSet = my_InitGeometry(my_Data.aVolume);
>     my_Data.aPolygonSetArray =
>     my_InitTransient(my_Data.aTetraSet,my_Data.aVolume);
>
>     Widget toplevel;
>     XtAppContext appCtxt;
>     XVisualInfo *visual;
>     Cardinal n1 = 0;
>     Arg args[4];
>
>     GLint attribs[] =
>     {GLX_RGBA, GLX_DOUBLEBUFFER, GLX_RED_SIZE, 1,
>      GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_DEPTH_SIZE, 1, None};
>
>     toplevel =
>       XtAppInitialize(&appCtxt, "Lean", NULL, 0, &argc, argv, NULL, NULL, 0);
>     XtSetArg(args[n1], XmNwidth, (int)windowSizeX); n1++;
>     XtSetArg(args[n1], XmNheight, (int)windowSizeY); n1++;
>     XtSetArg(args[n1], GLwNattribList, attribs); n1++;
>     Widget drawArea = GLwCreateMDrawingArea(toplevel, "pb", args, n1);
>
>     visual = glXChooseVisual(XtDisplay(toplevel), 0, attribs);
>     if (!visual)
>         fprintf(stderr, "Bad visual\n");
>
>     XtAddCallback(drawArea, GLwNinputCallback,  InputCB,  NULL);
>     XtAddCallback(drawArea, GLwNginitCallback,  GinitCB,  NULL);
>     XtAddCallback(drawArea, GLwNexposeCallback, ExposeCB, NULL);
>     XtAddCallback(drawArea, GLwNresizeCallback, ResizeCB, NULL);
>
>     XtManageChild(drawArea);
>
>     trackball(cumulativeQuaternion, 0.0, 0.0, 0.0, 0.0);
>
>     XtRealizeWidget(toplevel);
>     XtAppMainLoop(appCtxt);
>
> }
>
> void
> drawfloor(GLfloat alpha)
> {
>
>     static GLfloat floor_mat[] = {.5f, .5f, .5f, 1.f};
>
>
>     floor_mat[3] = alpha;
>     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, floor_mat);
>
>     glGenTexturesEXT(1, floorTextureObjectId);
>     glBindTextureEXT(GL_TEXTURE_2D, floorTextureObjectId[0]);
>     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texwid, texht, 0, GL_RGBA,
>                       GL_UNSIGNED_BYTE, floortex);
>
>     /* makes texturing faster, and looks better than GL_LINEAR */
>     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
>     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
>     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
>
>     glEnable(GL_TEXTURE_2D);
>
>     glBegin(GL_QUADS);
>
>     /* floor */
>     glNormal3f(0.f, 1.f, 0.f);
>     glTexCoord2i(0, 0);
>     glVertex3f(-100.f, 0.f,  100.f);
>     glTexCoord2i(2, 0);
>     glVertex3f( 100.f, 0.f,  100.f);
>     glTexCoord2i(2, 2);
>     glVertex3f( 100.f, 0.f, -100.f);
>     glTexCoord2i(0, 2);
>     glVertex3f(-100.f, 0.f, -100.f);
>
>     glEnd();
>
>     glDisable(GL_TEXTURE_2D);
>
> }
This archive was generated by hypermail 2.0b2 on Mon Nov 01 1999 - 14:25:43 PST