Anjali 'S CG REPORT Wit Code

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 43

NITTE MEENAKSHI INSTITUTE OF TECHNOLOGY

DEPARTMENT OF COMPUTER SCIENCE AND ENGINEERING


(AN AUTONOMOUS INSTITUTION AFFILIATED TO V.T.U(BELGAUM)) YELAHANKA,BANGALORE-560 064

PROJECT ON

SIMULATION OF SHADOW FUN USING OpenGL IN COMPUTER GRAPHICS

SUBMITTED BY
ANJALI BANSAL -(INT08CS016) BHAKTHI VISHWANATH -(INTO8CS028)

Shadow Fun

NITTE MEENAKSHI INSTITUTE OF TECHNOLOGY


DEPARTMENT OF COMPUTER SCIENCE AND ENGINEERING
(AN AUTONOMOUS INSTITUTION AFFILIATED TO V.T.U(BELGAUM)) YELAHANKA,BANGALORE-560 064

CERTIFICATE
This is to certify that the MINI PROJECT report entitled,Simulation of shadow fun in OpenGL has been successfully completed by Anjali bansal (INT08CS016) and Bhakthi vishwanath(INT08CS028) in partial fulfillment for VI semester in CS&E under the guidance and supervision of Mrs.Nirmala and Mrs.Chaitra during the year 2011

STAFF IN_CHARGE 1 Mrs.Nirmala 2 Mrs.Chaitra . HOD of Dept. of CS&E Dr.Nalini N

EXAMINERS:

1. 2

Department Of CSE

Page | 2

Shadow Fun

ABSTRACT
This project is a simulation of Shadow Fun using OpenGL in computer graphics. Here, we make use of Top Down approach. The users can make use of this simulation in knowing many important facts such as the planetary motion, rotation and revolution of the planets and the Sun, etc. OpenGL (Open Graphics Library) is a standard specification defining a cross-language, cross-platform API for writing applications that produce 2D and 3D computer graphics, describing a set of functions and the precise behaviors that they must perform. Our mini project titled Shadow Fun in Computer Graphics is implemented using OpenGL. This project would enable users to witness the simulation of shadow fun using a Computer System. The users can zoom in on the objects. With all these maneuver abilities, one can use this for education purpose or could be compiled into a Computer screen saver.

Department Of CSE

Page | 3

Shadow Fun

ACKNOWLEDGEMENT
\

The satisfaction and euphoria that accompany the successful completion of any task would be but incomplete without mention of the people who made it possible, whose constant guidance and encouragement crowned our efforts with success. We consider ourselves proud, to be part of NMIT family, the institution which stood by our way in all our endeavors. It gives us immense pleasure in expressing our gratitude to our guides Mrs.Nirmala and Mrs.Chaitra,department of CS&E,for their valuable advice,timely

suggestions,encouragement and guidance throughout the course of this project.

We wish to thank our Head of the Department, Mrs.Nalini N for her magnanimous benignity and benevolence.We humbly convey our thankfulness to Prof.Nagaraj, Principal,NMIT,Bangalore for providing us an opportunity to carry out this project.

CONTENTS
Department Of CSE Page | 4

Shadow Fun

1.Introduction -1.1 Flow diagram 2.Literature survey -2.1 Scope -2.2 Requirement specification -2.3 System requirements 3.Design -3.1 Function description -3.2 Flow diagram -3.3 System implementation -3.4 Source code -3.5 System testing 4.Result -4.1 Screen shots 5.Conclusion 6.Bibliography -6.1 Texts -6.2 Links 43 43 39-41 42 10 11 12 12-38 38 7 7 8 6

Department Of CSE

Page | 5

Shadow Fun

1.INTRODUCTION
This project is a simulation of Shadow Fun using OpenGL in computer graphics. Here, we make use of Top Down approach. The users can make use of this simulation in knowing many important facts such as the planetary motion, rotation and revolution of the planets and the Sun, etc. OpenGL (Open Graphics Library) is a standard specification defining a cross-language, cross-platform API for writing applications that produce 2D and 3D computer graphics, describing a set of functions and the precise behaviors that they must perform. Top Down approach refers to the programming-oriented approach to computer grachics.

1.1Flow Diagram Start


MAIN( )

Calls

INITSCENE( )

DISPLAY

Draws Adds Returns data


SCENE LIGHTING

Right-click
MENU

Quit
EXIT

Department Of CSE

Page | 6

Shadow Fun

2.LITERATURE SURVEY
2.1 SCOPE:
Our mini project titled Shadow Fun in Computer Graphics is implemented using OpenGL. This project would enable users to witness the simulation of shadow fun using a Computer System. The users can zoom in on the objects. With all these maneuver abilities, one can use this for education purpose or could be compiled into a Computer screen saver.

2.2 REQUIREMENT SPECIFICATIONS: 2.2.1 Details of the Software


Here, the coding of our project is done in Microsoft Visual C++ which is a commercial integrated development environment (IDE) with OpenGL (Open Graphics Library) which is a standard specification to produce 2D and 3D computer graphics. We use, the OpenGL Utility Toolkit called GLUT which is a library of utilities for OpenGL programs

2.2.2 Microsoft Visual C++


Microsoft Visual C++ is a commercial integrated development environment (IDE) product engineered by Microsoft for the C, C++ and C++/CLI programming languages. It has tools for developing and debugging C++ code, especially code written for the Microsoft Windows API, OpenGL API, the DirectX API and the Microsoft .NET Framework.

2.2.3 OpenGL and GLUT


