/* * Copyright (C) 2000, R3vis Corporation. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA, * or visit http://www.gnu.org/copyleft/gpl.html. * * Contributor(s): * Wes Bethel, R3vis Corporation, Marin County, California * * The OpenRM project is located at http://openrm.sourceforge.net/. */ /* * $Id: jack.c,v 1.5 2004/01/19 20:37:26 wes Exp $ * $Revision: 1.5 $ * $Name: OpenRM-1-5-2-RC1 $ * $Log: jack.c,v $ * Revision 1.5 2004/01/19 20:37:26 wes * Updated call that sets the context - was rmxPipeSetContext, is now * rmPipeSetContext. * * Set RM's frame rate to 60fps. You can now actually interact with these * programs on fast hardware. * * Revision 1.4 2003/08/06 19:04:01 wes * Updates for API changes present in OpenRM 1.5.0. * * Revision 1.3 2003/01/16 23:00:22 wes * Updated sources to reflect new organization of header files in OpenRM 1.5.0. * * Revision 1.2 2000/12/05 02:20:25 wes * Use OpenRM v1.4.0-alpha-1 API. * * Revision 1.1.1.1 2000/09/02 17:23:53 wes * Initial entry. * * */ /* * usage: jack [CAVE args] * * this demo program creates a single "jack" object that is placed * in the center of the CAVE. on each frame, it rotates by a * small amount about it's vertical axis. the purpose of this demo * program is to show how OpenRM can be used as a rendering and * data management infrastructure in CAVE applications. * * for more information about the CAVE library, visit the VRCO * website at http://www.vrco.com/. */ #include <stdio.h> #include <unistd.h> #include <rm/rm.h> #include <rm/rmaux.h> #include <cave_ogl.h> static RMnode *MyRoot; static RMpipe *myPipe; static int frameRate=60; /* could use a command line arg to set frame rate*/ void my_sphere(RMnode *addto, float cx, float cy, float cz, float radius, RMcolor3D *color) { RMprimitive *sprim; RMvertex3D v; v.x = cx; v.y = cy; v.z = cz; sprim = rmPrimitiveNew(RM_SPHERES); rmPrimitiveSetVertex3D(sprim,1,&v,RM_COPY_DATA,NULL); rmPrimitiveSetRadii(sprim, 1, &radius, RM_COPY_DATA, NULL); if (color != NULL) rmPrimitiveSetColor3D(sprim, 1, color, RM_COPY_DATA, NULL); rmPrimitiveSetModelFlag(sprim,RM_SPHERES_32); rmNodeAddPrimitive(addto, sprim); } void my_cylinder(RMnode *addto, float p1x, float p1y, float p1z, float p2x, float p2y, float p2z, float radius) { RMvertex3D v[2]; RMprimitive *cprim; v[0].x = p1x; v[0].y = p1y; v[0].z = p1z; v[1].x = p2x; v[1].y = p2y; v[1].z = p2z; cprim = rmPrimitiveNew(RM_CYLINDERS); rmPrimitiveSetVertex3D(cprim,2,v,RM_COPY_DATA,NULL); rmPrimitiveSetRadii(cprim, 1, &radius, RM_COPY_DATA, NULL); rmNodeAddPrimitive(addto, cprim); } void my_cone(RMnode *addto, float p1x, float p1y, float p1z, float p2x, float p2y, float p2z, float radius, RMcolor3D *color) { RMprimitive *cprim; RMvertex3D v[2]; v[0].x = p1x; v[0].y = p1y; v[0].z = p1z; v[1].x = p2x; v[1].y = p2y; v[1].z = p2z; cprim = rmPrimitiveNew(RM_CONES); rmPrimitiveSetVertex3D(cprim,2,v,RM_COPY_DATA,NULL); rmPrimitiveSetRadii(cprim, 1, &radius, RM_COPY_DATA, NULL); if (color != NULL) rmPrimitiveSetColor3D(cprim, 1, color, RM_COPY_DATA, NULL); rmNodeAddPrimitive(addto, cprim); } void buildInitialSceneGraph(void) { RMcolor3D color; /* from the cones.c in the x-demos distribution*/ MyRoot = rmNodeNew("MyRoot",RM_RENDERPASS_3D, RM_RENDERPASS_OPAQUE); { RMcolor4D c={0.2, 0.2, 0.3, 1.0}; float one = 1.0F; rmNodeSetSceneBackgroundColor(MyRoot, &c); rmNodeSetSceneDepthValue(MyRoot, &one); } rmNodeAddChild(rmRootNode(), MyRoot); rmDefaultLighting(rmRootNode()); /* build the jack */ /* the center sphere should be red. */ color.r = 1.0; color.g = color.b = 0.0; my_sphere(MyRoot,0.0F, 0.0F, 0.0F, 1.0F,&color); /* a blue sphere at (5,0,0) */ color.r = color.g = 0.0; color.b = 1.0; my_sphere(MyRoot,5.0F, 0.0F, 0.0F, 1.0F,&color); /* a white sphere opposite blue sphere at (-5, 0, 0) */ my_sphere(MyRoot,-5.0F, 0.0F, 0.0F, 1.0F,NULL); /* a green sphere at (0,0,5) */ color.r = color.b = 0.0; color.g = 1.0; my_sphere(MyRoot,0.0F, 0.0F, 5.0F, 1.0F,&color); /* a white sphere opposite the green sphere at (0,0,-5) */ my_sphere(MyRoot,0.0F, 0.0F, -5.0F, 1.0F,NULL); my_cylinder(MyRoot,0.0F, 0.0F, 0.0F, 5.0F, 0.0F, 0.0F, 0.3F); my_cylinder(MyRoot,0.0F, 0.0F, 0.0F, -5.0F, 0.0F, 0.0F, 0.3F); my_cylinder(MyRoot,0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 5.0F, 0.3F); my_cylinder(MyRoot,0.0F, 0.0F, 0.0F, 0.0F, 0.0F, -5.0F, 0.3F); { RMcolor3D red={1.0,0.0,0.0}; /* one cone is red, one is white (default color) */ my_cone(MyRoot,0.0F,0.0F,0.0F,0.0F,6.0F,0.0F,0.5F,NULL); my_cone(MyRoot,0.0F,0.0F,0.0F,0.0F,-6.0F,0.0F,0.5F,&red); } /* rmNodeComputeBoundingBox(MyRoot); */ /* * add "my root" to RM's root node. this is necessary since we're * doing an rmFrame() to render everything inside of rmauxUI(); */ #if 0 rmNodeUnionAllBoxes(rmRootNode()); rmNodeComputeCenterFromBoundingBox(rmRootNode()); rmNodeSetPolygonDrawMode(MyRoot,RM_FRONT_AND_BACK,RM_LINE); #endif /* * probably want to grab rmRootNode's bbox info to build a * xform matrix for use with the cave - sort of an equivalent * of "compute view from geometry." */ { RMmatrix m; RMvertex3D v; rmMatrixIdentity(&m); m.m[0][0] = m.m[1][1] = m.m[2][2] = 0.5; rmNodeSetScaleMatrix(MyRoot,&m); v.x = 0.0; v.y = 5.0; v.z = 0.0; rmNodeSetTranslateVector(MyRoot, &v); } rmNodeSetSceneViewport(rmRootNode(), NULL); } void mySpinFunc() { RMmatrix m,old; double d,c,s; rmMatrixIdentity(&m); d = RM_DEGREES_TO_RADIANS(1.0); c = cos(d); s = sin(d); m.m[0][0] = m.m[2][2] = c; m.m[0][2] = -s; m.m[2][0] = s; if (rmNodeGetRotateMatrix(MyRoot,&old) == RM_WHACKED) rmMatrixIdentity(&old); rmMatrixMultiply(&old,&m,&old); rmNodeSetRotateMatrix(MyRoot,&old); } void appInitGL(void) { int myWidth, myHeight, myOriginX, myOriginY; rmInit(); myPipe = rmPipeNew(RM_PIPE_GLX); /* * we have to manually assign needed parameters to the Pipe * using the values set up by CAVElib. */ /* want a channel format that doesn't blow the matrix stack upon entry. */ rmPipeSetChannelFormat(myPipe, RM_MONO_CHANNEL); rmPipeSetInitMatrixStackMode(myPipe, RM_FALSE); rmPipeSetFrameRate(myPipe, frameRate); /* turn off swapbuffers - CAVElib handles that. */ rmPipeSetSwapBuffersFunc(myPipe, NULL); /* obtain the OpenGL context from CAVElib, assign that to the pipe */ rmPipeSetContext(myPipe, CAVEGLXContext()); rmxPipeSetDisplay(myPipe, CAVEXDisplay()); /* obtain and assign window geometry */ CAVEGetWindowGeometry(&myOriginX, &myOriginY, &myWidth, &myHeight); rmPipeSetWindow(myPipe, CAVEXWindow(), myWidth, myHeight); rmPipeMakeCurrent(myPipe); /* */ buildInitialSceneGraph(); } void appDrawFunc(void) { rmFrame(myPipe, rmRootNode()); } int main(int argc, char *argv[]) { int numPipes; extern void caveDrawFunc(void); CAVEConfigure(&argc, argv, NULL); numPipes = CAVENumPipes(); CAVEInit(); /* app goes parallel here */ CAVEInitApplication(appInitGL, 0); /* each CAVE pipe or channel has some gfx initialization code. */ CAVEDisplay(appDrawFunc, 0); /* parallel draw */ CAVEFrameFunction(mySpinFunc, 0); while (!CAVEgetbutton(CAVE_ESCKEY)) usleep(1000); /* sleep 1000 microseconds (1msec) */ CAVEExit(); return(0); }