/* * 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: textureTest.c,v 1.8 2003/11/22 00:54:35 wes Exp $ * $Revision: 1.8 $ * $Name: OpenRM-1-5-2-RC1 $ * $Log: textureTest.c,v $ * Revision 1.8 2003/11/22 00:54:35 wes * New command line argument and support code to permit testing of * texture instancing. * * Revision 1.7 2003/04/13 18:13:23 wes * Updated copyright dates. * * Revision 1.6 2003/01/27 05:07:07 wes * Changes to RMpipe initialization sequence APIs. Tested for GLX, but not WGL. * * Revision 1.5 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.4 2002/09/22 17:32:00 wes * Defaults for number of textures is now [32, 32]. * * Revision 1.3 2002/09/17 14:27:16 wes * Added CLI that sets the number of textures to generate/draw. * * Revision 1.2 2002/09/05 15:22:35 wes * Increased number of quads/textures to exceed the default PAGE_SIZE. * * Revision 1.1 2002/09/05 15:09:01 wes * Initial entry. The spriteTest.c program will exercise the RMimage * realloc code, and the textureTest exercises the texture realloc code. * * Revision 1.3 2002/06/17 00:42:23 wes * Updated copyright line. * * Revision 1.2 2001/10/15 00:34:43 wes * Added rmPipeDelete() at the end of the program. * * Revision 1.1 2001/07/15 22:37:51 wes * Initial entry. * */ /* * usage: textureTest [-w imgWidthPixels] [-h imgHeightPixels] * [-n nTexturesPerSide] [-solo] * * This code is a skeleton application template. Use it as the basis * for your own OpenRM applications. */ #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 1024 #define DEFAULT_IMAGE_HEIGHT 960 #define DEFAULT_NTEXTURES 32 static int numTiles[2]={DEFAULT_NTEXTURES, DEFAULT_NTEXTURES}; static int numUnique = -1; static RMtexture **theTextures=NULL; RMtexture * myMakeTexture(float a) { int textureDims[2]={8, 4}; int i,j, indx; RMcolor4D sEven, sOdd, *d; RMtexture *t = rmTextureNew(2); RMimage *img = rmImageNew(2, textureDims[0], textureDims[1], 1, RM_IMAGE_RGBA,RM_FLOAT,RM_COPY_DATA); d = (RMcolor4D *)rmImageGetPixelData(img); sEven.r = 0.0F; sEven.g = a; sEven.b = 1.0-a; sEven.a = 1.0; sOdd.r = 1.0-a; sOdd.g = 0.0; sOdd.b = a; sOdd.a = 1.0; for (j=0;j<textureDims[1];j++) { for (i=0;i<textureDims[0];i++) { if (j & 1) { if (i & 1) *d = sOdd; else *d = sEven; } else { if (i & 1) *d = sEven; else *d = sOdd; } d++; } } rmTextureSetImages(t, &img, 1, 0); rmTextureSetEnv(t, GL_DECAL, NULL); return t; } void setMyTexture(RMnode *n, float a) { int textureDims[2]={8, 4}; int i,j, indx; RMcolor4D sEven, sOdd, *d; RMtexture *t = rmTextureNew(2); RMimage *img = rmImageNew(2, textureDims[0], textureDims[1], 1, RM_IMAGE_RGBA,RM_FLOAT,RM_COPY_DATA); d = (RMcolor4D *)rmImageGetPixelData(img); sEven.r = 0.0F; sEven.g = a; sEven.b = 1.0-a; sEven.a = 1.0; sOdd.r = 1.0-a; sOdd.g = 0.0; sOdd.b = a; sOdd.a = 1.0; for (j=0;j<textureDims[1];j++) { for (i=0;i<textureDims[0];i++) { if (j & 1) { if (i & 1) *d = sOdd; else *d = sEven; } else { if (i & 1) *d = sEven; else *d = sOdd; } d++; } } rmTextureSetImages(t, &img, 1, 0); rmTextureSetEnv(t, GL_DECAL, NULL); rmNodeSetSceneTexture(n, t); /* delete the RMimage and the RMtexture because RM has a copy now */ rmImageDelete(img); rmTextureDelete(t, RM_TRUE); } void buildTiles(RMnode *myRoot, int numWidth, int numHeight, int numUnique) { /* * assumptions: visible extents range from (-1,-1) .. (1,1) * leave 0.05 in margin all the way around the viewport. */ float x,dx, xwidth; float y,dy, yheight; RMvertex2D v[4]; RMvertex2D tc[4]; RMcolor4D unlitColor={0.0F, 1.0F, 0.0F, 1.0F}; int i, j; RMnode *blockRoot = rmNodeNew("blocks", RM_RENDERPASS_ALL, RM_RENDERPASS_ALL); float a, da; int tcount=0; rmNodeAddChild(myRoot, blockRoot); x = -1.0 + 0.05; dx = 1.9/(numWidth); /* increment to next block */ xwidth = dx - (dx * 0.2); y = -1.0 + 0.05; dy = 1.9/(numHeight); yheight = dy - (dy * 0.2); a = 1.0; if (numUnique == 1) da = 0.0; else da = -1.0/(float)(numUnique - 1); /* build the source textures */ theTextures = (RMtexture **)malloc(sizeof(RMtexture *)*numUnique); for (j=0;j<numUnique;j++, a+=da) theTextures[j] = myMakeTexture(a); rmNodeSetUnlitColor(blockRoot, &unlitColor); rmNodeSetShader(blockRoot, RM_SHADER_NOLIGHT); tc[0].x = tc[0].y = 0.0; tc[1].x = 1.0; tc[1].y = 0.0; tc[2].x = tc[2].y = 1.0; tc[3].x = 0.0; tc[3].y = 1.0; for (j=0;j<numHeight;j++) { for (i=0;i<numWidth;i++,a+=da) { char buf[32]; RMnode *n; RMprimitive *p; sprintf(buf,"node-%d-%d",j,i); n = rmNodeNew(buf,RM_RENDERPASS_ALL, RM_RENDERPASS_ALL); p = rmPrimitiveNew(RM_QUADS); v[0].x = x + i * dx; v[0].y = y + j * dy; v[1].x = v[0].x + xwidth; v[1].y = v[0].y; v[2].x = v[0].x + xwidth; v[2].y = v[0].y + yheight; v[3].x = v[0].x; v[3].y = v[2].y; rmPrimitiveSetVertex2D(p, 4, v, RM_COPY_DATA, NULL); rmPrimitiveSetTexcoord2D(p, 4, tc, RM_COPY_DATA, NULL); rmNodeAddPrimitive(n, p); rmNodeAddChild(blockRoot, n); rmNodeSetSceneTexture(n, theTextures[tcount % numUnique]); /* new_rmNodeSetSceneTexture(n, theTextures[tcount % numUnique], RM_TRUE); */ /* new_rmNodeSetSceneTexture(n, theTextures[tcount % numUnique], RM_FALSE); */ tcount++; /* setMyTexture(n, a); */ } } } void myInitFunc(RMpipe *p, RMnode *n) { /* insert code to build the initial scene graph here. be sure to add your scene graph to the node "n" */ RMcamera2D *c = rmCamera2DNew(); RMnode *myRoot = rmNodeNew("myRoot", RM_RENDERPASS_2D, RM_RENDERPASS_OPAQUE); RMcolor4D bgColor={0.3, 0.3, 0.3, 1.0}; rmNodeAddChild(n, myRoot); rmDefaultCamera2D(c); /* extents set to [-1,-1]..[1,1] */ rmNodeSetSceneCamera2D(myRoot, c); rmNodeSetSceneBackgroundColor(myRoot, &bgColor); rmCamera2DDelete(c); buildTiles(myRoot, numTiles[0], numTiles[1], numUnique); 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 [-w imgWidthPixels ] [-h imgHeightPixels] [-n NN (number of textures displayed 'per side' for a total of NN**2 textures, default is %d)] [-nt NN (defines the number of unique RMtexture objects, the default is %d*%d, or %d unique RMtexture objects) \n",s, DEFAULT_NTEXTURES, DEFAULT_NTEXTURES, DEFAULT_NTEXTURES, DEFAULT_NTEXTURES*DEFAULT_NTEXTURES); } void parseArgs(int ac, char *av[], int *imgWidth, int *imgHeight) { int i; i = 1; while (ac > 1) { 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 if (strcmp(av[i],"-n") == 0) { i++; ac--; sscanf(av[i],"%d", numTiles); numTiles[1] = numTiles[0]; fprintf(stderr," setting number of tiles to be %d by %d \n", numTiles[0], numTiles[1]); } else if (strcmp(av[i],"-nt") == 0) { i++; ac--; sscanf(av[i],"%d", &numUnique); fprintf(stderr," setting the number of unique textures to be %d \n", numUnique); } else { usage(av[0]); exit(-1); } i++; ac--; } } #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, &imgWidth, &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 if (numUnique == -1) /* user didn't specify -nt on command line, use a default value that corresponds to the number of tiles */ numUnique = numTiles[0]*numTiles[1]; /* * 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); rmPipeDelete(myPipe); rmFinish(); return(1); } /* EOF */