OpenGL (Open Graphics Library) is a standard specification defining a cross-language, cross-platform API for writing applications that produce 2D and 3D computer graphics, describing a set of functions and the precise behaviors that they must perform. From this specification, hardware vendors create implementations - libraries of functions created to match the functions stated in the OpenGL specification, making use of hardware acceleration where possible. Hardware vendors have to meet specific tests to be able to qualify their implementation as an OpenGL implementation. GLUT is the OpenGL Utility Toolkit, a window system independent toolkit for writing OpenGL programs. It implements a simple windowing application programming interface (API) for OpenGL. GLUT makes it considerably easier to learn about and explore OpenGL programming. GLUT provides a portable API so you can write a single OpenGL program that works across all PC and workstation OS platforms.

Department Of CSE

Page | 7

Shadow Fun

2.3 SYSTEM REQUIREMENTS:


2.3.1 Hardware Configuration A computer system with the following minimum requirements: 1 GHz or faster 32-bit(x86) or 64-bit(x64) processor 512 MB RAM 20MB available disk space DirectX 9 graphics processor (optional) 2.3.2 Software Configuration A computer system with the following minimum software installed: Microsoft Visual C++ 6.0 or above installed with any of its variants i.e., Express Edition or Professional Edition GLUT API version 3 or above

Department Of CSE

Page | 8

Shadow Fun

3. SYSTEM DESIGN
The system is divided into different modules in terms of functions such as Sphere( ), Cone( ), generateshadowvolume( ), Menu( ), rendershadow( ), Scene( ). Menu are subdivided into 6 functions, each representing different planets of the solar system as shown in the following diagram

Shadow Fun

Sphere

Cone

Generate Shadow volume

Render Shadow Menu

Scene

Object Shape

Viewpoint

Render mode

Action

Step Rotate

Department Of CSE

Page | 9

Shadow Fun

3.1 FUNCTION DESCRIPTION: Sphere( ): To draw a 3d sphere. Cone( ): To draw a 3d cone. Scene( ): Here the objects which are created are placed inside an closed room which has grey textured walls and checker board texture for the floor. Render shadow( ): It s used to enable the shadows and its also used to disable the shadow and lighting. Main( ): When user clicks the right mouse button a menu pops out on the screen showing the different option available to implement on the objects present in the scene .The content inside the menu are. Shape Viewing option Action Shadow render

Menu( ): The above mentioned option have been divided into submenus which are called in this function. Idle( ):This function is used to continue its given operation until another operation is selected by the user. Key( ):In this function we are using keyboard to stop n start the motions in the scene and to change the light source position. The keys used to do certain functions are: Arrow keys :To move the light source position in the scene. Space:To stop the movements in the scene. Enter:To stop the light source.

Department Of CSE

Page | 10

Shadow Fun

3.2 FLOW DIAGRAM: Start


MAIN( )

Calls

INITSCENE( )

DISPLAY

Draws Adds Returns data


SCENE LIGHTING

Right-click
MENU

Quit
EXIT

Department Of CSE

Page | 11

Shadow Fun

3.3 SYSTEM IMPLEMENTATIONS:


glutInit(int *argcv, char **argv); The two arguments allow the user to pass command-line arguments. glutCreateWindow(char *title); This function is used to give the title to the window. glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE); This function is used to initialize a window of size 640x480 void glutDisplayFunc(void (*func)(void)); This function sends the graphics to the screen. void glutKeyboardFunc(void (*func) (unsigned char key, int x, int y)); Parameters: func - The name of the function that will process the "normal" keyboard events. Passing NULL as an argument causes GLUT to ignore "normal" keys. key - indicates the ASCII code of the key pressed

glutAddMenuEntryThis function adds an entry into the menu. glutCreateMenuThis function will create a new menu. glutAddSubMenuThis function will add a submenu into the existing menu to have more options.

3.4 SORCE CODE #include <assert.h> #include <stdio.h> #include <stdlib.h> #include <math.h> #include <GL/glut.h> #ifdef GLU_VERSION_1_2 #ifndef CALLBACK #define CALLBACK #endif #ifndef M_PI
Department Of CSE Page | 12

Shadow Fun

#define M_PI 3.14159265 #endif const float uniquePassThroughValue = 34567.0; #define SmallerOf(a,b) ((a) < (b) ? (a) : (b)) int stencilBits; enum { DL_BALL = 1, DL_CONE, DL_LIGHT, DL_SHADOW_VOLUME, DL_SPHERE, DL_ICO, DL_TORUS, DL_CUBE, DL_SHADOW_VOLUME_TOP, DL_BASE_SHADOW_VOLUME }; enum { M_TORUS, M_CUBE, M_SPHERE, M_ICO, M_DOUBLE_TORUS, M_ANGLE, M_BOUNDARY, M_NO_SHADOW, M_NO_LIGHT, M_FRONT_VOLUME, M_BACK_VOLUME, M_SHADOW, M_LIGHT_SOURCE_VIEW, M_NORMAL_VIEW, M_SPIN, M_SWING, M_STOP }; enum { X, Y, Z }; const int TEXDIM = 64; int shape; GLfloat maxRadius; int renderMode = M_SHADOW; int view = M_NORMAL_VIEW; int renderBoundary = 0; GLfloat angle = 0.0; int frontFace = 1; int rotatingObject = 1; int swingingLight = 1; float swingTime = M_PI / 2.0; GLfloat lightDiffuse[4] =
Department Of CSE Page | 13

Shadow Fun

