/* * 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: imgMirror.c,v 1.6 2003/04/13 18:13:23 wes Exp $ * $Revision: 1.6 $ * $Name: OpenRM-1-5-2-RC1 $ * $Log: imgMirror.c,v $ * Revision 1.6 2003/04/13 18:13:23 wes * Updated copyright dates. * * Revision 1.5 2003/01/27 05:07:07 wes * Changes to RMpipe initialization sequence APIs. Tested for GLX, but not WGL. * * 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/09/22 17:31:43 wes * Added code to delete RMimage objects after they've been loaded * in as sprites. * * Revision 1.2 2002/06/17 00:37:27 wes * Updated copyright line. * * Revision 1.1 2001/10/15 00:23:34 wes * Initial entry. * */ /* * usage: imgMirror (no args). * */ #include <stdio.h> #ifndef RM_WIN #include <unistd.h> #endif #include <rm/rm.h> #include <rm/rmaux.h> #include <rm/rmi.h> #include "procmode.h" static RMpipe *myPipe=NULL; #define DEFAULT_IMAGE_WIDTH 800 #define DEFAULT_IMAGE_HEIGHT 700 void create2DCamera(RMpipe *p, RMnode *root) { RMcamera2D *c = rmCamera2DNew(); float viewExtents[] = {-1.1, -1.1, 1.1, 1.1}; float viewPort[] = {0.0, 0.0, 1.0, 1.0}; RMcolor4D bgColor = {.3F, .3F, .3F, 1.0F}; int winW, winH; rmPipeGetWindowSize(p, &winW, &winH); rmNodeSetSceneBackgroundColor(root, &bgColor); rmCamera2DSetAspectRatio(c, (float)winW/(float)winH); rmCamera2DSetExtents(c, viewExtents[0], viewExtents[1], viewExtents[2], viewExtents[3]); rmNodeSetSceneCamera2D(root, c); rmNodeSetSceneViewport(root, viewPort); rmCamera2DDelete(c); } void createObjects(RMpipe *pipe, RMnode *localRoot, RMimage *src) { RMnode *upperLeft, *lowerLeft, *upperRight, *lowerRight; RMprimitive *p; RMvertex2D v00={-1.0, 0.2}; RMvertex2D v01={-1.0, -1.0}; RMvertex2D v10={0.2, 0.2}; RMvertex2D v11={0.2, -1.0}; RMimage *upperLeftImage=NULL, *lowerLeftImage=NULL; RMimage *upperRightImage=NULL, *lowerRightImage=NULL; upperLeft = rmNodeNew("upperLeft", RM_RENDERPASS_2D, RM_RENDERPASS_ALL); lowerLeft = rmNodeNew("lowerLeft", RM_RENDERPASS_2D, RM_RENDERPASS_ALL); upperRight = rmNodeNew("upperRight", RM_RENDERPASS_2D, RM_RENDERPASS_ALL); lowerRight = rmNodeNew("lowerRight", RM_RENDERPASS_2D, RM_RENDERPASS_ALL); upperLeftImage = rmImageDup(src); p = rmPrimitiveNew(RM_SPRITE); rmPrimitiveSetVertex2D(p, 1, &v00, RM_COPY_DATA, NULL); rmPrimitiveSetSprites(p, 1, &upperLeftImage); rmNodeAddPrimitive(upperLeft, p); rmNodeAddChild(localRoot, upperLeft); /* do lower left image - mirror about vertical axis */ lowerLeftImage = rmImageDup(src); rmImageMirror(lowerLeftImage, RM_IMAGE_MIRROR_HEIGHT); p = rmPrimitiveNew(RM_SPRITE); rmPrimitiveSetVertex2D(p, 1, &v01, RM_COPY_DATA, NULL); rmPrimitiveSetSprites(p, 1, &lowerLeftImage); rmNodeAddPrimitive(lowerLeft, p); rmNodeAddChild(localRoot, lowerLeft); /* do upper right image - mirror about horizontal axis */ upperRightImage = rmImageDup(src); rmImageMirror(upperRightImage, RM_IMAGE_MIRROR_WIDTH); p = rmPrimitiveNew(RM_SPRITE); rmPrimitiveSetVertex2D(p, 1, &v10, RM_COPY_DATA, NULL); rmPrimitiveSetSprites(p, 1, &upperRightImage); rmNodeAddPrimitive(upperRight, p); rmNodeAddChild(localRoot, upperRight); /* lower right image - mirror about (1) horizontal, then (2) vertical */ lowerRightImage = rmImageDup(src); rmImageMirror(lowerRightImage, RM_IMAGE_MIRROR_WIDTH); rmImageMirror(lowerRightImage, RM_IMAGE_MIRROR_HEIGHT); p = rmPrimitiveNew(RM_SPRITE); rmPrimitiveSetVertex2D(p, 1, &v11, RM_COPY_DATA, NULL); rmPrimitiveSetSprites(p, 1, &lowerRightImage); rmNodeAddPrimitive(lowerRight, p); rmNodeAddChild(localRoot, lowerRight); /* free up images */ rmImageDelete(lowerRightImage); rmImageDelete(upperRightImage); rmImageDelete(lowerLeftImage); rmImageDelete(upperLeftImage); } void myInitFunc(RMpipe *p, RMnode *n) { char fname[]={"data/doghead.jpg"}; RMimage *srcImage = rmiReadJPEG(fname); RMimage *useImage = rmImageNew(2, 256, 256, 1, RM_IMAGE_RGB, RM_UNSIGNED_BYTE, RM_COPY_DATA); RMnode *localRoot = rmNodeNew("localRoot", RM_RENDERPASS_2D, RM_RENDERPASS_OPAQUE); if (srcImage == NULL) { rmError(" myInitFunc() error reading source image. "); exit(-1); } else { int w,h; rmImageGetImageSize(srcImage, NULL, &w, &h, NULL, NULL, NULL); printf(" w/h of src image are %d, %d \n", w,h); rmImageMirror(srcImage, RM_IMAGE_MIRROR_HEIGHT); rmImageResize(srcImage, useImage, RM_SOFTWARE, p); } /* create the 2D camera for the view model */ create2DCamera(p, localRoot); /* populate the scene graph with drawable stuff */ createObjects(p, localRoot, useImage); /* free up images */ rmImageDelete(srcImage); rmImageDelete(useImage); rmNodeAddChild(n, localRoot); rmFrame(p, n); } void myRenderFunc(RMpipe *myPipe, RMnode *subTree) { /* insert code to call frame-based renderer here */ rmFrame(myPipe, subTree); } void usage(char *s) { printf("usage: %s (no arguments) \n",s); } #if 0 void parseArgs(int ac, char *av[], int *imgWidth, int *imgHeight) { int i; i = 1; while (i < ac) { if (strcmp(av[i],"-w") == 0) { i++; ac--; sscanf(av[i],"%d", imgWidth); } else if (strcmp(av[i],"-h") == 0) { i++; ac--; sscanf(av[i],"%d", imgHeight); } else { usage(av[0]); exit(-1); } i++; } } #endif #ifdef RM_WIN int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { MSG msg; HWND hWnd; void *fptr; int status; int imgWidth, imgHeight; RMenum processingMode = DEFAULT_PROCESSING_MODE; /* in procmode.h */ RMenum targetPlatform = RM_PIPE_WGL; imgWidth = DEFAULT_IMAGE_WIDTH; imgHeight = DEFAULT_IMAGE_HEIGHT; /* parseArgs(__argc, __argv, &imgWdth, &imgHeight); */ #else /* assume RM_X */ int main(int argc, char *argv[]) { void *msg; /* needed for rmauxEventLoop win32/unix API consistency */ int status; int imgWidth, imgHeight; RMenum processingMode = DEFAULT_PROCESSING_MODE; /* in procmode.h */ RMenum targetPlatform = RM_PIPE_GLX; imgWidth = DEFAULT_IMAGE_WIDTH; imgHeight = DEFAULT_IMAGE_HEIGHT; /* parseArgs(argc, argv, &imgWidth, &imgHeight); */ #endif /* * first stage of RM initialization. */ rmInit(); /* * create the rendering pipe. this step is required in both * Win32 and X. */ myPipe = rmPipeNew(targetPlatform); processingMode = RM_PIPE_MULTISTAGE; rmPipeSetProcessingMode(myPipe, 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(myPipe, NULL, /* no parent window */ 20,20,imgWidth,imgHeight,"RM for Windows", hInstance,fptr); if (hWnd == 0) exit(-1); /* * assign the new window handle to the rendering pipe. */ rmPipeSetWindow(myPipe,hWnd, imgWidth, imgHeight); } #endif #ifdef RM_X { Window w; w = rmauxCreateXWindow(myPipe, (Window)NULL, /* parent window */ 0,0,imgWidth,imgHeight, "RM for X-Windows","RM for X-Windows",RM_TRUE); /* * assign the window to the rendering pipe. */ rmPipeSetWindow(myPipe,w,imgWidth,imgHeight); } #endif /* * X-ism: once the window is created and assigned to the * rendering pipe, rmPipeMakeCurrent 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(myPipe); rmauxSetInitFunc(myInitFunc); rmauxSetRenderFunc(myRenderFunc); /* * set key handler function so this prog will exit on "q" key. */ rmauxSetKeyFunc(myPipe, rmauxDefaultKeyFunc); rmauxEventLoop(myPipe,rmRootNode(), &msg); rmFinish(); return(1); }