1 /*
2  * Copyright (C) 2001-2005, R3vis Corporation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA,
17  * or visit http://www.gnu.org/copyleft/gpl.html.
18  *
19  * Contributor(s):
20  *   Wes Bethel, R3vis Corporation, Marin County, California
21  *
22  * The OpenRM project is located at http://openrm.sourceforge.net/.
23  */
24 /*
25  * $Id: imgMirror.c,v 1.8 2005/07/04 18:12:48 wes Exp $
26  * $Revision: 1.8 $
27  * $Name: OpenRM-1-6-0-2-c $
28  * $Log: imgMirror.c,v $
29  * Revision 1.8  2005/07/04 18:12:48  wes
30  * Fix w32 compile problems.
31  *
32  * Revision 1.7  2005/06/08 17:56:21  wes
33  * Code cleanup to eliminate compiler warnings.
34  *
35  * Revision 1.6  2003/04/13 18:13:23  wes
36  * Updated copyright dates.
37  *
38  * Revision 1.5  2003/01/27 05:07:07  wes
39  * Changes to RMpipe initialization sequence APIs. Tested for GLX, but not WGL.
40  *
41  * Revision 1.4  2003/01/16 22:22:45  wes
42  * Updated all source files to reflect new organization of header files: all
43  * headers that were formerly located in include/rmaux, include/rmv and
44  * include/rmi are now located in include/rm.
45  *
46  * Revision 1.3  2002/09/22 17:31:43  wes
47  * Added code to delete RMimage objects after they've been loaded
48  * in as sprites.
49  *
50  * Revision 1.2  2002/06/17 00:37:27  wes
51  * Updated copyright line.
52  *
53  * Revision 1.1  2001/10/15 00:23:34  wes
54  * Initial entry.
55  *
56  */
57 
58 /*
59  * usage: imgMirror [-w imgWidth] [-h imgHeight]
60  */
61 
62 #include <stdio.h>
63 #ifndef RM_WIN
64 #include <unistd.h>
65 #endif
66 #include <rm/rm.h>
67 #include <rm/rmaux.h>
68 #include <rm/rmi.h>
69 #include "procmode.h"
70 
71 static RMpipe *myPipe=NULL;
72 
73 #define DEFAULT_IMAGE_WIDTH 800
74 #define DEFAULT_IMAGE_HEIGHT 700
75 
76 void
create2DCamera(RMpipe * p,RMnode * root)77 create2DCamera(RMpipe *p,
78 	       RMnode *root)
79 {
80     RMcamera2D *c = rmCamera2DNew();
81     float viewExtents[] = {-1.1, -1.1, 1.1, 1.1};
82     float viewPort[] = {0.0,  0.0, 1.0, 1.0};
83     RMcolor4D bgColor = {.3F, .3F, .3F, 1.0F};
84     int winW, winH;
85 
86     rmPipeGetWindowSize(p, &winW, &winH);
87     rmNodeSetSceneBackgroundColor(root, &bgColor);
88 
89     rmCamera2DSetAspectRatio(c, (float)winW/(float)winH);
90     rmCamera2DSetExtents(c, viewExtents[0], viewExtents[1], viewExtents[2], viewExtents[3]);
91 
92     rmNodeSetSceneCamera2D(root, c);
93     rmNodeSetSceneViewport(root, viewPort);
94 
95     rmCamera2DDelete(c);
96 }
97 
98 void
createObjects(RMnode * localRoot,RMimage * src)99 createObjects(RMnode *localRoot,
100 	      RMimage *src)
101 {
102     RMnode *upperLeft, *lowerLeft, *upperRight, *lowerRight;
103     RMprimitive *p;
104     RMvertex2D v00={-1.0, 0.2};
105     RMvertex2D v01={-1.0, -1.0};
106     RMvertex2D v10={0.2, 0.2};
107     RMvertex2D v11={0.2, -1.0};
108     RMimage *upperLeftImage=NULL, *lowerLeftImage=NULL;
109     RMimage *upperRightImage=NULL, *lowerRightImage=NULL;
110 
111     upperLeft = rmNodeNew("upperLeft", RM_RENDERPASS_2D, RM_RENDERPASS_ALL);
112     lowerLeft = rmNodeNew("lowerLeft", RM_RENDERPASS_2D, RM_RENDERPASS_ALL);
113     upperRight = rmNodeNew("upperRight", RM_RENDERPASS_2D, RM_RENDERPASS_ALL);
114     lowerRight = rmNodeNew("lowerRight", RM_RENDERPASS_2D, RM_RENDERPASS_ALL);
115 
116     upperLeftImage = rmImageDup(src);
117 
118     p = rmPrimitiveNew(RM_SPRITE);
119     rmPrimitiveSetVertex2D(p, 1, &v00, RM_COPY_DATA, NULL);
120     rmPrimitiveSetSprites(p, 1, &upperLeftImage);
121 
122     rmNodeAddPrimitive(upperLeft, p);
123     rmNodeAddChild(localRoot, upperLeft);
124 
125     /* do lower left image - mirror about vertical axis */
126     lowerLeftImage = rmImageDup(src);
127     rmImageMirror(lowerLeftImage, RM_IMAGE_MIRROR_HEIGHT);
128 
129     p = rmPrimitiveNew(RM_SPRITE);
130     rmPrimitiveSetVertex2D(p, 1, &v01, RM_COPY_DATA, NULL);
131     rmPrimitiveSetSprites(p, 1, &lowerLeftImage);
132 
133     rmNodeAddPrimitive(lowerLeft, p);
134     rmNodeAddChild(localRoot, lowerLeft);
135 
136     /* do upper right image - mirror about horizontal axis */
137     upperRightImage = rmImageDup(src);
138     rmImageMirror(upperRightImage, RM_IMAGE_MIRROR_WIDTH);
139 
140     p = rmPrimitiveNew(RM_SPRITE);
141     rmPrimitiveSetVertex2D(p, 1, &v10, RM_COPY_DATA, NULL);
142     rmPrimitiveSetSprites(p, 1, &upperRightImage);
143 
144     rmNodeAddPrimitive(upperRight, p);
145     rmNodeAddChild(localRoot, upperRight);
146 
147     /* lower right image - mirror about (1) horizontal, then (2) vertical */
148     lowerRightImage = rmImageDup(src);
149     rmImageMirror(lowerRightImage, RM_IMAGE_MIRROR_WIDTH);
150     rmImageMirror(lowerRightImage, RM_IMAGE_MIRROR_HEIGHT);
151 
152     p = rmPrimitiveNew(RM_SPRITE);
153     rmPrimitiveSetVertex2D(p, 1, &v11, RM_COPY_DATA, NULL);
154     rmPrimitiveSetSprites(p, 1, &lowerRightImage);
155 
156     rmNodeAddPrimitive(lowerRight, p);
157     rmNodeAddChild(localRoot, lowerRight);
158 
159     /* free up images */
160     rmImageDelete(lowerRightImage);
161     rmImageDelete(upperRightImage);
162     rmImageDelete(lowerLeftImage);
163     rmImageDelete(upperLeftImage);
164 }
165 
166 void
myInitFunc(RMpipe * p,RMnode * n)167 myInitFunc(RMpipe *p,
168 	   RMnode *n)
169 {
170     char fname[]={"data/doghead.jpg"};
171     RMimage *srcImage = rmiReadJPEG(fname);
172     RMimage *useImage = rmImageNew(2, 256, 256, 1, RM_IMAGE_RGB, RM_UNSIGNED_BYTE, RM_COPY_DATA);
173     RMnode *localRoot = rmNodeNew("localRoot", RM_RENDERPASS_2D, RM_RENDERPASS_OPAQUE);
174 
175     if (srcImage == NULL)
176     {
177 	rmError(" myInitFunc() error reading source image. ");
178 	exit(-1);
179     }
180     else
181     {
182 	int w,h;
183 	rmImageGetImageSize(srcImage, NULL, &w, &h, NULL, NULL, NULL);
184 	printf(" w/h of src image are %d, %d \n", w,h);
185 	rmImageMirror(srcImage, RM_IMAGE_MIRROR_HEIGHT);
186 	rmImageResize(srcImage, useImage, RM_SOFTWARE, p);
187     }
188 
189     /* create the 2D camera for the view model */
190     create2DCamera(p, localRoot);
191 
192     /* populate the scene graph with drawable stuff */
193     createObjects(localRoot, useImage);
194 
195     /* free up images */
196     rmImageDelete(srcImage);
197     rmImageDelete(useImage);
198 
199     rmNodeAddChild(n, localRoot);
200 
201     rmFrame(p, n);
202 }
203 
204 void
myRenderFunc(RMpipe * myPipe,RMnode * subTree)205 myRenderFunc(RMpipe *myPipe,
206 	     RMnode *subTree)
207 {
208     /* insert code to call frame-based renderer here */
209     rmFrame(myPipe, subTree);
210 }
211 
212 void
usage(char * s)213 usage(char *s)
214 {
215     printf("usage: %s [-w imgWidth] [-h imgHeight] \n",s);
216 }
217 
218 void
parseArgs(int ac,char * av[],int * imgWidth,int * imgHeight)219 parseArgs(int ac,
220 	  char *av[],
221 	  int *imgWidth,
222 	  int *imgHeight)
223 {
224     int i;
225 
226     i = 1;
227     while (i < ac)
228     {
229 	if (strcmp(av[i],"-w") == 0)
230 	{
231 	    i++;
232 	    ac--;
233 	    sscanf(av[i],"%d", imgWidth);
234 	}
235 	else if (strcmp(av[i],"-h") == 0)
236 	{
237 	    i++;
238 	    ac--;
239 	    sscanf(av[i],"%d", imgHeight);
240 	}
241 	else
242 	{
243 	    usage(av[0]);
244 	    exit(-1);
245 	}
246 	i++;
247     }
248 }
249 
250 #ifdef RM_WIN
WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpszCmdLine,int nCmdShow)251 int WINAPI WinMain (HINSTANCE hInstance,
252 		    HINSTANCE hPrevInstance,
253                     LPSTR lpszCmdLine, int nCmdShow)
254 {
255     MSG      msg;
256     HWND     hWnd;
257     void *fptr;
258 
259     int imgWidth, imgHeight;
260     RMenum processingMode = DEFAULT_PROCESSING_MODE; /* in procmode.h */
261     RMenum targetPlatform = RM_PIPE_WGL;
262 
263     imgWidth = DEFAULT_IMAGE_WIDTH;
264     imgHeight = DEFAULT_IMAGE_HEIGHT;
265 
266     parseArgs(__argc, __argv, &imgWidth, &imgHeight);
267 
268 #else  /* assume RM_X */
269 int
270 main(int argc,
271      char *argv[])
272 {
273     void *msg;			/* needed for rmauxEventLoop
274 				 win32/unix API consistency */
275     int imgWidth, imgHeight;
276     RMenum processingMode = DEFAULT_PROCESSING_MODE; /* in procmode.h */
277     RMenum targetPlatform = RM_PIPE_GLX;
278 
279     imgWidth = DEFAULT_IMAGE_WIDTH;
280     imgHeight = DEFAULT_IMAGE_HEIGHT;
281 
282     parseArgs(argc, argv, &imgWidth, &imgHeight);
283 #endif
284 
285     /*
286      * first stage of RM initialization.
287      */
288     rmInit();
289 
290     /*
291      * create the rendering pipe. this step is required in both
292      * Win32 and X.
293      */
294     myPipe = rmPipeNew(targetPlatform);
295     processingMode = RM_PIPE_MULTISTAGE;
296     rmPipeSetProcessingMode(myPipe, processingMode);
297 
298 #ifdef RM_WIN
299     {
300         /*
301 	 * Win32: when a window is created, we have to tell windows the
302 	 * name of the "WndProc," the procedure that gets called by
303 	 * windows with events (the event loop) (contrast to the X model
304 	 * where the name of the event loop is not part of the window).
305 	 * Since we're using RMaux, we know about the event handling
306 	 * procedure named "rmauxWndProc" and we provide that here.
307 	 */
308 
309         fptr = (void *)(rmauxWndProc);
310 	hWnd = rmauxCreateW32Window(myPipe,
311 			       NULL, /* no parent window */
312 			       20,20,imgWidth,imgHeight,"RM for Windows",
313 			       hInstance,fptr);
314 	if (hWnd == 0)
315 	  exit(-1);
316 
317 	/*
318 	 * assign the new window handle to the rendering pipe.
319 	 */
320 	rmPipeSetWindow(myPipe,hWnd, imgWidth, imgHeight);
321     }
322 #endif
323 #ifdef RM_X
324     {
325 	Window w;
326 
327 	w = rmauxCreateXWindow(myPipe,
328 			       (Window)NULL, /* parent window */
329 			       0,0,imgWidth,imgHeight,
330 			       "RM for X-Windows","RM for X-Windows",RM_TRUE);
331 
332 	/*
333 	 * assign the window to the rendering pipe.
334 	 */
335 	rmPipeSetWindow(myPipe,w,imgWidth,imgHeight);
336     }
337 #endif
338 
339     /*
340      * X-ism: once the window is created and assigned to the
341      * rendering pipe, rmPipeMakeCurrent makes the OpenGL rendering context
342      * current for the pipe+window combination.
343      *
344      * this step is required for X. in these demo programs, it is not
345      * strictly required by Win32, as the newly created context is made
346      * current as part of the OpenGL initialization sequence.
347      */
348     rmPipeMakeCurrent(myPipe);
349 
350     rmauxSetInitFunc(myInitFunc);
351     rmauxSetRenderFunc(myRenderFunc);
352 
353     /*
354      * set key handler function so this prog will exit on "q" key.
355      */
356     rmauxSetKeyFunc(myPipe, rmauxDefaultKeyFunc);
357 
358     rmauxEventLoop(myPipe,rmRootNode(), &msg);
359 
360     rmFinish();
361 
362     return(1);
363 }
364 
365 /* EOF */
366