{1.0, 0.0, 0.0, 1.0}; GLfloat lightPos[4] = {60.0, 50.0, -350.0, 1.0}; GLfloat objectPos[4] = {40.0, 30.0, -360.0, 1.0}; GLfloat sceneEyePos[4] = {0.0, 0.0, 0.0, 0.0}; struct VertexHolder { struct VertexHolder *next; GLfloat v[2]; }; typedef struct _ShadowVolumeMemoryPool { int refcnt; GLUtesselator *tess; GLfloat viewScale; GLfloat *combineList; int combineListSize; int combineNext; struct VertexHolder *excessList; } ShadowVolumeMemoryPool; typedef struct _ShadowVolumeState { ShadowVolumeMemoryPool *pool; GLfloat shadowProjectionDistance; GLfloat extentScale; int saveFirst; GLfloat *firstVertex; } ShadowVolumeState; ShadowVolumeState *svs; static void CALLBACK begin(GLenum type, void *shadowVolumeState) { ShadowVolumeState *svs = (ShadowVolumeState *) shadowVolumeState; assert(type == GL_LINE_LOOP); if (renderBoundary) { glBegin(type); } else { svs->saveFirst = 1; glBegin(GL_TRIANGLE_FAN);
Department Of CSE Page | 14

Shadow Fun

glColor3f(0, 1, 0); glVertex3f(0.0, 0.0, 0.0); } } static void CALLBACK vertex(void *data, void *shadowVolumeState) { ShadowVolumeState *svs = (ShadowVolumeState *) shadowVolumeState; GLfloat *v = data; if (renderBoundary) { glVertex2fv(v); } else { if (svs->saveFirst) { svs->firstVertex = v; svs->saveFirst = 0; } glColor3f(0, 0, 1); glVertex3f(svs->extentScale * v[X], svs->extentScale * v[Y], svs->shadowProjectionDistance); } } static void CALLBACK end(void *shadowVolumeState) { ShadowVolumeState *svs = (ShadowVolumeState *) shadowVolumeState; if (!renderBoundary) { glColor3f(0, 0, 1); glVertex3f(svs->extentScale * svs->firstVertex[X], svs->extentScale * svs>firstVertex[Y], svs->shadowProjectionDistance); } glEnd(); } static void freeExcessList(ShadowVolumeMemoryPool * pool) { struct VertexHolder *holder, *next; holder = pool->excessList;
Department Of CSE Page | 15

Shadow Fun

while (holder) { next = holder->next; free(holder); holder = next; } pool->excessList = NULL; } static void CALLBACK combine(GLdouble coords[3], void *d[4], GLfloat w[4], void **dataOut, void *shadowVolumeState) { ShadowVolumeState *svs = (ShadowVolumeState *) shadowVolumeState; ShadowVolumeMemoryPool *pool = svs->pool; struct VertexHolder *holder; GLfloat *new; if (pool->combineNext >= pool->combineListSize) { holder = (struct VertexHolder *) malloc(sizeof(struct VertexHolder)); holder->next = pool->excessList; pool->excessList = holder; new = holder->v; } else { new = &pool->combineList[pool->combineNext * 2]; } new[0] = coords[0]; new[1] = coords[1]; *dataOut = new; pool->combineNext++; } static void CALLBACK error(GLenum errno) { printf("ERROR: %s\n", gluErrorString(errno)); } static void processFeedback(GLint size, GLfloat * buffer, ShadowVolumeState * svs) { ShadowVolumeMemoryPool *pool = svs->pool; GLfloat *loc, *end, *eyeLoc; GLdouble v[3]; int token, nvertices, i; GLfloat passThroughToken; int watchingForEyePos;
Department Of CSE Page | 16

Shadow Fun

if (pool->combineNext > pool->combineListSize) { freeExcessList(pool); pool->combineListSize = pool->combineNext; pool->combineList = realloc(pool->combineList, sizeof(GLfloat) * 2 * pool>combineListSize); } pool->combineNext = 0; watchingForEyePos = 0; eyeLoc = NULL; glColor3f(1, 1, 1); gluTessBeginPolygon(pool->tess, svs); loc = buffer; end = buffer + size; while (loc < end) { token = *loc; loc++; switch (token) { case GL_POLYGON_TOKEN: nvertices = *loc; loc++; assert(nvertices >= 3); gluTessBeginContour(pool->tess); for (i = 0; i < nvertices; i++) { v[0] = loc[0]; v[1] = loc[1]; v[2] = 0.0; gluTessVertex(pool->tess, v, loc); loc += 2; } gluTessEndContour(pool->tess); break; case GL_PASS_THROUGH_TOKEN: passThroughToken = *loc; if (passThroughToken == uniquePassThroughValue) { watchingForEyePos = !watchingForEyePos; } else { /* Ignore everything else. */ fprintf(stderr, "ERROR: Unexpected feedback token 0x%x (%d).\n", token, token); } loc++; break; case GL_POINT_TOKEN:
Department Of CSE Page | 17

Shadow Fun

if (watchingForEyePos) { fprintf(stderr, "WARNING: Eye point possibly within the shadow volume.\n") fprintf(stderr, " Program should be improved to handle this.\n"); eyeLoc = loc; watchingForEyePos = 0; } else { fprintf(stderr, "ERROR: Unexpected feedback token 0x%x (%d).\n", token, token); } loc += 2; break; default: fprintf(stderr, "ERROR: Unexpected feedback token 0x%x (%d).\n", token, token); } } gluTessEndPolygon(pool->tess); if (eyeLoc && renderBoundary) { glColor3f(0, 1, 0); glPointSize(7.0); glBegin(GL_POINTS); glVertex2fv(eyeLoc); glEnd(); } } static GLfloat vdot(const GLfloat * v1, const GLfloat * v2) { return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]; } static void vcross(const GLfloat * v1, const GLfloat * v2, GLfloat * cross) { assert(v1 != cross && v2 != cross); cross[0] = (v1[1] * v2[2]) - (v1[2] * v2[1]); cross[1] = (v1[2] * v2[0]) - (v1[0] * v2[2]); cross[2] = (v1[0] * v2[1]) - (v1[1] * v2[0]); } void svsFreeShadowVolumeState(ShadowVolumeState * svs)
Department Of CSE Page | 18

