The following is the final C program for tutorial # 5: /***************************************************************************** Example NuGraf Rendering Library Script File # 4 This Demonstrates the INDEXEDPOLYGON and USERDEFINED Primitives, Shadow Mapping, and the Fog Atmospheric Shader. See Explanation in the NuGraf Reference Manual - Tutorial Chapter. This file can be compiled and run stand-alone. Copyright (c) 1988, 2003 Okino Computer Graphics, Inc. All Rights Reserved. *****************************************************************************/ #include "ni.h" /* This is the main NuGraf include file */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> /* Define ONE of the following to be Nc_TRUE. It selects the geometric primitive */ /* type to use which will send the polygonal data to the renderer. */ #define USE_POLYGON_PRIMITIVE Nc_FALSE #define USE_INDEXEDPOLYGON_PRIMITIVE Nc_FALSE #define USE_USERDEFINED_PRIMITIVE Nc_TRUE /* Resolution of the image */ #define IMAGE_X_RESOLUTION 512 #define IMAGE_Y_RESOLUTION 488 static Nd_Void UserDefined_Primitive_Callback(Nd_UserDefPrim_Callback_Info *cbi); /* --------------->>>> Polygon Geometry <<<<----------------- */ static Nd_Int num_floor_vertices=4; static Nd_Int num_wall_vertices=4; static Nd_Vector wall_vertices[]={ { 1.0, 1.0, 0.0 }, { 1.0, 1.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 } }; static Nd_Vector floor_vertices[]={ { 1.0, 0.0, 1.0 }, { 1.0, 0.0, 1.0 }, { 1.0, 0.0, 1.0 }, { 1.0, 0.0, 1.0 } }; static Nd_Vector texture_coordinates[]={ { 1.0, 0.0, 0.0 }, { 1.0, 1.0, 0.0 }, { 0.0, 1.0, 0.0 }, { 0.0, 0.0, 0.0 } }; /*>>>> IndexedPolygon Primitive Variables <<<<-------- */ #if USE_INDEXEDPOLYGON_PRIMITIVE /* Total number of polygons in the object */ static Nd_Int num_polygons=1; /* Array of length 'num_polygons' describing the # of vertices in */ /* each polygon (including holes and islands). */ static Nd_Int num_vertices_per_polygon[]={ 4 }; /* Vertex data variables */ static Nd_Int num_vertex_coords=4; static Nd_Int vertex_indices[]={ 1, 2, 3, 4 }; /* Texture coordinates variables */ static Nd_Int num_texture_coords=4; static Nd_Int texture_indices[]={ 1, 2, 3, 4 }; #endif /* USE_INDEXEDPOLYGON_PRIMITIVE */ Nd_Void main() { char *home_directory=NULL; char *current_working_directory=NULL; /* General variables */ Nd_Vector vec; Nd_Float rotation_angle; Nd_Int Oversampling_Values[2]={ 1, 4 }; /* The 32-bit user-defined values passed to the primitive callback */ Nd_Ptr Nv_User_Data_Ptr1; Nd_Ptr Nv_User_Data_Ptr2; /* Sphere primitive parameters */ Nd_Float sph_radius=1; Nd_Int sph_u_subdiv=14; /* parametric u & v subdivisions */ Nd_Int sph_v_subdiv=14; /* Texture mapping parameters */ Nd_Float floor_u_scale=1.0 / 512.0; Nd_Float floor_v_scale=1.0 / 128.0; Nd_Float wall_u_scale=1.0 / 6.0; Nd_Float wall_v_scale=1.0 / 6.0; /* Shading coefficients for the polygons */ Nd_Float ambient_coeff=0.4; Nd_Float diffuse_coeff=0.3; Nd_Float specular_coeff=0.7; /* Light source variables */ Nd_Vector light1_shinefrom={ 9.0, 16.0, 0.0 }; Nd_Vector light2_shinefrom={ 8.0, 15.0, 5.0 }; Nd_Vector light3_shinefrom={ 20.0, 20.0, 20.0 }; Nd_Vector light3_shineat={ 0.0, 10.0, 0.0 }; Nd_Float light3_cutoff_angle=22.5; Nd_Vector light4_shinefrom={ 0.0, 1.0, 0.0 }; Nd_Float light4_intensity=0.5; /* Fog variables */ Nd_Float fog_near_distance=10.0; Nd_Float fog_far_distance=50.0; Nd_Float fog_near_blend=0.0; Nd_Float fog_far_blend=1.0; /* Shadow map parameters for light 1 */ Nd_Float SM_Attenuation=0.8; Nd_Int SM_Numsamples=32; Nd_Float SM_Resfactor=2; Nd_Float SM_Bias0=0.1; Nd_Float SM_Bias1=0.2; Nd_Int SM_Resolution=512; /* Shadow map camera parameters */ Nd_Vector sm_camera_lookfrom={ 20.0, 24.0, 20.0 }; Nd_Vector sm_camera_lookat={ 0.0, 4.0, 0.0 }; Nd_Float sm_camera_distance=10.0; Nd_Float sm_camera_window[2]={ 4.0, 4.0 }; /* Camera variables */ Nd_Vector lookfrom={ 0.0, 5.0, 18.0 }; Nd_Vector lookat={ 0.0, 4.0, 0.0 }; Nd_Float camera_window[]={ 1.0, 1.0 }; Nd_Float camera_focallength=1.0; /* Image Resolution */ Nd_Int image_res[2]; /*>>>> Initialize the Library <<<<------------- */ /* Initialize the library and the directory locations */ Ni_Initialize(home_directory, current_working_directory); /*>>>> Define Textures <<<<----------------- */ /* 2D texture image for general texture mapping */ Ni_Texture("checker bitmap texture", Nt_IMAGE, Nt_TEXTUREIMAGE, Nt_TIFF, "check256.tif", Nt_CMDSEP, Nt_FILTER, Nt_MIPMAP, Nt_CMDSEP, Nt_CMDEND); /*>>>> Define Surfaces <<<<--------------- */ Ni_Surface("floor surface", Nt_SHADINGCOEFFS, Nt_AMBIENT, (Nd_Float *) &ambient_coeff, Nt_DIFFUSE, (Nd_Float *) &diffuse_coeff, Nt_SPECULAR, (Nd_Float *) &specular_coeff, Nt_CMDSEP, Nt_TEXTURE, "layer 1", Nt_TEXTURELINK, "checker bitmap texture", Nt_USCALE, (Nd_Float *) &floor_u_scale, Nt_VSCALE, (Nd_Float *) &floor_v_scale, Nt_CMDSEP, Nt_CMDEND); Ni_Surface("wall surface", Nt_SHADINGCOEFFS, Nt_AMBIENT, (Nd_Float *) &ambient_coeff, Nt_DIFFUSE, (Nd_Float *) &diffuse_coeff, Nt_SPECULAR, (Nd_Float *) &specular_coeff, Nt_CMDSEP, Nt_TEXTURE, "layer 1", Nt_TEXTURELINK, "checker bitmap texture", Nt_USCALE, (Nd_Float *) &wall_u_scale, Nt_VSCALE, (Nd_Float *) &wall_v_scale, Nt_CMDSEP, Nt_CMDEND); Ni_Surface("sphere 1 surface", Nt_COLOR, Nt_COLORNAME, "red", Nt_CMDEND); Ni_Surface("sphere 2 surface", Nt_COLOR, Nt_COLORNAME, "green", Nt_CMDEND); /*>>>> Define Sphere Object <<<<-------------- */ /* Create a single sphere object centered at the origin */ Ni_Object_Define("sphere object", Nt_CMDEND); Ni_Primitive(Nt_SPHERE, Nt_RADIUS, (Nd_Float *) &sph_radius, Nt_CMDSEP, Nt_CMDEND); Ni_Object_End(Nt_CMDEND); /*>>>> Define Polygonal Objects <<<<------------ */ #if USE_POLYGON_PRIMITIVE Ni_Object_Define("wall object", Nt_CMDEND); Ni_Primitive(Nt_POLYGON, Nt_NUMVERTICES, (Nd_Int *) &num_wall_vertices, Nt_CMDSEP, Nt_VERTEX, (Nd_Vector *) wall_vertices, Nt_CMDSEP, Nt_TEXTURE, (Nd_Vector *) texture_coordinates, Nt_CMDSEP, Nt_CMDEND); Ni_Object_End(Nt_CMDEND); Ni_Object_Define("floor object", Nt_CMDEND); Ni_Primitive(Nt_POLYGON, Nt_NUMVERTICES, (Nd_Int *) &num_floor_vertices, Nt_CMDSEP, Nt_VERTEX, (Nd_Vector *) floor_vertices, Nt_CMDSEP, Nt_TEXTURE, (Nd_Vector *) texture_coordinates, Nt_CMDSEP, Nt_CMDEND); Ni_Object_End(Nt_CMDEND); #elif USE_INDEXEDPOLYGON_PRIMITIVE Ni_Object_Define("wall object", Nt_CMDEND); Ni_Primitive(Nt_INDEXEDPOLYGONS, Nt_NUMPOLYGONS, (Nd_Int *) &num_polygons, Nt_CMDSEP, Nt_VERTICESPERPOLY, (Nd_Int *) num_vertices_per_polygon, Nt_CMDSEP, Nt_VERTEX, (Nd_Int *) &num_vertex_coords, (Nd_Vector *) wall_vertices, (Nd_Int *) vertex_indices, Nt_CMDSEP, Nt_TEXTURE, (Nd_Int *) &num_texture_coords, (Nd_Vector *) texture_coordinates, (Nd_Int *) texture_indices, Nt_CMDSEP, Nt_CMDEND); Ni_Object_End(Nt_CMDEND); Ni_Object_Define("floor object", Nt_CMDEND); Ni_Primitive(Nt_INDEXEDPOLYGONS, Nt_NUMPOLYGONS, (Nd_Int *) &num_polygons, Nt_CMDSEP, Nt_VERTICESPERPOLY, (Nd_Int *) num_vertices_per_polygon, Nt_CMDSEP, Nt_VERTEX, (Nd_Int *) &num_vertex_coords, (Nd_Vector *) floor_vertices, (Nd_Int *) vertex_indices, Nt_CMDSEP, Nt_TEXTURE, (Nd_Int *) &num_texture_coords, (Nd_Vector *) texture_coordinates, (Nd_Int *) texture_indices, Nt_CMDSEP, Nt_CMDEND); Ni_Object_End(Nt_CMDEND); #elif USE_USERDEFINED_PRIMITIVE /* Create a wall object which uses the user-defined callback function */ /* Pass the vertices and texture coordinates in the 32-bit user data pointers. */ Nv_User_Data_Ptr1=(void *) wall_vertices; Nv_User_Data_Ptr2=(void *) texture_coordinates; Ni_Object_Define("wall object", Nt_CMDEND); Ni_Primitive(Nt_USERDEFINED, (Nd_UserDefPrim_CB_Func) UserDefined_Primitive_Callback, (void **) &Nv_User_Data_Ptr1, (void **) &Nv_User_Data_Ptr2, Nt_CMDEND); Ni_Object_End(Nt_CMDEND); /* Create a floor object which uses the user-defined callback function */ /* Pass the vertices and texture coordinates in the 32-bit user data pointers. */ Nv_User_Data_Ptr1=(void *) floor_vertices; Nv_User_Data_Ptr2=(void *) texture_coordinates; Ni_Object_Define("floor object", Nt_CMDEND); Ni_Primitive(Nt_USERDEFINED, (Nd_UserDefPrim_CB_Func) UserDefined_Primitive_Callback, (void **) &Nv_User_Data_Ptr1, (void **) &Nv_User_Data_Ptr2, Nt_CMDEND); Ni_Object_End(Nt_CMDEND); #endif /*>>>> Link Surfaces to Objects <<<<----------- */ Ni_Surfacelink(Nt_SURFACE, "floor surface", Nt_OBJECT, "floor object", Nt_CMDEND); Ni_Surfacelink(Nt_SURFACE, "wall surface", Nt_OBJECT, "wall object", Nt_CMDEND); /*>>>> Make Instances <<<<------------------ */ Ni_Add_Instance(Nt_INSTANCE, "sphere instance 1", Nt_OBJECT, "sphere object", Nt_CMDEND); Ni_Attach(Nt_INSTANCE, "sphere instance 1", Nt_INSTANCE, "world", Nt_CMDEND); Ni_Add_Instance(Nt_INSTANCE, "sphere instance 2", Nt_OBJECT, "sphere object", Nt_CMDEND); Ni_Attach(Nt_INSTANCE, "sphere instance 2", Nt_INSTANCE, "world", Nt_CMDEND); Ni_Add_Instance(Nt_INSTANCE, "floor instance", Nt_OBJECT, "floor object", Nt_CMDEND); Ni_Attach(Nt_INSTANCE, "floor instance", Nt_INSTANCE, "world", Nt_CMDEND); Ni_Add_Instance(Nt_INSTANCE, "wall instance", Nt_OBJECT, "wall object", Nt_CMDEND); Ni_Attach(Nt_INSTANCE, "wall instance", Nt_INSTANCE, "world", Nt_CMDEND); /*>>>> Link Surfaces to Instances <<<<---------- */ Ni_Surfacelink(Nt_SURFACE, "sphere 1 surface", Nt_INSTANCE, "sphere instance 1", Nt_CMDEND); Ni_Surfacelink(Nt_SURFACE, "sphere 2 surface", Nt_INSTANCE, "sphere instance 2", Nt_CMDEND); /*>>>> Instance Attributes <<<<----------------- */ /* The floor does not cast shadows */ Ni_Instance("floor instance", Nt_CASTSSHADOWS, Nt_ENABLED, Nt_OFF, Nt_CMDSEP, Nt_SHADOWED, Nt_ENABLED, Nt_ON, Nt_CMDSEP, Nt_CMDEND); /*>>>> Apply the Transformations <<<<----------- */ /* Scale and rotate the wall instance */ vec[0]=6.0; vec[1]=10.0; vec[2]=1.0; Ni_Transform(Nt_INSTANCE, "wall instance", Nt_POSTMULTIPLY, Nt_SCALE, (Nd_Vector *) vec, Nt_CMDEND); rotation_angle=45.0; Ni_Transform(Nt_INSTANCE, "wall instance", Nt_POSTMULTIPLY, Nt_ROTATE, Nt_YAXIS, (Nd_Float *) &rotation_angle, Nt_CMDEND); /* Scale the floor instance */ vec[0]=1000.0; vec[1]=1.0; vec[2]=500.0; Ni_Transform(Nt_INSTANCE, "floor instance", Nt_POSTMULTIPLY, Nt_SCALE, (Nd_Vector *) vec, Nt_CMDEND); /* Translate sphere # 1 into position */ vec[0]=1.0; vec[1]=7.0; vec[2]=3.0; Ni_Transform(Nt_INSTANCE, "sphere instance 1", Nt_POSTMULTIPLY, Nt_TRANSLATE, (Nd_Vector *) vec, Nt_CMDEND); /* Translate sphere # 2 into position */ vec[0]=5.0; vec[1]=5.0; vec[2]=0.0; Ni_Transform(Nt_INSTANCE, "sphere instance 2", Nt_POSTMULTIPLY, Nt_TRANSLATE, (Nd_Vector *) vec, Nt_CMDEND); /*>>>> Render <<<<------------------ */ /* Set the resolution of the image */ image_res[Na_X_VALUE]=IMAGE_X_RESOLUTION; image_res[Na_Y_VALUE]=IMAGE_Y_RESOLUTION; Ni_Option( Nt_ANTIALIAS, Nt_ENABLED, Nt_OFF, Nt_OVERSAMPLE, (Nd_Int *) Oversampling_Values, Nt_CMDSEP, Nt_CULLING, Nt_BACK, Nt_CMDSEP, Nt_RESOLUTION, (Nd_Int *) image_res, Nt_CMDSEP, Nt_SHADING, Nt_SMOOTH, Nt_CMDSEP, Nt_SHADOWS, Nt_ENABLED, Nt_ON, Nt_CMDSEP, Nt_SUBDIVISIONS, Nt_SPHERE, Nt_USUBDIV, (Nd_Int *) &sph_u_subdiv, Nt_VSUBDIV, (Nd_Int *) &sph_v_subdiv, Nt_CMDSEP, Nt_CMDEND); /* Set the global shadowmap parameters */ Ni_Option(Nt_SHADOWMAP, /* The following parameters are used during shadowmap creation */ Nt_CULLINGOVERRIDE, Nt_BACK, Nt_SHADOWMAPSIZE, (Nd_Int *) &SM_Resolution, /* The following parameters are used during shadow rendering */ Nt_ATTENUATION, &SM_Attenuation, Nt_BIAS0, &SM_Bias0, Nt_BIAS1, &SM_Bias1, Nt_NUMSAMPLES, &SM_Numsamples, Nt_RESFACTOR, &SM_Resfactor, Nt_CMDEND); /* Add the light sources */ Ni_Light("light1", Nt_MODEL, Nt_POINT, Nt_CMDSEP, Nt_SHINEFROM, light1_shinefrom, Nt_CMDSEP, Nt_CMDEND); Ni_Light("light2", Nt_MODEL, Nt_POINT, Nt_CMDSEP, Nt_SHINEFROM, light2_shinefrom, Nt_CMDSEP, Nt_CMDEND); /* Light shining on the top middle part of wall */ Ni_Light("light3", Nt_MODEL, Nt_SPOT, Nt_CMDSEP, Nt_SHINEFROM, light3_shinefrom, Nt_CMDSEP, Nt_SHINEAT, light3_shineat, Nt_CMDSEP, Nt_CUTOFF, (Nd_Float *) &light3_cutoff_angle, Nt_CMDSEP, Nt_SHADOWMAP, "default", Nt_ENABLED, Nt_OFF, Nt_CMDSEP, Nt_CMDEND); Ni_Light("light4", Nt_MODEL, Nt_DIRECTION, Nt_CMDSEP, Nt_SHINEFROM, light4_shinefrom, Nt_CMDSEP, Nt_INTENSITY, (Nd_Float *) &light4_intensity, Nt_CMDSEP, Nt_CMDEND); /* Define the viewing camera */ Ni_Camera("default", Nt_ACTIVE, Nt_CMDSEP, /* Make it the active camera */ Nt_FOCALLENGTH, (Nd_Float *) &camera_focallength, Nt_CMDSEP, Nt_LOOKFROM, lookfrom, Nt_CMDSEP, Nt_LOOKAT, lookat, Nt_CMDSEP, Nt_PROJECTION, Nt_PERSPECTIVE, Nt_CMDSEP, Nt_WINDOW, (Nd_Float *) camera_window, Nt_CMDSEP, Nt_CMDEND); /* Define a camera viewpoint which will be used to create the */ /* shadowmap for point light source # 1. */ Ni_Camera("shadowmap light1 camera", Nt_FOCALLENGTH, (Nd_Float *) &sm_camera_distance, Nt_CMDSEP, Nt_WINDOW, (Nd_Float *) sm_camera_window, Nt_CMDSEP, Nt_LOOKFROM, sm_camera_lookfrom, Nt_CMDSEP, Nt_LOOKAT, sm_camera_lookat, Nt_CMDSEP, Nt_PROJECTION, Nt_PERSPECTIVE, Nt_CMDSEP, Nt_CMDEND); /* Now associate a shadow map camera with light # 1 which will be used */ /* to create the point light source's shadow map. */ Ni_Light("light1", Nt_SHADOWMAP, "default", Nt_ENABLED, Nt_ON, Nt_USEGLOBALVALUES, Nt_ENABLED, Nt_ON, Nt_USECAMERA, "shadowmap light1 camera", Nt_CMDEND); /* Enable the fog shader */ Ni_Atmosphere(Nt_FOG, Nt_ENABLED, Nt_ON, Nt_FOGTYPE, Nt_LINEAR, Nt_COLOR, Nt_COLORNAME, "red", Nt_NEARDISTANCE, (Nd_Float *) &fog_near_distance, Nt_FARDISTANCE, (Nd_Float *) &fog_far_distance, Nt_NEARBLEND, (Nd_Float *) &fog_near_blend, Nt_FARBLEND, (Nd_Float *) &fog_far_blend, Nt_BGFOGGED, Nt_ENABLED, Nt_ON, Nt_USEBGCOLOR, Nt_ENABLED, Nt_OFF, Nt_CMDEND); /* Select the TIFF file output driver. */ Ni_Output_Driver("driver#1", Nt_FILE, Nt_TIFF, Nt_CMDSEP, Nt_FILENAME, "example4.tif", Nt_CMDSEP, Nt_CMDEND); /* Now render the scene to the TIFF output file */ Ni_Render(Nt_CMDEND); Ni_Exit_Cleanup(); } /*>>>> User-Defined-Primitive Callback Generator <<<<------ */ /* The following callback function is called by the renderer whenever */ /* it wants to generate the user-defined primitive or request bounding-box */ /* information about the primitive. */ /* This callback is very simplistic: it only has to return 1 polygon to the renderer. */ #if USE_USERDEFINED_PRIMITIVE static Nd_Void UserDefined_Primitive_Callback(Nd_UserDefPrim_Callback_Info *cbi) { static short vertex_count, polygon_count; Nd_Vector *vertex_data_ptr, *texture_coords_ptr; /* Pick up the two user pointers which were passed to the */ /* Ni_Primitive() command. They point to the vertices and texture */ /* coordinates of this polygon. */ vertex_data_ptr=(Nd_Vector *) cbi->Nv_User_Data_Ptr1; texture_coords_ptr = (Nd_Vector *) cbi->Nv_User_Data_Ptr2; /* Determine what data the renderer wants us to return. */ switch(cbi->Nv_Action) { case Nc_UDP_ACTION_CB_INITIALIZE: /* This is called to initialize this callback function */ /* before it is called to inquire about the polygon data. */ polygon_count = 0; break; case Nc_UDP_ACTION_CB_SHUTDOWN: /* This is called to shutdown the callback function */ break; case Nc_UDP_ACTION_DELETE: /* This is called whenever the parent object definition */ /* holding this primitive is about to be deleted by the renderer. */ /* All locally allocated data should be freed up here. */ break; case Nc_UDP_ACTION_GET_BOUNDINGBOX: /* Return the primitive-space extents of the geometric data */ break; case Nc_UDP_ACTION_GET_NEXT_POLYGON: vertex_count = 0; /* There is only 1 polygon in each object for this tutorial example */ if (++polygon_count > 1) { /* We are done once all of the polygons have been processed */ cbi->Nv_Return_Status = Nc_UDP_STATUS_NO_DATA_AVAILABLE; return; } break; case Nc_UDP_ACTION_GET_NEXT_VERTEX: /* Return the next vertex attributes of the current polygon */ /* Return a pointer to the vertex position (mandatory) */ cbi->Nv_Vertex_Position = &vertex_data_ptr[vertex_count]; if (cbi->Nv_Request_Mask & Nc_UDP_REQUEST_TEXTURE) { cbi->Nv_Vertex_Texture = &texture_coords_ptr[vertex_count]; cbi->Nv_Returned_Data_Mask |= Nc_UDP_HAS_TEXTURE; } /* Determine the 'return status' */ ++vertex_count; if (vertex_count == 4) /* This is the last vertex of this polygon */ cbi->Nv_Return_Status = Nc_UDP_STATUS_LAST_VERTEX; else /* Else, this is just another vertex of this polygon */ cbi->Nv_Return_Status = Nc_UDP_STATUS_SUCCESS; break; } } #endif /* USE_USERDEFINED_PRIMITIVE */
The following is the final C program for tutorial # 5:
/***************************************************************************** Example NuGraf Rendering Library Script File # 4 This Demonstrates the INDEXEDPOLYGON and USERDEFINED Primitives, Shadow Mapping, and the Fog Atmospheric Shader. See Explanation in the NuGraf Reference Manual - Tutorial Chapter. This file can be compiled and run stand-alone. Copyright (c) 1988, 2003 Okino Computer Graphics, Inc. All Rights Reserved. *****************************************************************************/ #include "ni.h" /* This is the main NuGraf include file */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> /* Define ONE of the following to be Nc_TRUE. It selects the geometric primitive */ /* type to use which will send the polygonal data to the renderer. */ #define USE_POLYGON_PRIMITIVE Nc_FALSE #define USE_INDEXEDPOLYGON_PRIMITIVE Nc_FALSE #define USE_USERDEFINED_PRIMITIVE Nc_TRUE /* Resolution of the image */ #define IMAGE_X_RESOLUTION 512 #define IMAGE_Y_RESOLUTION 488 static Nd_Void UserDefined_Primitive_Callback(Nd_UserDefPrim_Callback_Info *cbi); /* --------------->>>> Polygon Geometry <<<<----------------- */ static Nd_Int num_floor_vertices=4; static Nd_Int num_wall_vertices=4; static Nd_Vector wall_vertices[]={ { 1.0, 1.0, 0.0 }, { 1.0, 1.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 } }; static Nd_Vector floor_vertices[]={ { 1.0, 0.0, 1.0 }, { 1.0, 0.0, 1.0 }, { 1.0, 0.0, 1.0 }, { 1.0, 0.0, 1.0 } }; static Nd_Vector texture_coordinates[]={ { 1.0, 0.0, 0.0 }, { 1.0, 1.0, 0.0 }, { 0.0, 1.0, 0.0 }, { 0.0, 0.0, 0.0 } }; /*>>>> IndexedPolygon Primitive Variables <<<<-------- */ #if USE_INDEXEDPOLYGON_PRIMITIVE /* Total number of polygons in the object */ static Nd_Int num_polygons=1; /* Array of length 'num_polygons' describing the # of vertices in */ /* each polygon (including holes and islands). */ static Nd_Int num_vertices_per_polygon[]={ 4 }; /* Vertex data variables */ static Nd_Int num_vertex_coords=4; static Nd_Int vertex_indices[]={ 1, 2, 3, 4 }; /* Texture coordinates variables */ static Nd_Int num_texture_coords=4; static Nd_Int texture_indices[]={ 1, 2, 3, 4 }; #endif /* USE_INDEXEDPOLYGON_PRIMITIVE */ Nd_Void main() { char *home_directory=NULL; char *current_working_directory=NULL; /* General variables */ Nd_Vector vec; Nd_Float rotation_angle; Nd_Int Oversampling_Values[2]={ 1, 4 }; /* The 32-bit user-defined values passed to the primitive callback */ Nd_Ptr Nv_User_Data_Ptr1; Nd_Ptr Nv_User_Data_Ptr2; /* Sphere primitive parameters */ Nd_Float sph_radius=1; Nd_Int sph_u_subdiv=14; /* parametric u & v subdivisions */ Nd_Int sph_v_subdiv=14; /* Texture mapping parameters */ Nd_Float floor_u_scale=1.0 / 512.0; Nd_Float floor_v_scale=1.0 / 128.0; Nd_Float wall_u_scale=1.0 / 6.0; Nd_Float wall_v_scale=1.0 / 6.0; /* Shading coefficients for the polygons */ Nd_Float ambient_coeff=0.4; Nd_Float diffuse_coeff=0.3; Nd_Float specular_coeff=0.7; /* Light source variables */ Nd_Vector light1_shinefrom={ 9.0, 16.0, 0.0 }; Nd_Vector light2_shinefrom={ 8.0, 15.0, 5.0 }; Nd_Vector light3_shinefrom={ 20.0, 20.0, 20.0 }; Nd_Vector light3_shineat={ 0.0, 10.0, 0.0 }; Nd_Float light3_cutoff_angle=22.5; Nd_Vector light4_shinefrom={ 0.0, 1.0, 0.0 }; Nd_Float light4_intensity=0.5; /* Fog variables */ Nd_Float fog_near_distance=10.0; Nd_Float fog_far_distance=50.0; Nd_Float fog_near_blend=0.0; Nd_Float fog_far_blend=1.0; /* Shadow map parameters for light 1 */ Nd_Float SM_Attenuation=0.8; Nd_Int SM_Numsamples=32; Nd_Float SM_Resfactor=2; Nd_Float SM_Bias0=0.1; Nd_Float SM_Bias1=0.2; Nd_Int SM_Resolution=512; /* Shadow map camera parameters */ Nd_Vector sm_camera_lookfrom={ 20.0, 24.0, 20.0 }; Nd_Vector sm_camera_lookat={ 0.0, 4.0, 0.0 }; Nd_Float sm_camera_distance=10.0; Nd_Float sm_camera_window[2]={ 4.0, 4.0 }; /* Camera variables */ Nd_Vector lookfrom={ 0.0, 5.0, 18.0 }; Nd_Vector lookat={ 0.0, 4.0, 0.0 }; Nd_Float camera_window[]={ 1.0, 1.0 }; Nd_Float camera_focallength=1.0; /* Image Resolution */ Nd_Int image_res[2]; /*>>>> Initialize the Library <<<<------------- */ /* Initialize the library and the directory locations */ Ni_Initialize(home_directory, current_working_directory); /*>>>> Define Textures <<<<----------------- */ /* 2D texture image for general texture mapping */ Ni_Texture("checker bitmap texture", Nt_IMAGE, Nt_TEXTUREIMAGE, Nt_TIFF, "check256.tif", Nt_CMDSEP, Nt_FILTER, Nt_MIPMAP, Nt_CMDSEP, Nt_CMDEND); /*>>>> Define Surfaces <<<<--------------- */ Ni_Surface("floor surface", Nt_SHADINGCOEFFS, Nt_AMBIENT, (Nd_Float *) &ambient_coeff, Nt_DIFFUSE, (Nd_Float *) &diffuse_coeff, Nt_SPECULAR, (Nd_Float *) &specular_coeff, Nt_CMDSEP, Nt_TEXTURE, "layer 1", Nt_TEXTURELINK, "checker bitmap texture", Nt_USCALE, (Nd_Float *) &floor_u_scale, Nt_VSCALE, (Nd_Float *) &floor_v_scale, Nt_CMDSEP, Nt_CMDEND); Ni_Surface("wall surface", Nt_SHADINGCOEFFS, Nt_AMBIENT, (Nd_Float *) &ambient_coeff, Nt_DIFFUSE, (Nd_Float *) &diffuse_coeff, Nt_SPECULAR, (Nd_Float *) &specular_coeff, Nt_CMDSEP, Nt_TEXTURE, "layer 1", Nt_TEXTURELINK, "checker bitmap texture", Nt_USCALE, (Nd_Float *) &wall_u_scale, Nt_VSCALE, (Nd_Float *) &wall_v_scale, Nt_CMDSEP, Nt_CMDEND); Ni_Surface("sphere 1 surface", Nt_COLOR, Nt_COLORNAME, "red", Nt_CMDEND); Ni_Surface("sphere 2 surface", Nt_COLOR, Nt_COLORNAME, "green", Nt_CMDEND); /*>>>> Define Sphere Object <<<<-------------- */ /* Create a single sphere object centered at the origin */ Ni_Object_Define("sphere object", Nt_CMDEND); Ni_Primitive(Nt_SPHERE, Nt_RADIUS, (Nd_Float *) &sph_radius, Nt_CMDSEP, Nt_CMDEND); Ni_Object_End(Nt_CMDEND); /*>>>> Define Polygonal Objects <<<<------------ */ #if USE_POLYGON_PRIMITIVE Ni_Object_Define("wall object", Nt_CMDEND); Ni_Primitive(Nt_POLYGON, Nt_NUMVERTICES, (Nd_Int *) &num_wall_vertices, Nt_CMDSEP, Nt_VERTEX, (Nd_Vector *) wall_vertices, Nt_CMDSEP, Nt_TEXTURE, (Nd_Vector *) texture_coordinates, Nt_CMDSEP, Nt_CMDEND); Ni_Object_End(Nt_CMDEND); Ni_Object_Define("floor object", Nt_CMDEND); Ni_Primitive(Nt_POLYGON, Nt_NUMVERTICES, (Nd_Int *) &num_floor_vertices, Nt_CMDSEP, Nt_VERTEX, (Nd_Vector *) floor_vertices, Nt_CMDSEP, Nt_TEXTURE, (Nd_Vector *) texture_coordinates, Nt_CMDSEP, Nt_CMDEND); Ni_Object_End(Nt_CMDEND); #elif USE_INDEXEDPOLYGON_PRIMITIVE Ni_Object_Define("wall object", Nt_CMDEND); Ni_Primitive(Nt_INDEXEDPOLYGONS, Nt_NUMPOLYGONS, (Nd_Int *) &num_polygons, Nt_CMDSEP, Nt_VERTICESPERPOLY, (Nd_Int *) num_vertices_per_polygon, Nt_CMDSEP, Nt_VERTEX, (Nd_Int *) &num_vertex_coords, (Nd_Vector *) wall_vertices, (Nd_Int *) vertex_indices, Nt_CMDSEP, Nt_TEXTURE, (Nd_Int *) &num_texture_coords, (Nd_Vector *) texture_coordinates, (Nd_Int *) texture_indices, Nt_CMDSEP, Nt_CMDEND); Ni_Object_End(Nt_CMDEND); Ni_Object_Define("floor object", Nt_CMDEND); Ni_Primitive(Nt_INDEXEDPOLYGONS, Nt_NUMPOLYGONS, (Nd_Int *) &num_polygons, Nt_CMDSEP, Nt_VERTICESPERPOLY, (Nd_Int *) num_vertices_per_polygon, Nt_CMDSEP, Nt_VERTEX, (Nd_Int *) &num_vertex_coords, (Nd_Vector *) floor_vertices, (Nd_Int *) vertex_indices, Nt_CMDSEP, Nt_TEXTURE, (Nd_Int *) &num_texture_coords, (Nd_Vector *) texture_coordinates, (Nd_Int *) texture_indices, Nt_CMDSEP, Nt_CMDEND); Ni_Object_End(Nt_CMDEND); #elif USE_USERDEFINED_PRIMITIVE /* Create a wall object which uses the user-defined callback function */ /* Pass the vertices and texture coordinates in the 32-bit user data pointers. */ Nv_User_Data_Ptr1=(void *) wall_vertices; Nv_User_Data_Ptr2=(void *) texture_coordinates; Ni_Object_Define("wall object", Nt_CMDEND); Ni_Primitive(Nt_USERDEFINED, (Nd_UserDefPrim_CB_Func) UserDefined_Primitive_Callback, (void **) &Nv_User_Data_Ptr1, (void **) &Nv_User_Data_Ptr2, Nt_CMDEND); Ni_Object_End(Nt_CMDEND); /* Create a floor object which uses the user-defined callback function */ /* Pass the vertices and texture coordinates in the 32-bit user data pointers. */ Nv_User_Data_Ptr1=(void *) floor_vertices; Nv_User_Data_Ptr2=(void *) texture_coordinates; Ni_Object_Define("floor object", Nt_CMDEND); Ni_Primitive(Nt_USERDEFINED, (Nd_UserDefPrim_CB_Func) UserDefined_Primitive_Callback, (void **) &Nv_User_Data_Ptr1, (void **) &Nv_User_Data_Ptr2, Nt_CMDEND); Ni_Object_End(Nt_CMDEND); #endif /*>>>> Link Surfaces to Objects <<<<----------- */ Ni_Surfacelink(Nt_SURFACE, "floor surface", Nt_OBJECT, "floor object", Nt_CMDEND); Ni_Surfacelink(Nt_SURFACE, "wall surface", Nt_OBJECT, "wall object", Nt_CMDEND); /*>>>> Make Instances <<<<------------------ */ Ni_Add_Instance(Nt_INSTANCE, "sphere instance 1", Nt_OBJECT, "sphere object", Nt_CMDEND); Ni_Attach(Nt_INSTANCE, "sphere instance 1", Nt_INSTANCE, "world", Nt_CMDEND); Ni_Add_Instance(Nt_INSTANCE, "sphere instance 2", Nt_OBJECT, "sphere object", Nt_CMDEND); Ni_Attach(Nt_INSTANCE, "sphere instance 2", Nt_INSTANCE, "world", Nt_CMDEND); Ni_Add_Instance(Nt_INSTANCE, "floor instance", Nt_OBJECT, "floor object", Nt_CMDEND); Ni_Attach(Nt_INSTANCE, "floor instance", Nt_INSTANCE, "world", Nt_CMDEND); Ni_Add_Instance(Nt_INSTANCE, "wall instance", Nt_OBJECT, "wall object", Nt_CMDEND); Ni_Attach(Nt_INSTANCE, "wall instance", Nt_INSTANCE, "world", Nt_CMDEND); /*>>>> Link Surfaces to Instances <<<<---------- */ Ni_Surfacelink(Nt_SURFACE, "sphere 1 surface", Nt_INSTANCE, "sphere instance 1", Nt_CMDEND); Ni_Surfacelink(Nt_SURFACE, "sphere 2 surface", Nt_INSTANCE, "sphere instance 2", Nt_CMDEND); /*>>>> Instance Attributes <<<<----------------- */ /* The floor does not cast shadows */ Ni_Instance("floor instance", Nt_CASTSSHADOWS, Nt_ENABLED, Nt_OFF, Nt_CMDSEP, Nt_SHADOWED, Nt_ENABLED, Nt_ON, Nt_CMDSEP, Nt_CMDEND); /*>>>> Apply the Transformations <<<<----------- */ /* Scale and rotate the wall instance */ vec[0]=6.0; vec[1]=10.0; vec[2]=1.0; Ni_Transform(Nt_INSTANCE, "wall instance", Nt_POSTMULTIPLY, Nt_SCALE, (Nd_Vector *) vec, Nt_CMDEND); rotation_angle=45.0; Ni_Transform(Nt_INSTANCE, "wall instance", Nt_POSTMULTIPLY, Nt_ROTATE, Nt_YAXIS, (Nd_Float *) &rotation_angle, Nt_CMDEND); /* Scale the floor instance */ vec[0]=1000.0; vec[1]=1.0; vec[2]=500.0; Ni_Transform(Nt_INSTANCE, "floor instance", Nt_POSTMULTIPLY, Nt_SCALE, (Nd_Vector *) vec, Nt_CMDEND); /* Translate sphere # 1 into position */ vec[0]=1.0; vec[1]=7.0; vec[2]=3.0; Ni_Transform(Nt_INSTANCE, "sphere instance 1", Nt_POSTMULTIPLY, Nt_TRANSLATE, (Nd_Vector *) vec, Nt_CMDEND); /* Translate sphere # 2 into position */ vec[0]=5.0; vec[1]=5.0; vec[2]=0.0; Ni_Transform(Nt_INSTANCE, "sphere instance 2", Nt_POSTMULTIPLY, Nt_TRANSLATE, (Nd_Vector *) vec, Nt_CMDEND); /*>>>> Render <<<<------------------ */ /* Set the resolution of the image */ image_res[Na_X_VALUE]=IMAGE_X_RESOLUTION; image_res[Na_Y_VALUE]=IMAGE_Y_RESOLUTION; Ni_Option( Nt_ANTIALIAS, Nt_ENABLED, Nt_OFF, Nt_OVERSAMPLE, (Nd_Int *) Oversampling_Values, Nt_CMDSEP, Nt_CULLING, Nt_BACK, Nt_CMDSEP, Nt_RESOLUTION, (Nd_Int *) image_res, Nt_CMDSEP, Nt_SHADING, Nt_SMOOTH, Nt_CMDSEP, Nt_SHADOWS, Nt_ENABLED, Nt_ON, Nt_CMDSEP, Nt_SUBDIVISIONS, Nt_SPHERE, Nt_USUBDIV, (Nd_Int *) &sph_u_subdiv, Nt_VSUBDIV, (Nd_Int *) &sph_v_subdiv, Nt_CMDSEP, Nt_CMDEND); /* Set the global shadowmap parameters */ Ni_Option(Nt_SHADOWMAP, /* The following parameters are used during shadowmap creation */ Nt_CULLINGOVERRIDE, Nt_BACK, Nt_SHADOWMAPSIZE, (Nd_Int *) &SM_Resolution, /* The following parameters are used during shadow rendering */ Nt_ATTENUATION, &SM_Attenuation, Nt_BIAS0, &SM_Bias0, Nt_BIAS1, &SM_Bias1, Nt_NUMSAMPLES, &SM_Numsamples, Nt_RESFACTOR, &SM_Resfactor, Nt_CMDEND); /* Add the light sources */ Ni_Light("light1", Nt_MODEL, Nt_POINT, Nt_CMDSEP, Nt_SHINEFROM, light1_shinefrom, Nt_CMDSEP, Nt_CMDEND); Ni_Light("light2", Nt_MODEL, Nt_POINT, Nt_CMDSEP, Nt_SHINEFROM, light2_shinefrom, Nt_CMDSEP, Nt_CMDEND); /* Light shining on the top middle part of wall */ Ni_Light("light3", Nt_MODEL, Nt_SPOT, Nt_CMDSEP, Nt_SHINEFROM, light3_shinefrom, Nt_CMDSEP, Nt_SHINEAT, light3_shineat, Nt_CMDSEP, Nt_CUTOFF, (Nd_Float *) &light3_cutoff_angle, Nt_CMDSEP, Nt_SHADOWMAP, "default", Nt_ENABLED, Nt_OFF, Nt_CMDSEP, Nt_CMDEND); Ni_Light("light4", Nt_MODEL, Nt_DIRECTION, Nt_CMDSEP, Nt_SHINEFROM, light4_shinefrom, Nt_CMDSEP, Nt_INTENSITY, (Nd_Float *) &light4_intensity, Nt_CMDSEP, Nt_CMDEND); /* Define the viewing camera */ Ni_Camera("default", Nt_ACTIVE, Nt_CMDSEP, /* Make it the active camera */ Nt_FOCALLENGTH, (Nd_Float *) &camera_focallength, Nt_CMDSEP, Nt_LOOKFROM, lookfrom, Nt_CMDSEP, Nt_LOOKAT, lookat, Nt_CMDSEP, Nt_PROJECTION, Nt_PERSPECTIVE, Nt_CMDSEP, Nt_WINDOW, (Nd_Float *) camera_window, Nt_CMDSEP, Nt_CMDEND); /* Define a camera viewpoint which will be used to create the */ /* shadowmap for point light source # 1. */ Ni_Camera("shadowmap light1 camera", Nt_FOCALLENGTH, (Nd_Float *) &sm_camera_distance, Nt_CMDSEP, Nt_WINDOW, (Nd_Float *) sm_camera_window, Nt_CMDSEP, Nt_LOOKFROM, sm_camera_lookfrom, Nt_CMDSEP, Nt_LOOKAT, sm_camera_lookat, Nt_CMDSEP, Nt_PROJECTION, Nt_PERSPECTIVE, Nt_CMDSEP, Nt_CMDEND); /* Now associate a shadow map camera with light # 1 which will be used */ /* to create the point light source's shadow map. */ Ni_Light("light1", Nt_SHADOWMAP, "default", Nt_ENABLED, Nt_ON, Nt_USEGLOBALVALUES, Nt_ENABLED, Nt_ON, Nt_USECAMERA, "shadowmap light1 camera", Nt_CMDEND); /* Enable the fog shader */ Ni_Atmosphere(Nt_FOG, Nt_ENABLED, Nt_ON, Nt_FOGTYPE, Nt_LINEAR, Nt_COLOR, Nt_COLORNAME, "red", Nt_NEARDISTANCE, (Nd_Float *) &fog_near_distance, Nt_FARDISTANCE, (Nd_Float *) &fog_far_distance, Nt_NEARBLEND, (Nd_Float *) &fog_near_blend, Nt_FARBLEND, (Nd_Float *) &fog_far_blend, Nt_BGFOGGED, Nt_ENABLED, Nt_ON, Nt_USEBGCOLOR, Nt_ENABLED, Nt_OFF, Nt_CMDEND); /* Select the TIFF file output driver. */ Ni_Output_Driver("driver#1", Nt_FILE, Nt_TIFF, Nt_CMDSEP, Nt_FILENAME, "example4.tif", Nt_CMDSEP, Nt_CMDEND); /* Now render the scene to the TIFF output file */ Ni_Render(Nt_CMDEND); Ni_Exit_Cleanup(); } /*>>>> User-Defined-Primitive Callback Generator <<<<------ */ /* The following callback function is called by the renderer whenever */ /* it wants to generate the user-defined primitive or request bounding-box */ /* information about the primitive. */ /* This callback is very simplistic: it only has to return 1 polygon to the renderer. */ #if USE_USERDEFINED_PRIMITIVE static Nd_Void UserDefined_Primitive_Callback(Nd_UserDefPrim_Callback_Info *cbi) { static short vertex_count, polygon_count; Nd_Vector *vertex_data_ptr, *texture_coords_ptr; /* Pick up the two user pointers which were passed to the */ /* Ni_Primitive() command. They point to the vertices and texture */ /* coordinates of this polygon. */ vertex_data_ptr=(Nd_Vector *) cbi->Nv_User_Data_Ptr1; texture_coords_ptr = (Nd_Vector *) cbi->Nv_User_Data_Ptr2; /* Determine what data the renderer wants us to return. */ switch(cbi->Nv_Action) { case Nc_UDP_ACTION_CB_INITIALIZE: /* This is called to initialize this callback function */ /* before it is called to inquire about the polygon data. */ polygon_count = 0; break; case Nc_UDP_ACTION_CB_SHUTDOWN: /* This is called to shutdown the callback function */ break; case Nc_UDP_ACTION_DELETE: /* This is called whenever the parent object definition */ /* holding this primitive is about to be deleted by the renderer. */ /* All locally allocated data should be freed up here. */ break; case Nc_UDP_ACTION_GET_BOUNDINGBOX: /* Return the primitive-space extents of the geometric data */ break; case Nc_UDP_ACTION_GET_NEXT_POLYGON: vertex_count = 0; /* There is only 1 polygon in each object for this tutorial example */ if (++polygon_count > 1) { /* We are done once all of the polygons have been processed */ cbi->Nv_Return_Status = Nc_UDP_STATUS_NO_DATA_AVAILABLE; return; } break; case Nc_UDP_ACTION_GET_NEXT_VERTEX: /* Return the next vertex attributes of the current polygon */ /* Return a pointer to the vertex position (mandatory) */ cbi->Nv_Vertex_Position = &vertex_data_ptr[vertex_count]; if (cbi->Nv_Request_Mask & Nc_UDP_REQUEST_TEXTURE) { cbi->Nv_Vertex_Texture = &texture_coords_ptr[vertex_count]; cbi->Nv_Returned_Data_Mask |= Nc_UDP_HAS_TEXTURE; } /* Determine the 'return status' */ ++vertex_count; if (vertex_count == 4) /* This is the last vertex of this polygon */ cbi->Nv_Return_Status = Nc_UDP_STATUS_LAST_VERTEX; else /* Else, this is just another vertex of this polygon */ cbi->Nv_Return_Status = Nc_UDP_STATUS_SUCCESS; break; } } #endif /* USE_USERDEFINED_PRIMITIVE */