/* * Copyright (C) 2001-2003, 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: markers2d.c,v 1.5 2003/04/13 18:13:23 wes Exp $ * $Revision: 1.5 $ * $Name: OpenRM-1-5-2-RC1 $ * $Log: markers2d.c,v $ * Revision 1.5 2003/04/13 18:13:23 wes * Updated copyright dates. * * Revision 1.4 2003/01/16 22:22:45 wes * Updated all source files to reflect new organization of header files: all * headers that were formerly located in include/rmaux, include/rmv and * include/rmi are now located in include/rm. * * Revision 1.3 2002/06/17 00:39:40 wes * Updated copyright line. * * Revision 1.2 2001/07/15 22:33:19 wes * Added rmPipeDelete to the end of all demo progs. For those that use * an initfunc, added a new RMnode * parm (which is unused, except for rm2screen). * * Revision 1.1 2001/06/03 17:54:06 wes * Initial entry. This program is currently non-operational pending some * work inside OpenRM that will separate access to 2d geometric markers from * the RMV library. * * */ /* * June 3, 2001 - this program is not yet operational. Some additional * work is needed to separate 2d geometric markers from the RMV library. * wes */ #include <rm/rm.h> #include <rm/rmv.h> #include <rm/rmaux.h> #include "procmode.h" static RMnode *MyRoot; int img_width=800,img_height=480; typedef struct { RMvertex2D p; char string[54]; } labelStruct; #define CZERO 0.1 #define CONE 0.2 #define CTWO 0.3 #define CTHREE 0.4 #define CFOUR 0.5 #define CFIVE 0.6 #define CSIX 0.7 #define CSEVEN 0.8 #define HHW 0.05 /*#define HHW 0.05 */ #define NUM_COLUMN_LABELS 1 #define NUM_ROW_LABELS 8 labelStruct columnLabels[NUM_COLUMN_LABELS] = { { {CONE-1.8*HHW, 1.F}, "Markers" } }; labelStruct rowLabels[NUM_ROW_LABELS] = { { {CONE-1.8*HHW, CSEVEN}, "RMV_2DMARKER_SQUARE" }, { {CONE-1.8*HHW, CSIX}, "RMV_2DMARKER_CROSS" }, { {CONE-1.8*HHW, CFIVE}, "RMV_2DMARKER_X" }, { {CONE-1.8*HHW, CFOUR}, "RMV_2DMARKER_NORTHTRIANGLE" }, { {CONE-1.8*HHW, CTHREE}, "RMV_2DMARKER_BOWTIE" }, { {CONE-1.8*HHW, CTWO}, "RMV_2DMARKER_SOUTHTRIANGLE" }, { {CONE-1.8*HHW, CONE}, "RMV_2DMARKER_DIAMOND" }, { {CONE-1.8*HHW, CZERO}, "RMV_2DMARKER_NORTHTRIANGLE_FILLED" } }; #define NUM_MARKERS 8 RMenum markerTypes[NUM_MARKERS] = { RMV_2DMARKER_SQUARE, RMV_2DMARKER_CROSS, RMV_2DMARKER_X, RMV_2DMARKER_NORTHTRIANGLE, RMV_2DMARKER_BOWTIE, RMV_2DMARKER_SOUTHTRIANGLE, RMV_2DMARKER_DIAMOND, RMV_2DMARKER_NORTHTRIANGLE_FILLED }; RMvertex2D markersVerts[NUM_MARKERS] = { {CZERO, 0.0F}, {CONE, 0.0F}, {CTWO, 0.0F}, {CTHREE, 0.0F}, {CFOUR, 0.0F}, {CFIVE, 0.0F}, {CSIX, 0.0F}, {CSEVEN, 0.0F} }; float markerYCoords[NUM_MARKERS] = { CZERO, CONE, CTWO, CTHREE, CFOUR, CFIVE, CSIX, CSEVEN }; float markerScale[NUM_MARKERS] = { 0.01, 0.05, 0.1, 0.25, 0.5, 1.0, 3.0 }; void my_set_scene(RMnode *addTo) { RMcamera2D *c = rmCamera2DNew();; rmDefaultCamera2D(c); /* assign it some default values. */ /* change the default scene camera from (0,0) to (1,1) */ rmCamera2DSetExtents(c, -0.25F, -0.2F, 1.25F, 1.2F); /* add the camera to "my root's" scene parms. */ rmNodeSetSceneCamera2D(addTo,c); } void makeMarkers(RMenum markerType, int nmarkers, RMvertex2D *markerVerts, float markerYCoord, float *markerScales) { RMinternalMarker2D *m; int i; RMvertex2D *v = rmVertex2DNew(nmarkers); memcpy((void *)v, (void *)markerVerts, sizeof(RMvertex2D)*nmarkers); for (i=0;i<nmarkers;i++) v[i].y = markerYCoord; m = rmInternalMarker2DNew(rmv2DMarkerTools[markerType].nv, rmv2DMarkerTools[markerType].gl_begin_flag, rmv2DMarkerTools[markerType].shape); rmPrimitiveSetVertex2D(t, npts, v, RM_COPY_DATA, NULL); #if 0 if (c) { rmPrimitiveSetColor4D(t, npts, c, RM_COPY_DATA, NULL); rmColor4DDelete(c); } #endif rmPrimitiveSetMarkerScale(t, nmarkers, markerScales, RM_COPY_DATA, NULL); rmPrimitiveSetMarkerPrims(t, 1, &m); } void my_build_objs(void) { int i,limit; RMprimitive *tlist; RMnode *textRoot; RMnode *textNode; RMnode *markersRoot; MyRoot = rmNodeNew("MyRoot", RM_RENDERPASS_2D, RM_RENDERPASS_OPAQUE); textRoot = rmNodeNew("textRoot",RM_RENDERPASS_2D, RM_RENDERPASS_OPAQUE); markersRoot = rmNodeNew("linesRoot",RM_RENDERPASS_2D, RM_RENDERPASS_OPAQUE); rmNodeAddChild(rmRootNode(),MyRoot); rmNodeAddChild(MyRoot,textRoot); rmNodeAddChild(MyRoot,markersRoot); limit = NUM_MARKERS; for (i=0;i<limit;i++) { RMnode *n; RMprimitive *p; char buf[32]; sprintf(buf,"marker-%d",i); n = rmNodeNew(buf,RM_RENDERPASS_2D,RM_RENDERPASS_OPAQUE); p = makeMarkers(markerTypes[i],NUM_MARKERS,markerVerts, markerYCoords[i],makerScale); rmNodeAddPrimitive(n,p); #if 0 rmPrimitiveSetVertex2D(p,2,lines[i].p,RM_COPY_DATA,NULL); rmNodeSetLineStyle(n,lines[i].lineStyle); rmNodeSetLineWidth(n,lines[i].lineWidth); #endif rmNodeAddChild(markersRoot, n); } /* * for all the column headers, we have to set node-level text properties * to declare horizontal centering for justification, and use a smaller- * than-default font size. */ limit = NUM_COLUMN_LABELS; for (i=0;i<limit;i++) { char name[32]; char *strings[1]; RMtextProps *tp; RMcolor4D c={1.0F, 1.0F, 0.5F, 1.0F}; sprintf(name,"text-%d",i); textNode = rmNodeNew(name,RM_RENDERPASS_2D,RM_RENDERPASS_OPAQUE); rmNodeSetUnlitColor(textNode, &c); tlist = rmPrimitiveNew(RM_TEXT); rmNodeAddPrimitive(textNode, tlist); rmNodeAddChild(textRoot, textNode); rmPrimitiveSetVertex2D(tlist,1, &(columnLabels[i].p), /* pointer to stuff */ RM_COPY_DATA, /* let RM manage this data */ NULL); /* don't need a freefunc for RM_COPY_DATA */ strings[0] = columnLabels[i].string; rmPrimitiveSetText(tlist,1,strings); tp = rmTextPropsNew(); rmTextPropsSetAttribs(tp, RM_FONT_SANS, /* font family */ RM_FONT_M, /* size */ RM_FALSE, /* embolden? */ RM_FALSE, /* italicize? */ RM_CENTER, /* horiz justification */ RM_BOTTOM); /* vertical justification */ rmNodeSetSceneTextProps(textNode, tp); rmTextPropsDelete(tp); } /* * for all the column headers, we have to set node-level text properties * to declare horizontal centering for justification, and use a smaller- * than-default font size. */ limit = NUM_ROW_LABELS; for (i=0;i<limit;i++) { char name[32]; char *strings[1]; RMtextProps *tp; RMcolor4D c={0.5F, 1.0F, 0.5F, 1.0F}; sprintf(name,"text-%d",i); textNode = rmNodeNew(name,RM_RENDERPASS_2D,RM_RENDERPASS_OPAQUE); rmNodeSetUnlitColor(textNode,&c); tlist = rmPrimitiveNew(RM_TEXT); rmNodeAddPrimitive(textNode, tlist); rmNodeAddChild(textRoot, textNode); rmPrimitiveSetVertex2D(tlist,1, &(rowLabels[i].p), /* pointer to stuff */ RM_COPY_DATA, /* let RM manage this data */ NULL); /* don't need a freefunc for RM_COPY_DATA */ strings[0] = rowLabels[i].string; rmPrimitiveSetText(tlist,1,strings); tp = rmTextPropsNew(); rmTextPropsSetAttribs(tp, RM_FONT_SANS, /* font family */ RM_FONT_XXS, /* size */ RM_FALSE, /* embolden? */ RM_FALSE, /* italicize? */ RM_RIGHT, /* horiz justification */ RM_BOTTOM); /* vertical justification */ rmNodeSetSceneTextProps(textNode, tp); rmTextPropsDelete(tp); } #if 0 /* * set text justification parameter, controls justification for all * text prims at the given node. */ { RMvertex3D bmin,bmax,center; rmNodeUnionAllBoxes(rmRootNode()); rmNodeGetBoundingBox(rmRootNode(),&bmin,&bmax); center.x = bmin.x + 0.5F *(bmax.x - bmin.x); center.y = bmin.y + 0.5F *(bmax.y - bmin.y); center.z = bmin.z + 0.5F *(bmax.z - bmin.z); rmNodeSetCenter(rmRootNode(),¢er); } #endif { RMcolor4D bgcolor={0.2,0.2,0.3,1.0}; /* * assign a background color to take effect at "MyRoot" */ rmNodeSetSceneBackgroundColor(MyRoot,&bgcolor); } } void myinitfunc(RMpipe *p) { my_build_objs(); my_set_scene(); rmauxUI(rmRootNode(),p); /* * set handler to reset aspect ratio when the window is resized. */ rmauxSetResizeFunc(p, MyRoot, rmauxDefaultResizeFunc); rmFrame(p,rmRootNode()); rmFrame(p,rmRootNode()); } #ifdef RM_WIN int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { MSG msg; HWND hWnd; void *fptr; #else /* assume RM_X */ int main() { void *msg; /* needed for rmauxEventLoop win32/unix API consistency */ #endif int status; RMpipe *pipe=NULL; RMenum processingMode = DEFAULT_PROCESSING_MODE; /* in procmode.h */ /* * first stage of RM initialization. */ rmInit(); /* * create the rendering pipe. this step is required in both * Win32 and X. */ status = rmPipeInit(getenv("DISPLAY"),RM_MONO_CHANNEL,&pipe); rmPipeSetProcessingMode(pipe, processingMode); #ifdef RM_WIN { /* * Win32: when a window is created, we have to tell windows the * name of the "WndProc," the procedure that gets called by * windows with events (the event loop) (contrast to the X model * where the name of the event loop is not part of the window). * Since we're using RMaux, we know about the event handling * procedure named "rmauxWndProc" and we provide that here. */ fptr = (void *)(rmauxWndProc); hWnd = rmauxCreateW32Window(pipe, NULL, /* no parent window */ 20,20,img_width,img_height, "OpenRM - 2D Markers", hInstance,fptr); if (hWnd == 0) exit(-1); /* * assign the new window handle to the rendering pipe. */ rmPipeSetWindow(pipe,hWnd, img_width, img_height); } #endif #ifdef RM_X { Window w; w = rmauxCreateXWindow(pipe, (Window)NULL, /* parent window */ 0,0,img_width,img_height, "OpenRM - 2D Markers","OpenRM",1); /* * assign the window to the rendering pipe. */ rmPipeSetWindow(pipe,w,img_width,img_height); } #endif /* * specify the name of the "init" function. the "init" function is * mandatory in the Win32 world, and optional in the X world. * * in Win32, we don't want to call RM services until OpenGL is * ready. we can be assured of readiness by using an init function * with RMaux. * * in X, at this point, the window is mapped and OpenGL is ready, * and we could call our init function directly. */ rmauxSetInitFunc(myinitfunc); /* * X-ism: once the window is created and assigned to the * rendering pipe, rmUsePipe makes the OpenGL rendering context * current for the pipe+window combination. * * this step is required for X. in these demo programs, it is not * strictly required by Win32, as the newly created context is made * current as part of the OpenGL initialization sequence. */ rmPipeMakeCurrent(pipe); /* * set key handler function so this prog will exit on "q" key */ rmauxSetKeyFunc(lone_pipe, rmauxDefaultKeyFunc); rmauxEventLoop(lone_pipe,rmRootNode(), &msg); rmPipeDelete(lone_pipe); rmFinish(); #ifdef RM_WIN return( msg.wParam ); #else return(1); #endif }