Shadow Fun

{ if (svs->pool) { svs->pool->refcnt--; if (svs->pool->refcnt == 0) { if (svs->pool->excessList) { freeExcessList(svs->pool); } if (svs->pool->combineList) { free(svs->pool->combineList); } if (svs->pool->tess) { gluDeleteTess(svs->pool->tess); } free(svs->pool); } } free(svs); } ShadowVolumeState * svsCreateShadowVolumeState(GLfloat shadowProjectionDistance, ShadowVolumeState * shareSVS) { ShadowVolumeState *svs; ShadowVolumeMemoryPool *pool; GLUtesselator *tess; svs = (ShadowVolumeState *) malloc(sizeof(ShadowVolumeState)); if (svs == NULL) { return NULL; } svs->pool = NULL; if (shareSVS == NULL) { pool = (ShadowVolumeMemoryPool *) malloc(sizeof(ShadowVolumeMemoryPool)); if (pool == NULL) { svsFreeShadowVolumeState(svs); return NULL; } pool->refcnt = 1; pool->excessList = NULL; pool->combineList = NULL; pool->combineListSize = 0; pool->combineNext = 0; pool->tess = NULL;
Department Of CSE Page | 19

Shadow Fun

svs->pool = pool; tess = gluNewTess(); if (tess == NULL) { svsFreeShadowVolumeState(svs); return NULL; } gluTessProperty(tess, GLU_TESS_BOUNDARY_ONLY, GL_TRUE); gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO); gluTessCallback(tess, GLU_TESS_BEGIN_DATA, (void (CALLBACK*)()) begin); gluTessCallback(tess, GLU_TESS_VERTEX_DATA, (void (CALLBACK*)()) vertex); gluTessCallback(tess, GLU_TESS_COMBINE_DATA, (void (CALLBACK*)()) combine); gluTessCallback(tess, GLU_TESS_END_DATA, (void (CALLBACK*)()) end); gluTessCallback(tess, GLU_TESS_ERROR, (void (CALLBACK*)()) error); pool->tess = tess; } else { pool = shareSVS->pool; pool->refcnt++; } svs->pool = pool; svs->shadowProjectionDistance = shadowProjectionDistance; return svs; } int svsGenerateShadowVolume(ShadowVolumeState * svs, void (*renderFunc) (void), int feedbackBufferSizeGuess, GLfloat maxRadius, GLfloat lightPos[3], GLfloat objectPos[3], GLfloat eyePos[3]) { static GLfloat unit[3] = {0.0, 0.0, 1.0}; static GLfloat *feedbackBuffer = NULL; static int bufferSize = 0; GLfloat axis[3], lightDelta[3], eyeDelta[3]; GLfloat nnear, ffar; /* Avoid Intel C keywords. Grumble. */
Department Of CSE Page | 20

Shadow Fun

GLfloat lightDistance, eyeDistance, angle, fieldOfViewRatio, fieldOfViewAngle, topScale, viewScale; GLint returned; if (svs->pool->viewScale == 0.0) { GLfloat maxViewSize[2]; glGetFloatv(GL_MAX_VIEWPORT_DIMS, maxViewSize); printf("max viewport = %gx%g\n", maxViewSize[0], maxViewSize[1]); svs->pool->viewScale = SmallerOf(maxViewSize[0], maxViewSize[1]) / 2.0; } viewScale = svs->pool->viewScale; if (bufferSize > feedbackBufferSizeGuess) { feedbackBufferSizeGuess = bufferSize; } /* Calculate the light's distance from the object being shadowed. */ lightDelta[X] = objectPos[X] - lightPos[X]; lightDelta[Y] = objectPos[Y] - lightPos[Y]; lightDelta[Z] = objectPos[Z] - lightPos[Z]; lightDistance = sqrt(lightDelta[X] * lightDelta[X] + lightDelta[Y] * lightDelta[Y] + lightDelta[Z] * lightDelta[Z]); /* Determine the appropriate field of view. We want to use as narrow a field of view as possible to not waste resolution, but not narrower than the object. Add 50% extra slop. */ fieldOfViewRatio = maxRadius / lightDistance; if (fieldOfViewRatio > 0.99) { fprintf(stderr, "WARNING: Clamping FOV to 164 degrees for determining shadow boundary.\n"); fprintf(stderr, " Light distance = %g, object maxmium radius = %g\n", lightDistance, maxRadius); /* 2*asin(0.99) ~= 164 degrees. */ fieldOfViewRatio = 0.99; } /* Pre-compute scaling factors for the near and far extent of the shadow volume. */ svs->extentScale = svs->shadowProjectionDistance * fieldOfViewRatio / viewScale; glMatrixMode(GL_PROJECTION); glPushMatrix();
Department Of CSE Page | 21

Shadow Fun

glLoadIdentity(); nnear = 0.5 * (lightDistance - maxRadius); if (nnear < 0.0001) { fprintf(stderr, "WARNING: Clamping near clip plane to 0.0001 because light source too near.\n"); fprintf(stderr, " Light distance = %g, object maxmium radius = %g\n", lightDistance, maxRadius); nnear = 0.0001; } ffar = 2.0 * (lightDistance + maxRadius); if (eyePos) { eyeDelta[X] = eyePos[X] - lightPos[X]; eyeDelta[Y] = eyePos[Y] - lightPos[Y]; eyeDelta[Z] = eyePos[Z] - lightPos[Z]; eyeDistance = 1.05 * sqrt(eyeDelta[X] * eyeDelta[X] + eyeDelta[Y] * eyeDelta[Y] + eyeDelta[Z] * eyeDelta[Z]); if (eyeDistance > ffar) { ffar = eyeDistance; } } fieldOfViewAngle = 2.0 * asin(fieldOfViewRatio) * 180 / M_PI; gluPerspective(fieldOfViewAngle, 1.0, nnear, ffar); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); /* XXX Need to update "up vector". Degenerate when light directly above or below the object. */ gluLookAt(lightPos[X], lightPos[Y], lightPos[Z], objectPos[X], objectPos[Y], objectPos[Z], 0.0, 1.0, 0.0); /* up is in positive Y direction */ glPushAttrib(GL_VIEWPORT_BIT); glViewport(-viewScale, -viewScale, 2 * viewScale, 2 * viewScale); doFeedback: /* XXX Careful, some systems still don't understand realloc of NULL. */ if (bufferSize < feedbackBufferSizeGuess) { bufferSize = feedbackBufferSizeGuess; /* XXX Add 32 words of slop (an extra cache line) to end for buggy hardware that uses DMA to return feedback results but that sometimes
Department Of CSE Page | 22

Shadow Fun

overrun the buffer. Yuck. */ feedbackBuffer = realloc(feedbackBuffer, bufferSize * sizeof(GLfloat) + 32 * 4); } glFeedbackBuffer(bufferSize, GL_2D, feedbackBuffer); (void) glRenderMode(GL_FEEDBACK); (*renderFunc) (); /* Render the eye position. The eye position is "bracketed" by unique pass through tokens. These bracketing pass through tokens let us determine if the eye position was clipped or not. This helps us determine whether the eye position is possibly within the shadow volume or not. If the point is clipped, the eye position is not in the shadow volume. If the point is not clipped, a more complicated test is necessary to determine if the eye position is really in the shadow volume or not. See processFeedback. */ if (eyePos) { glPassThrough(uniquePassThroughValue); glBegin(GL_POINTS); glVertex3fv(eyePos); glEnd(); glPassThrough(uniquePassThroughValue); } returned = glRenderMode(GL_RENDER); #if 0 if (returned == -1) { #else /* XXX RealityEngine workaround. */ if (returned == -1 || returned == feedbackBufferSizeGuess) { #endif feedbackBufferSizeGuess = feedbackBufferSizeGuess + (feedbackBufferSizeGuess >> 1); goto doFeedback; /* Try again with larger feedback buffer. */ } glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glPopAttrib(); /* Restore viewport. */ if (renderBoundary) {
Department Of CSE Page | 23

