250 likes | 421 Views
Class 4. Spaces needed to coordinate modeling, animation, viewing, and rendering. CS580 (Computer Graphics Rendering). Orig. by Ulrich Neumann. Spaces : model, world, image (camera), perspective (NDC), screen. screen is pixel coords like FB in HW1 (Right-handed coords)
E N D
Class 4. Spaces needed to coordinate modeling, animation, viewing, and rendering CS580(Computer Graphics Rendering) Orig. by Ulrich Neumann
Spaces : model, world, image (camera), perspective (NDC), screen • screen is pixel coords like FB in HW1 (Right-handed coords) • perspective is NDC (x, y = [-1,1], z = [0,1]) (LHC) • image has center of projection plane at (0,0,0), looking along +z (LHC) • world has all some origin/axis as reference for object locations (LHC) • model has coord frame(s) of its own (LHC) • All are left-handed except for screen, which is right-handed z-in x y y z-in x
Transforms: screen Xsp perspective (NDC) Xpi image Xiw world Xwm model • Xforms are between spaces - Renderer maintains the complete transformation Xsm • Application/animation controls each transform for different purposes Xwm object positions (per frame or per instance) Xiw camera motion/external parameters (per frame) Xpi camera FOV (focal length, zoom) internal parameters (per frame) Xsp screen or frame-buffer mapping (per session)
Managing Xforms • Use one of more stack structures that allow push/pop operations. • Push in sequence from screen to model. • Pop as many as needed in reverse order to allow push of modified matrix. • Complete pushes before rendering next frame. • Full stack must transform models to screen Xsm • Let stack accumulate transforms, rather than just storing them • Push A Top of stack = Q0 = (A) • Push B Top of stack = Q1 = (Q0B) = (AB) • Push C Top of stack = Q2 = (Q1C) = (ABC) • Pop Top of stack = Q1 = (AB) • Push D Top of stack = Q2 = (Q1D) = (ABD)
Initializating the Matrix Stack • The Renderer is responsible for creating and initializing Xsw on the transform stack before any tris are drawn • Application provides high-level parameters that gives Renderer the info needed to build Xsw during initialization Xsp depends on frame buffer params (xs, ys, zmax) Xpidepends on camera FOV Xiwdepends on camera pose • Xwm is set by the Application after Renderer initialization of stack to Xsw -- when the application is ready to place and draw objects • The Renderer does not need to know how the Xwm matrices are created – they are simply appended to the stack using push/pop • The application must push Xwm before rendering any objects
Ex: How to move camera • Change Xiw to produces a camera change • Build new Xiw (show how in later slide) • Pop to remove Xwm from full Xsm stack • leaves Xsw on stack • Pop to remove Xiw from Xsm stack • leaves Xsi on stack • Push new Xiw (set new camera position) • Push same Xwm as previously used • must have Xwm saved in application since application makes the push/pop commands
Ex: How to spin model • Model position and orientation is based on Xwm • Build new X’wm based on desired spinning motion • First rotate the model in model space to create a spinning version of the model (T-1RT) • Translate model-space origin to desired rotation center (create a new fixed-point for rotation) • Apply the desired rotation to model • Translate origin back to initial model-space location • Place the new spinning model in the world using the initial placement Xwm • Pop to remove Xwm from full Xsm stack • leaves Xsw on stack • Push new X’wm =Xwm(T-1RT) • must have initial Xwm saved in application since application makes the push/pop commands
Ex: How to zoom camera in/out • Xpi [3][2] = 1/d where d is focal length. Modify d for new zoom factor. • Larger d for longer focal length (zoom in), smaller d for wider view angle (zoom out).
Ex: How to instance N chairs • Given a chair room position T, orientation R, and size S • X’wm = T R S • assumes fixed-point for chair model in models space is suitable for scaling and rotation so it does not need to change • otherwise need to change fixed-point X’wm = T (Tf-1) R S (Tf) • Scale the chair model about its origin • Rotate the scaled chair about R to the desired chair orientation • Translate the chair to its position in the world T • Pop to remove prior Xwm from full Xsm stack • leaves Xsw on stack • Push new X’wm on stack • Render the chair model • repeat 3-step sequence with new TRS for each chair
Xsp = xs/2 0 0 xs/2 0 -ys/2 0 ys/2 0 0 1 0 0 0 0 1 Building the matrices (1) • Xsp mat takes care of scale to output device - device independence is good thing • Perspective (NDC) [-1, 1] LH coords - origin in center • Square aspect for screen size and pixels (our definition) • Screen coords RH coords - origin in upper left (raster scans x, then y) • Map entire NDC to screen • best-fit subset of NDC when screen is not square
Xsp = xs/2 0 0 xs/2 0 -ys/2 0 ys/2 0 0 Zmax/d0 0 0 0 1 Building the matrices (2) • Recall from projection transformation, z = [0, d] • Integer Z-buffer resolution has a fixed range we should use for all d • Scale output of projection by Zmax/d (in Xsp[2][2]) to get z = [0, Zmax]
Xpi = 1 0 0 0 0 1 0 0 0 0 10 0 0 1/d 1 Building the matrices (3) • Xpimat takes image space to perspective space • Image space is X,Y = [-1,1], Z = [0, +inf] • The projection term in this mat is defined by the distance d from the view plane to focal point (also FOV) 1/d=tan(FOV/2) +1 FOV d -1
Building the matrices (4) • Xiw Camera transform defines image space coordinates needed to set up projection. • Choose position of camera (view plane origin) in world = c, (all coords in world space) • lookat point = l, (world space) • camera Z-axis, Z = cl / || cl || (world space) • up vector = (0, 1, 0) is up-direction in world space (unit-length vector) • up' = up - (up Z)Z • camera Y-axis, Y = up' / || up'|| • camera X-axis, X = (Y x Z) (LH coords for camera) X = (Y x Z) = i (Yy Zz - Yz Zy) + j (Yz Zx - Yx Zz) + k (Yx Zy - Yy Zx) up up’ l Y c Z X out
Xwi = Xx Yx Zx Cx Xy Yy Zy Cy Xz Yz Zz Cz 0 0 0 1 Building the matrices (5) • Image-space camera X, Y, Z axes are all normalized and orthogonal -- and expressed in world space coords, so we can make Xwi directly • (Cx, Cy, Cz = camera origin in world coords) = Xwi (0,0,0) camera origin transforms to camera location in world space – right column does this • 3x3 UR rotation is column vectors of the 3 camera axis we just computed in world space, so an input camera axis vector of 1,0,0 or 0,1,0 or 0,0,1will output oneof the columns, the world space vector for that axis
Xiw = Xx Xy Xz -XC Yx Yy Yz -YC Zx Zy Zz -ZC 0 0 0 1 Building the matrices (6) • Xiw is inverse of Xwi, so use fact that Xwi = T R • create R-1 and T-1 and concat to get Xiw = R-1 T-1 -The translation column elements are dot-products of two vectors
Review of Z issue • Why process Z to get z = Z/((Z/d) + 1)? Why do perspective Xform for Z at all – why not use Image-space Z? • We get bounded z [0, d] • z interpolates correctly, Z does not interpolate correctly • Illustrate the problem with a plane in perspective • If Z were simply interpolated over screen from a to c, then b would be Z>11. • When box corner is projected to point b with Z=11.1, it would appear "in front" of plane and be visible. • By interpolating a to c and testing in z-buffer the perspective z values, z = Z/((Z/d) + 1), depth comparison comes out correct. a b c Z=1 Z = 11 Z = 21
HW3 API/function overview • NameList and ValueList are used to send parameters to the renderer • camera params, transforms, etc… • Push/Pop matrix stack functions are needed for HW3 • Stack accumulates xforms (on right side) as they are pushed • Render sequence is: • Application will create FB and Rend - renderer can build Xsp once FB params are known (once only) • Application will set camera parameters - renderer will build Xpi and Xiw and push them (and Xsp) on stack (every frame) • Application will push/pop Xwm for each object and render tris • Make sure to compute and interpolate z, not Z
App3 fragments /* initialize the display and the renderer */ status |= GzNewDisplay(&display, GZ_RGBAZ_DISPLAY, 256, 256); status |= GzInitDisplay(display); /* optional since BeginRender will also clear FB every frame */ status |= GzNewRender(&renderer, GZ_Z_BUFFER_RENDER, display); /* set up app-defined camera if desired, else rely on camera defaults set during NewRender setup */ camera.position[X] = 13.2; camera.position[Y] = -8.7; camera.position[Z] = -14.8; camera.lookat[X] = 0.8; camera.lookat[Y] = 0.7; camera.lookat[Z] = 4.5; camera.worldup[X] = -0.2; camera.worldup[Y] = 1.0; camera.worldup[Z] = 0.0; camera.FOV = 53.7; /* degrees */ status |= GzPutCamera(renderer, &camera); /* overwrite default camera */ status |= GzBeginRender(renderer); /* Renderer sets up everything for drawing a frame */ /* set up model matrices as desired */ status |= GzPushMatrix(renderer, scale); status |= GzPushMatrix(renderer, rotateY); status |= GzPushMatrix(renderer, rotateX); /* Walk through the list of triangles, set color and render each triangle */ /* dump image file */ GzFlushDisplay(display); /* Clean up and exit */ status |= GzFreeRender(renderer); status |= GzFreeDisplay(display);
Assignment 3 for cs580 Add the transformation process to your HW2 rastorizer. *** Changes in the API are not allowed *** The standard application must work without modification. The files in hw3.zip include: hw3.txt This file in full Gz.h A few new definitions for hw3 app3.c New application that calls your rend.c functions rend.skel New skeleton file with API definition and comments tri.asc A one-triangle data file tri.ppm The result of running "app3 <tri.asc >tri.ppm" pot4.asc The Utah teapot triangle data file pot4.ppm The result of "app3 <pot4.asc >pot4.ppm" with default camera pot4.cam.ppm The result of "app3 <pot4.asc >pot4.cam.ppm" with app1 camera /* Camera defaults are set so the app can omit camera setup if desired */ #define DEFAULT_FOV 35.0 /* use a default look-at point = 0,0,0 */ #define DEFAULT_IM_Z (-10.0) /* world coords for image plane origin (camera origin) */ #define DEFAULT_IM_Y (5.0) #define DEFAULT_IM_X (-10.0) You can change the resolution of your FB image to magnify or shrink the entire image. Again - your background color may be different than mine. You should "stress-test" your renderer by changing the camera and look at point with the PutCamera call. Don't forget to clip (ignore) triangles that are behind the view plane (negative Z vertex coord).
Renderer API (1) int GzNewRender(render, class, display) GzRender **render; GzRenderClass class; GzDisplay *display; { /* - malloc a renderer struct - keep closed until all inits are done - setup Xsp and anything only done once - save pointer to display for init and rasterizer - check for legal class GZ_Z_BUFFER_RENDER - init default camera – normalize “up vector” just in case. */ } int GzFreeRender(render) GzRender *render; { /* -free all renderer resources -it doesn't exist anymore */ }
Renderer API (2) int GzBeginRender(render) GzRender *render; { /* - set up for start of each frame - clear frame buffer - compute Xiw and projection xform Xpi from camera definition - init Xform stack - put Xsp at base of stack, push on Xpi and Xiw - now stack contains Xsw and app can push model Xforms when it want to */ } int GzPutCamera(render, camera) GzRender *render; GzCamera *camera; { /* - overwrite renderer camera structure with new camera definition - normalize “up vector” just in case (sanity check) */ }
Renderer API (3) int GzPushMatrix(render, matrix) GzRender *render; GzMatrix matrix; { /* - push a matrix onto the Ximage stack - check for stack overflow */ } int GzPopMatrix(render) GzRender *render; { /* - pop a matrix off the Ximage stack - check for stack underflow */ }
Renderer API (4) int GzPutAttribute(render, numAttributes, nameList, valueList) GzRender *render; int numAttributes; GzToken *nameList; GzPointer *valueList; { /* - set renderer attribute info (only GZ_RGB_COLOR for now) - later HWs will use this call to define shaders, interpolaters, texture maps, and lights */ } int GzPutTriangle(render, numParts, nameList, valueList) GzRender *render; int numParts; /* how many names and values */ GzToken *nameList; GzPointer *valueList; { /* - pass in a triangle description with tokens and values corresponding to GZ_POSITION: 3 vert coords in model space - Xform vert coordinates - Clip - discard any triangle with verts behind view plane (Z < 0) - Run your HW2 triangle rasterizer with Xformed verts */ }
HW3 Results Pot4cam.ppm pot4.ppm tri.ppm
HW3 Details The lid and pot are separate parts and not airtight There is no bottom to the pot