/* * Copyright (C) 1997-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: text2d.c,v 1.11 2003/04/13 18:13:23 wes Exp $ * $Revision: 1.11 $ * $Name: OpenRM-1-5-2-RC1 $ * $Log: text2d.c,v $ * Revision 1.11 2003/04/13 18:13:23 wes * Updated copyright dates. * * Revision 1.10 2003/01/27 05:07:07 wes * Changes to RMpipe initialization sequence APIs. Tested for GLX, but not WGL. * * Revision 1.9 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.8 2002/06/17 00:43:21 wes * updated copyright line. * * Revision 1.7 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.6 2001/06/03 19:44:05 wes * Add calls to new rmaux routines to handle window resize events, and * for keyboard event handling. * * Revision 1.5 2001/03/31 16:55:18 wes * Added procmode.h, which defines an RMpipe processing mode used in * most demonstration programs. The default processing mode is * RM_PIPE_MULTISTAGE_VIEW_PARALLEL. * * Revision 1.4 2000/12/02 17:24:32 wes * Version 1.4.0-alpha-1 checkin. See the RELEASENOTES file for * a summary of changes. With this checkin, these demo programs * are no longer compatible with versions of the OpenRM API that * are pre-1.4.0. * * Revision 1.3 2000/08/28 01:38:18 wes * Updated rmaux* interfaces - rmauxEventLoop now takes two additional * parameters (keypress and window resize app callbacks); replaced * rmauxUI with rmauxSetGeomTransform and, where appropriate, * rmauxSetCamera3DTransform. * * Revision 1.2 2000/04/20 18:04:34 wes * Minor tweaks and reorg for OpenRM 1.2.1. * * Revision 1.1.1.1 2000/02/28 21:55:30 wes * OpenRM 1.2 Release * * Revision 1.9 2000/02/28 17:21:55 wes * RM 1.2, pre-OpenRM * */ #include <rm/rm.h> #include <rm/rmaux.h> #include "procmode.h" static RMnode *MyRoot; int img_width=600,img_height=480; typedef struct tstruct { RMvertex2D xy; char string[RM_MAX_STRING_LENGTH]; int font,italic,bold,size; RMcolor3D color; } tstruct; static RMenum hJustify=RM_LEFT, vJustify = RM_BOTTOM; #define NUM_TEXT_STRINGS 14 static tstruct pile_o_text[NUM_TEXT_STRINGS] = { { {0.1,0.55}, "Serif XS NonItalic NonBold", RM_FONT_SERIF, RM_FALSE, RM_FALSE, RM_FONT_XS, {1.0,0.8,0.8} }, { {0.1,0.5}, "Serif XXS NonItalic NonBold", RM_FONT_SERIF, RM_FALSE, RM_FALSE, RM_FONT_XXS, {1.0,1.0,1.0} }, { {0.1,0.6}, "Serif S NonItalic NonBold", RM_FONT_SERIF, RM_FALSE, RM_FALSE, RM_FONT_S, {1.0,0.6,0.6} }, { {0.1,0.65}, "Serif M NonItalic NonBold", RM_FONT_SERIF, RM_FALSE, RM_FALSE, RM_FONT_M, {1.0,0.4,0.4} }, { {0.1,0.7}, "Serif L NonItalic NonBold", RM_FONT_SERIF, RM_FALSE, RM_FALSE, RM_FONT_L, {1.0,0.2,0.2} }, { {0.1,0.75}, "Serif XL NonItalic NonBold", RM_FONT_SERIF, RM_FALSE, RM_FALSE, RM_FONT_XL, {1.0,0.0,0.0} }, { {0.1,0.8}, "Serif XXL NonItalic NonBold", RM_FONT_SERIF, RM_TRUE, RM_TRUE, RM_FONT_XXL, {1.0,0.0,0.0} }, { {0.3,0.1}, "Sans XXS NonItalic NonBold", RM_FONT_SANS, RM_FALSE, RM_FALSE, RM_FONT_XXS, {1.0,1.0,1.0} }, { {0.3,0.15}, "Sans XS NonItalic NonBold", RM_FONT_SANS, RM_FALSE, RM_FALSE, RM_FONT_XS, {0.8,0.8,1.0} }, { {0.3,0.2}, "Sans S NonItalic NonBold", RM_FONT_SANS, RM_FALSE, RM_FALSE, RM_FONT_S, {0.6,0.6,1.0} }, { {0.3,0.25}, "Sans M NonItalic NonBold", RM_FONT_SANS, RM_FALSE, RM_FALSE, RM_FONT_M, {0.4,0.4,1.0} }, { {0.3,0.3}, "Sans L NonItalic NonBold", RM_FONT_SANS, RM_FALSE, RM_FALSE, RM_FONT_L, {0.2,0.2,1.0} }, { {0.3,0.35}, "Sans XL NonItalic NonBold", RM_FONT_SANS, RM_FALSE, RM_FALSE, RM_FONT_XL, {0.,0.,1.0} }, { {0.3,0.4}, "Sans XXL NonItalic NonBold", RM_FONT_SYMBOL, RM_FALSE, RM_TRUE, RM_FONT_XXL, {0.,0.,1.0} } }; void my_set_scene(RMnode *camNode) { RMcamera2D *c = rmCamera2DNew();; rmDefaultCamera2D(c); /* assign it some default values. */ /* change the default scene camera from -1..1 to 0..1 */ rmCamera2DSetExtents(c,0.0F,0.F,1.0F,1.0F); /* add the camera to "my root's" scene parms. */ rmNodeSetSceneCamera2D(camNode,c); } void my_build_objs(void) { int i,limit; RMprimitive *tlist; RMnode *textRoot; RMnode *textNode; MyRoot = rmNodeNew("MyRoot", RM_RENDERPASS_2D, RM_RENDERPASS_OPAQUE); textRoot = rmNodeNew("textRoot",RM_RENDERPASS_2D, RM_RENDERPASS_OPAQUE); rmNodeAddChild(rmRootNode(),MyRoot); rmNodeAddChild(MyRoot,textRoot); limit = NUM_TEXT_STRINGS; /* * each text string is assumed to be of a different font, size, etc. * so each text string gets a unique node in the scene graph. the * scene graph node contains the font, size, italic, embolden * enumerators, while the underlying scene graph node primitive * contains the actual text string itself. */ for (i=0;i<limit;i++) { char name[32]; RMtextProps *tp; char *strings[1]; sprintf(name,"text-%d",i); textNode = rmNodeNew(name,RM_RENDERPASS_2D,RM_RENDERPASS_OPAQUE); tlist = rmPrimitiveNew(RM_TEXT); rmNodeAddPrimitive(textNode, tlist); rmNodeAddChild(textRoot, textNode); tp = rmTextPropsNew(); rmTextPropsSetAttribs(tp, pile_o_text[i].font, pile_o_text[i].size, pile_o_text[i].bold, pile_o_text[i].italic, hJustify, vJustify); rmNodeSetSceneTextProps(textNode, tp); rmTextPropsDelete(tp); rmPrimitiveSetVertex2D(tlist,1, &(pile_o_text[i].xy), /* pointer to stuff */ RM_COPY_DATA, /* let RM manage this data */ NULL); /* don't need a freefunc for RM_COPY_DATA */ /* now, we need to add the stuff into the text primitive so that the PS driver can deal with it ok. */ strings[0] = pile_o_text[i].string; rmPrimitiveSetText(tlist,1,strings); rmPrimitiveSetColor3D(tlist,1, &(pile_o_text[i].color), RM_COPY_DATA, NULL); } /* * 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); } { 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, RMnode *n) { my_build_objs(); my_set_scene(MyRoot); rmauxSetGeomTransform(rmRootNode(),p); /* * set handler to reset aspect ratio when the window is resized. */ rmauxSetResizeFunc(p, MyRoot, rmauxDefaultResizeFunc); if (rmPipeProcessingModeIsMultithreaded(p) == RM_TRUE) 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; RMenum targetPlatform = RM_PIPE_WGL; #else /* assume RM_X */ int main() { void *msg; /* needed for rmauxEventLoop win32/unix API consistency */ RMenum targetPlatform = RM_PIPE_GLX; #endif int status; RMpipe *lone_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. */ lone_pipe = rmPipeNew(targetPlatform); rmPipeSetProcessingMode(lone_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(lone_pipe, NULL, /* no parent window */ 20,20,img_width,img_height,"RM for Windows", hInstance,fptr); if (hWnd == 0) exit(-1); /* * assign the new window handle to the rendering pipe. */ rmPipeSetWindow(lone_pipe,hWnd, img_width, img_height); } #endif #ifdef RM_X { Window w; w = rmauxCreateXWindow(lone_pipe, (Window)NULL, /* parent window */ 0,0,img_width,img_height, "RM for X-Windows","icon-title",RM_TRUE); /* * assign the window to the rendering pipe. */ rmPipeSetWindow(lone_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(lone_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 }