Shadow Fun

glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(-viewScale, viewScale, -viewScale, viewScale); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); processFeedback(returned, feedbackBuffer, svs); } else { glNewList(DL_BASE_SHADOW_VOLUME, GL_COMPILE); vcross(unit, lightDelta, axis); angle = acos(vdot(unit, lightDelta) / lightDistance) * 180.0 / M_PI; glRotatef(angle, axis[X], axis[Y], axis[Z]); processFeedback(returned, feedbackBuffer, svs); glEndList(); glNewList(DL_SHADOW_VOLUME, GL_COMPILE); glPushMatrix(); glTranslatef(lightPos[X], lightPos[Y], lightPos[Z]); glCallList(DL_BASE_SHADOW_VOLUME); glPopMatrix(); glEndList(); glNewList(DL_SHADOW_VOLUME_TOP, GL_COMPILE); glPushMatrix(); glTranslatef(lightPos[X], lightPos[Y], lightPos[Z]); topScale = (lightDistance + maxRadius) / svs->shadowProjectionDistance; glScalef(topScale, topScale, topScale); glCallList(DL_BASE_SHADOW_VOLUME); glPopMatrix(); glEndList(); } return returned; } GLfloat objectMaxRadius[] = { 8.0 + 2.0, /* M_TORUS */ 12.0 / 2.0 * 1.142, /* M_CUBE */ 8.0, /* M_SPHERE */ 8.0, /* M_ICO */ 8.0 + 2.0, /* M_DOUBLE_TORUS */ }; void
Department Of CSE Page | 24

Shadow Fun

renderShadowingObject(void) { static int torusList = 0, cubeList = 0, sphereList = 0, icoList = 0; glPushMatrix(); glTranslatef(objectPos[X], objectPos[Y], objectPos[Z]); glRotatef(angle, 1.0, 0.3, 0.0); switch (shape) { case M_TORUS: if (torusList) { glCallList(torusList); } else { torusList = DL_TORUS; glNewList(torusList, GL_COMPILE_AND_EXECUTE); glutSolidTorus(2.0, 8.0, 8, 15); glEndList(); } break; case M_CUBE: if (cubeList) { glCallList(cubeList); } else { cubeList = DL_CUBE; glNewList(cubeList, GL_COMPILE_AND_EXECUTE); glutSolidCube(12.0); glEndList(); } break; case M_SPHERE: if (sphereList) { glCallList(sphereList); } else { sphereList = DL_SPHERE; glNewList(sphereList, GL_COMPILE_AND_EXECUTE); glutSolidSphere(8.0, 10, 10); glEndList(); } break; case M_ICO: if (icoList) { glCallList(icoList); } else { icoList = DL_ICO;
Department Of CSE Page | 25

Shadow Fun

glNewList(icoList, GL_COMPILE_AND_EXECUTE); glEnable(GL_NORMALIZE); glPushMatrix(); glScalef(8.0, 8.0, 8.0); glutSolidIcosahedron(); glPopMatrix(); glDisable(GL_NORMALIZE); glEndList(); } break; case M_DOUBLE_TORUS: if (torusList) { glCallList(torusList); } else { torusList = DL_TORUS; glNewList(torusList, GL_COMPILE_AND_EXECUTE); glutSolidTorus(2.0, 8.0, 8, 15); glEndList(); } glRotatef(90, 0, 1, 0); glCallList(torusList); break; } glPopMatrix(); } void sphere(void) { glPushMatrix(); glTranslatef(60.0, -50.0, -400.0); glCallList(DL_BALL); glPopMatrix(); } void cone(void) { glPushMatrix(); glTranslatef(-40.0, -40.0, -400.0); glCallList(DL_CONE); glPopMatrix(); }
Department Of CSE Page | 26

