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