Shadow Fun

void scene(void) { /* material properties for objects in scene */ static GLfloat wall_mat[] = {1.0, 1.0, 1.0, 1.0}; static GLfloat shad_mat[] = {1.0, 0.1, 0.1, 1.0}; glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (view == M_LIGHT_SOURCE_VIEW) { gluPerspective(45.0, 1.0, 0.1, 600.0); } else { gluPerspective(33.0, 1.0, 1.0, 600.0); } glMatrixMode(GL_MODELVIEW); glLoadIdentity(); if (view == M_LIGHT_SOURCE_VIEW) { gluLookAt(lightPos[X], lightPos[Y], lightPos[Z], objectPos[X], objectPos[Y], objectPos[Z], 0.0, 1.0, 0.); /* up is in positive Y direction */ } else { gluLookAt(0.0, 0.0, 0.0, 0.0, 0.0, -100.0, 0.0, 1.0, 0.); /* up is in positive Y direction */ } /* Place light 0 in the right place. */ glLightfv(GL_LIGHT0, GL_POSITION, lightPos); /* Note: wall verticies are ordered so they are all front facing this lets me do back face culling to speed things up. */ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, wall_mat); /* Floor with checkerboard texture. */ glEnable(GL_TEXTURE_2D); glColor3f(0, 0, 0); /* Since we want to turn texturing on for floor only, we have to make floor a separate glBegin()/glEnd() sequence. You can't turn texturing on and
Department Of CSE Page | 27

Shadow Fun

off between begin and end calls */ glBegin(GL_QUADS); glNormal3f(0.0, 1.0, 0.0); glTexCoord2i(0, 0); glVertex3f(-100.0, -100.0, -320.0); glTexCoord2i(4, 0); glVertex3f(100.0, -100.0, -320.0); glTexCoord2i(4, 4); glVertex3f(100.0, -100.0, -520.0); glTexCoord2i(0, 4); glVertex3f(-100.0, -100.0, -520.0); glEnd(); glDisable(GL_TEXTURE_2D); /* Walls. */ glBegin(GL_QUADS); /* Left wall. */ glNormal3f(1.0, 0.0, 0.0); glVertex3f(-100.0, -100.0, -320.0); glVertex3f(-100.0, -100.0, -520.0); glVertex3f(-100.0, 100.0, -520.0); glVertex3f(-100.0, 100.0, -320.0); /* Right wall. */ glNormal3f(-1.0, 0.0, 0.0); glVertex3f(100.0, -100.0, -320.0); glVertex3f(100.0, 100.0, -320.0); glVertex3f(100.0, 100.0, -520.0); glVertex3f(100.0, -100.0, -520.0); /* Ceiling. */ glNormal3f(0.0, -1.0, 0.0); glVertex3f(-100.0, 100.0, -320.0); glVertex3f(-100.0, 100.0, -520.0); glVertex3f(100.0, 100.0, -520.0); glVertex3f(100.0, 100.0, -320.0); /* Back wall. */ glNormal3f(0.0, 0.0, 1.0); glVertex3f(-100.0, -100.0, -520.0); glVertex3f(100.0, -100.0, -520.0);
Department Of CSE Page | 28

Shadow Fun

glVertex3f(100.0, 100.0, -520.0); glVertex3f(-100.0, 100.0, -520.0); glEnd(); cone(); sphere(); glPushMatrix(); glTranslatef(lightPos[X], lightPos[Y], lightPos[Z]); glCallList(DL_LIGHT); glPopMatrix(); /* Draw shadowing object. */ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, shad_mat); renderShadowingObject(); } void generateShadowVolume(void) { GLfloat *eyePos; if (view == M_LIGHT_SOURCE_VIEW) { eyePos = lightPos; } else { eyePos = sceneEyePos; } svsGenerateShadowVolume(svs, renderShadowingObject, 250, maxRadius, lightPos, objectPos, eyePos); } void display(void) { if (renderBoundary) { glClear(GL_COLOR_BUFFER_BIT); glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); generateShadowVolume(); glEnable(GL_LIGHTING);
Department Of CSE Page | 29

Shadow Fun

} else { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); switch (renderMode) { case M_NO_SHADOW: glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHT0); scene(); break; case M_NO_LIGHT: /* Render scene without the light source enabled (conceptually, the entire scene is "in the shadow"). */ glEnable(GL_DEPTH_TEST); glDisable(GL_LIGHT0); scene(); break; case M_FRONT_VOLUME: case M_BACK_VOLUME: generateShadowVolume(); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHT0); scene(); if (frontFace) { glFrontFace(GL_CW); } else { glFrontFace(GL_CCW); } glCallList(DL_SHADOW_VOLUME); glFrontFace(GL_CCW); break; case M_SHADOW: /* Construct DL_SHADOW_VOLUME display list for the scene's current shadow volume. */ generateShadowVolume(); /* 1st scene pass. */ glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHT0); scene(); /* 1st shadow volume pass: Enable stencil to increment the stencil value of pixels that pass the depth test when drawing the front
Department Of CSE Page | 30

Shadow Fun

facing polygons of the shadow volume. Do not update the depth buffer while rendering the shadow volume. */ glDisable(GL_LIGHTING); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glEnable(GL_STENCIL_TEST); glDepthMask(GL_FALSE); glStencilFunc(GL_ALWAYS, 0, 0); glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT); glCullFace(GL_FRONT); glCallList(DL_SHADOW_VOLUME); /* 2nd shadow volume pass: Now, draw the back facing polygons of the shadow volume except decrement pixels that pass the depth test. Again, do not update the depth buffer. */ glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT); glCullFace(GL_BACK); glCallList(DL_SHADOW_VOLUME); glDisable(GL_CULL_FACE); glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO); glCallList(DL_SHADOW_VOLUME_TOP); glEnable(GL_CULL_FACE); /* Now, pixels that lie within the shadow volume are tagged with a one stencil value. Empty shadowed regions of the shadow volume get incremented, then decremented, to resolve to a net zero stencil value. */ /* 2nd scene pass (render shadowed region): Re-enable update of the depth and color buffer (use GL_LEQUAL for depth buffer so we can over-write depth values again with color. Switch back to backface culling and disable the light source. Only update pixels with a stencil value of one (shadowed). */ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); #if 0 glDepthFunc(GL_EQUAL); #else glDepthMask(GL_TRUE); glDepthFunc(GL_LEQUAL); #endif glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glStencilFunc(GL_EQUAL, 1, 1); glDisable(GL_LIGHT0);
Department Of CSE Page | 31

Shadow Fun

glEnable(GL_LIGHTING); scene(); /* Put state back to sane modes. */ glDepthMask(GL_TRUE); glDepthFunc(GL_LESS); glDisable(GL_STENCIL_TEST); break; } } glutSwapBuffers(); } void idle(void) { if (rotatingObject) { angle += 10.0; } if (swingingLight) { swingTime += 0.05; lightPos[X] += 2 * cos(swingTime); } glutPostRedisplay(); } void menu(int value) { switch (value) { case M_TORUS: case M_CUBE: case M_SPHERE: case M_ICO: case M_DOUBLE_TORUS: shape = value; maxRadius = objectMaxRadius[value]; glutPostRedisplay(); break; case M_ANGLE: angle += 10.0; glutPostRedisplay(); break;
Department Of CSE Page | 32

Shadow Fun

case M_BOUNDARY: renderBoundary = 1; glutPostRedisplay(); break; case M_FRONT_VOLUME: case M_BACK_VOLUME: frontFace = (value == M_FRONT_VOLUME); /* FALLTHROUGH */ case M_NO_SHADOW: case M_NO_LIGHT: case M_SHADOW: renderBoundary = 0; renderMode = value; glutPostRedisplay(); break; case M_LIGHT_SOURCE_VIEW: case M_NORMAL_VIEW: view = value; glutPostRedisplay(); break; case M_STOP: swingingLight = 0; rotatingObject = 0; glutIdleFunc(NULL); break; case M_SPIN: rotatingObject = 1; glutIdleFunc(idle); break; case M_SWING: swingingLight = 1; glutIdleFunc(idle); break; case 666: svsFreeShadowVolumeState(svs); exit(0); break; } } void visible(int vis) {
Department Of CSE Page | 33

Shadow Fun

if (vis == GLUT_VISIBLE && swingingLight && rotatingObject) { glutIdleFunc(idle); } else { glutIdleFunc(NULL); } } void key(unsigned char c, int x, int y) { switch (c) { case 27: /* Escape. */ svsFreeShadowVolumeState(svs); exit(0); break; case 13: /* Return. */ swingingLight = !swingingLight; swingTime = M_PI / 2.0; break; case ' ': /* Space. */ if (rotatingObject || swingingLight) { rotatingObject = 0; swingingLight = 0; glutIdleFunc(NULL); } else { rotatingObject = 1; swingingLight = 1; glutIdleFunc(idle); } break; } } void special(int key, int x, int y) { switch (key) { case GLUT_KEY_HOME: frontFace = !frontFace; glutPostRedisplay(); break; case GLUT_KEY_UP: lightPos[Y] += 10.0;
Department Of CSE Page | 34

Shadow Fun

glutPostRedisplay(); break; case GLUT_KEY_DOWN: lightPos[Y] -= 10.0; glutPostRedisplay(); break; case GLUT_KEY_PAGE_UP: lightPos[Z] += 10.0; glutPostRedisplay(); break; case GLUT_KEY_PAGE_DOWN: lightPos[Z] -= 10.0; glutPostRedisplay(); break; case GLUT_KEY_RIGHT: lightPos[X] += 10.0; glutPostRedisplay(); break; case GLUT_KEY_LEFT: lightPos[X] -= 10.0; glutPostRedisplay(); break; } } GLfloat * makeTexture(int maxs, int maxt) { int s, t; static GLfloat *texture; texture = (GLfloat *) malloc(maxs * maxt * sizeof(GLfloat)); for (t = 0; t < maxt; t++) { for (s = 0; s < maxs; s++) { texture[s + maxs * t] = ((s >> 4) & 0x1) ^ ((t >> 4) & 0x1); } } return texture; } void initScene(void) {
Department Of CSE Page | 35

Shadow Fun

GLfloat *tex; GLUquadricObj *qobj; static GLfloat sphere_mat[] = {1.0, 0.5, 0.0, 1.0}; static GLfloat cone_mat[] = {0.0, 0.5, 1.0, 1.0}; glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_CULL_FACE); glCullFace(GL_BACK); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); qobj = gluNewQuadric(); glNewList(DL_BALL, GL_COMPILE); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, sphere_mat); gluSphere(qobj, 20.0, 20, 20); glEndList(); glNewList(DL_CONE, GL_COMPILE); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cone_mat); glRotatef(-90.0, 1.0, 0.0, 0.0); gluDisk(qobj, 0.0, 20.0, 20, 1); gluCylinder(qobj, 20.0, 0.0, 60.0, 20, 20); glEndList(); glNewList(DL_LIGHT, GL_COMPILE); glDisable(GL_LIGHTING); glColor3f(0.9, 0.9, 0.6); gluSphere(qobj, 5.0, 20, 20); glEnable(GL_LIGHTING); glEndList(); gluDeleteQuadric(qobj); /* load pattern for current 2d texture */ tex = makeTexture(TEXDIM, TEXDIM); glTexImage2D(GL_TEXTURE_2D, 0, 1, TEXDIM, TEXDIM, 0, GL_RED, GL_FLOAT, tex);
Department Of CSE Page | 36

Shadow Fun

free(tex); } int main(int argc, char **argv) { int shapeMenu, viewMenu, actionMenu, renderModeMenu; svs = svsCreateShadowVolumeState(1000.0, NULL); glutInitDisplayString("stencil>=1 rgb double depth samples"); glutInit(&argc, argv); glutCreateWindow("shadowfun"); stencilBits = glutGet(GLUT_WINDOW_STENCIL_SIZE); printf("bits of stencil = %d\n", stencilBits); glutDisplayFunc(display); glutVisibilityFunc(visible); glutSpecialFunc(special); glutKeyboardFunc(key); initScene(); shapeMenu = glutCreateMenu(menu); glutAddMenuEntry("Torus", M_TORUS); glutAddMenuEntry("Cube", M_CUBE); glutAddMenuEntry("Sphere", M_SPHERE); glutAddMenuEntry("Icosahedron", M_ICO); glutAddMenuEntry("Double Torus", M_DOUBLE_TORUS); viewMenu = glutCreateMenu(menu); glutAddMenuEntry("Normal view", M_NORMAL_VIEW); glutAddMenuEntry("Light source view", M_LIGHT_SOURCE_VIEW); renderModeMenu = glutCreateMenu(menu); glutAddMenuEntry("With shadow", M_SHADOW); glutAddMenuEntry("With front shadow volume", M_FRONT_VOLUME); glutAddMenuEntry("With back shadow volume", M_BACK_VOLUME); glutAddMenuEntry("Without shadow", M_NO_SHADOW); glutAddMenuEntry("Without light", M_NO_LIGHT); glutAddMenuEntry("2D shadow boundary", M_BOUNDARY); actionMenu = glutCreateMenu(menu); glutAddMenuEntry("Spin object", M_SPIN); glutAddMenuEntry("Swing light", M_SWING); glutAddMenuEntry("Stop", M_STOP); glutCreateMenu(menu); glutAddSubMenu("Object shape", shapeMenu);
Department Of CSE Page | 37

Shadow Fun

glutAddSubMenu("Viewpoint", viewMenu); glutAddSubMenu("Render mode", renderModeMenu); glutAddSubMenu("Action", actionMenu); glutAddMenuEntry("Step rotate", M_ANGLE); glutAddMenuEntry("Quit", 666); glutAttachMenu(GLUT_RIGHT_BUTTON); menu(M_DOUBLE_TORUS); glutMainLoop(); return 0; /* ANSI C requires main to return int. */ } #else int main(int argc, char** argv) { fprintf(stderr, "This program requires the new tesselator API in GLU 1.2.\n"); fprintf(stderr, "Your GLU library does not support this new interface, sorry.\n"); return 0; } #endif /* GLU_VERSION_1_2 */

3.5 SYSTEM TESTING:


The project is tested on different machines which meet the above stated requirements and it is indeed compatible and portable.The shadow fun is tested for each possible options shown in the menu,i.e light source movement,changing the viewing source,object shapes,controlling the position of the light and step rotation.

Department Of CSE

Page | 38

Shadow Fun

4. RESULT
4.1 SCREEN SHOT:

Department Of CSE

Page | 39

Shadow Fun

Department Of CSE

Page | 40

Shadow Fun

Department Of CSE

Page | 41

Shadow Fun

5. CONCLUSION

The project has the capability to evolve i.e., a whole lot of new features can be added to it. This project is a simulation of Shadow Fun which is implemented by unleashing the power of Computer Graphics using OpenGL. It could be used for various education and non-educationl purposes as stated above. This project has enabled us to understand computer graphics concepts through their implementations. We were also able to appreciate these concepts when their effects were realized. Improvements can be made to the Shadow Fun as stated above.

Department Of CSE

Page | 42

Shadow Fun

6. BIBLIOGRAPHY
6.1 TEXTS:
1.Interactive Computer Graphics A Top Down Approach with OpenGL by Edward Angel 2.Computer Graphics by James D Foley, Andries Van Dam, Steven K Feiner and John F Hughes

6.2 LINKS:
1.opengl.softalizer.com/reviews.html 2.glprogramming.com/red/chapter14.html 3.wn.com/OpenGL_3D_Engine_%5BHD_720p%5D 4.www.freedownloadmanager.org/.../opengl-shadows-sample-2365347.html 5. www.filebuzz.com/findsoftware/Road...Simulation...Opengl/2.html

Department Of CSE

Page | 43

You might also like