The following is an example program which creates a scene containing
a textured sphere and wall using the NuGraf 'C' interface language. Please note that this
example is rather simple and in general most application programs which interface to the
NuGraf Toolkit will have interface code that is many times larger than this example.
/*****************************************************************************
An Example NuGraf Rendering Library Script File
This script renders a textured mapped sphere and wall.
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>
/* --------------------->>>> Function Prototypes <<<<--------------------- */
Nd_Void main ARGS(( Nd_Void ));
Nd_Void
Example_Error_Handler ARGS((Nd_Error_Handler_Info *Nv_Error_Info)),
Print_Error_Type ARGS((Nd_Error_Handler_Info *Nv_Error_Info, FILE *fp)),
Example_User_Interrupt_Handler ARGS((Nd_User_Interrupt_Info *, Nd_Int *Nv_Abort_Renderer));
/* -------------------------------------------------------------- */
Nd_Void
main() {
/* Object # 1 data data (a wall) */
Nd_Int num_vertices = 4;
Nd_Vector vertices[4] = {
{ 0.0, 0.0, 0.0 },
{ 1.0, 0.0, 0.0 },
{ 1.0, 1.0, 0.0 },
{ 0.0, 1.0, 0.0 }};
/* Vertex colors for the 4 corners of the wall */
Nd_Color colours[4] = {
{ 1.0, 1.0, 1.0 },
{ 1.0, 0.0, 0.0 },
{ 0.0, 1.0, 0.0 },
{ 0.0, 0.0, 1.0 }};
/* Sphere parameters */
Nd_Float sph_spin_angle = 360.0;
Nd_Float sph_radius = 0.25;
Nd_Int sph_u_subdiv = 12; /* Default is 6 */
Nd_Int sph_v_subdiv = 12; /* Default is 6 */
/* Light variables */
Nd_Color light1_color = { 1.0, 1.0, 1.0 };
Nd_Vector light1_shinefrom = { 0.0, 10.0, 10.0 };
/* Camera variables */
Nd_Vector lookat = { 0.5, 0.5, 0.0 };
Nd_Vector lookfrom = { 1.5, 1.0, 1.5 };
Nd_Float camera_distance = 10.0;
Nd_Float camera_window_width = 10.0;
Nd_Float camera_window_height = 10.0;
/* Surface variables */
Nd_Color surface_color = { 0.0, 0.0, 1.0 }; /* red, green, blue */
Nd_Color sphere_color = { 0.6, 0.6, 0.0 };
/* Background colour */
Nd_Color bg_color = { 0.0, 0.0, 0.0 };
/* Output driver variables */
Nd_Float Nv_Gamma_Value = 1.7;
/* Spherical environment mapping parameters */
Nd_Float sph_env_reflectcoeff = 1.0;
Nd_Float sph_env_rot_angle = 180.0;
Nd_Float sph_env_uoffset = 0.0;
Nd_Float sph_env_voffset = 0.0;
Nd_Float sph_env_uscale = 1.0;
Nd_Float sph_env_vscale = 1.0;
/* ---------------->>>> Setup Custom Handlers <<<<----------------- */
/* Initialize the rendering library and the directory locations */
Ni_Initialize(NULL, NULL);
/* Set the home (root) directory of the NuGraf file structure */
Ni_Set_Environment("NG_HOME", "c:/nugraf");
/* Default the output driver in case user does not choose one */
Ni_Output_Driver("driver1", Nt_FRAMEBUFFER, "vga", Nt_CMDSEP,
Nt_MODE, Nt_RGB, Nt_CMDSEP,
Nt_DISPLAYGAMMA, (Nd_Float *) &Nv_Gamma_Value, Nt_CMDSEP,
Nt_DITHER, Nt_ENABLED, Nt_ON, Nt_CMDSEP,
Nt_OPTIONSTRING, "mode=640x480x256", Nt_CMDEND);
/* Set the default error handler (send output to a file) */
Ni_Set_Error_Handler(Example_Error_Handler);
/* Set the default user interrupt handler */
Ni_Set_User_Interrupt_Handler(Example_User_Interrupt_Handler);
/* Remove the error log file */
remove(ERROR_LOG_FILE);
/* And initially send errors to the screen and the error log */
error_print_mode = ERRORS_TO_BOTH;
/* --------------------->>>> Add Textures <<<<---------------------- */
/* Load in the Coca Cola texture image and call it "texture1" */
Ni_Texture("texture1",
Nt_IMAGE,
Nt_TEXTUREIMAGE, Nt_DGPRLE, "cans/cokesmal.rle", Nt_CMDSEP,
Nt_FILTER, Nt_MIPMAP, Nt_CMDSEP,
Nt_CMDEND);
/* ------------------->>>> Define Surfaces <<<<--------------------- */
/* These statements define `surface definitions' which describe */
/* an object's surface attributes (texture, color, material, etc). */
Ni_Surface("surface1",
Nt_COLOR, surface_color, Nt_CMDSEP,
Nt_CMDEND);
Ni_Surface("surface2",
Nt_COLOR, sphere_color, Nt_CMDSEP,
/* Enable spherical environment mapping - use "texture1" */
Nt_SPHENVMAP,
Nt_ENABLED, Nt_ON,
Nt_TEXTURELINK, "texture1",
Nt_REFLECTCOEFF, (Nd_Float *) &sph_env_reflectcoeff,
Nt_ROTATE, Nt_YAXIS, (Nd_Float *) &sph_env_rot_angle,
Nt_UOFFSET, (Nd_Float *) &sph_env_uoffset,
Nt_VOFFSET, (Nd_Float *) &sph_env_voffset,
Nt_USCALE, (Nd_Float *) &sph_env_uscale,
Nt_VSCALE, (Nd_Float *) &sph_env_vscale,
Nt_CMDSEP,
Nt_CMDEND);
Ni_Surface("surface3",
/* Associate a 2D image texture definition with this surface */
Nt_TEXTURE, "texture_ref_id1",
Nt_TEXTURELINK, "texture1",
Nt_CMDSEP,
Nt_CMDEND);
/* -------------------->>>> Define Objects <<<<--------------------- */
/* These statements define the object geometry. Normally an application */
/* would use the INDEXPOLYGON primitive to send geometry to the library */
/* since it is most efficient, but we will use the inefficient POLYGON */
/* primitives here to simplify this file. */
/* Use the POLYGON primitive */
Ni_Object_Define("simple_obj");
Ni_Primitive(Nt_POLYGON,
(Nd_Int *) &num_vertices,
Nt_VERTEX, (Nd_Vector *) vertices,
Nt_TEXTURE_UV, (Nd_Vector *) texture_coords,
Nt_CMDEND);
Ni_Object_End();
/* Use the SPHERE primitive */
Ni_Object_Define("simple_obj2");
Ni_Primitive(Nt_SPHERE,
Nt_CLOSED, Nt_ENABLED, Nt_ON,
Nt_ANGLE, (Nd_Float *) &sph_spin_angle,
Nt_RADIUS, (Nd_Float *) &sph_radius,
/* These really shouldn't be specified unless */
/* necessary (use the global subdivision count instead). */
Nt_USUBDIV, (Nd_Int *) &sph_u_subdiv,
Nt_VSUBDIV, (Nd_Int *) &sph_v_subdiv,
Nt_CMDEND);
Ni_Object_End();
/* ----------------->>>> Link Surfaces to Objects <<<<-------------- */
/* These associate a surface definition with an object definition */
Ni_Surfacelink(Nt_SURFACE, "surface1", Nt_OBJECT, "simple_obj");
Ni_Surfacelink(Nt_SURFACE, "surface2", Nt_OBJECT, "simple_obj2");
/* ------------------->>>> Make Instances <<<<---------------------- */
/* These statements create instances of the geometry and */
/* hierarchically attach the instances together. */
Ni_Add_Instance(Nt_INSTANCE, "simple_inst", Nt_OBJECT, "simple_obj");
Ni_Attach(Nt_INSTANCE, "simple_inst", Nt_INSTANCE, "world");
Ni_Add_Instance(Nt_INSTANCE, "simple_inst2", Nt_OBJECT, "simple_obj2");
Ni_Attach(Nt_INSTANCE, "simple_inst2", Nt_INSTANCE, "world");
/* ----------------------->>>> Render <<<<-------------------------- */
/* Set up the runtime options */
Ni_Option(
Nt_SHADING, Nt_SMOOTH, Nt_CMDSEP,
Nt_RENDERLEVEL, Nt_ZSCANLINE, Nt_CMDSEP,
Nt_CMDEND);
/* Select the background colour scheme */
Ni_Background(Nt_COLORSCHEME, Nt_COLOR, Nt_RGB, bg_color, Nt_CMDEND);
/* Add one point light source to the scene */
Ni_Light("light1",
Nt_MODEL, Nt_POINT, Nt_CMDSEP,
Nt_COLOR, light1_color, Nt_CMDSEP,
Nt_SHINEFROM, light1_shinefrom, Nt_CMDSEP,
Nt_CMDEND);
/* And create a custom camera */
Ni_Camera("camera1",
Nt_ACTIVE, Nt_CMDSEP, /* Make it the active camera */
Nt_FOCALLENGTH, (Nd_Float *) &camera_distance, Nt_CMDSEP,
Nt_WINDOW,
Nt_WIDTH, (Nd_Float *) &camera_window_width,
Nt_HEIGHT, (Nd_Float *) &camera_window_height,
Nt_CMDSEP,
Nt_LOOKFROM, lookfrom, Nt_CMDSEP,
Nt_LOOKAT, lookat, Nt_CMDSEP,
Nt_CMDEND);
/* Then go render the scene */
Ni_Render(Nt_CMDEND);
Ni_Exit_Program();
}
/* ---------------->>> Custom Error Handling Routines <<<<----------------- */
/* This is a custom error handler which manages all errors sent from the library. */
/* The error condition is logged to a file and then output to the console. */
Nd_Void
Example_Error_Handler(Nd_Error_Handler_Info *Nv_Error_Info)
{
FILE *error_file_fp;
if (error_print_mode == ERRORS_TO_FILE || error_print_mode == ERRORS_TO_BOTH) {
/* Open error log for appending error messages. */
error_file_fp = fopen(ERROR_LOG_FILE, "a");
Print_Error_Type(Nv_Error_Info, error_file_fp);
if (Nv_Error_Info->Nv_Err_Level == Nc_ERR_FATAL)
fprintf(error_file_fp, "\nAborting program.\n");
fclose(error_file_fp);
}
if (error_print_mode == ERRORS_TO_CONSOLE || error_print_mode == ERRORS_TO_BOTH)
Print_Error_Type(Nv_Error_Info, stderr);
if (Nv_Error_Info->Nv_Err_Level == Nc_ERR_FATAL)
Ni_Abort_Program();
}
/* Print the error message header */
Nd_Void
Print_Error_Type(Nd_Error_Handler_Info *Nv_Error_Info, FILE *fp)
{
char *msg;
switch(Nv_Error_Info->Nv_Err_Level) {
case Nc_ERR_INFO:
msg = "[NuGraf INFO MESSAGE]: ";
break;
case Nc_ERR_DEBUG:
msg = "[NuGraf DEBUG INFO]:";
break;
case Nc_ERR_WARNING:
msg = "[NuGraf WARNING]:";
break;
case Nc_ERR_ERROR:
msg = "[NuGraf RECOVERABLE ERROR]:";
break;
case Nc_ERR_FATAL:
msg = "[NuGraf FATAL ERROR]:";
break;
default:
printf("Fatal error: Default case statement reached. Aborting program.\n");
exit(0);
}
fprintf(fp, "%s", msg);
fprintf(fp, "\n--> ");
fprintf(fp, Nv_Error_Info->Nv_Message);
}
/* ------------------>>> Custom User Abort Handler <<<<----------------- */
/* This is an example user interrupt handler. It will be called frequently */
/* during the rendering process to see if the renderer should be stopped. */
/* A fatal error message will be sent to the calling program once the */
/* renderer has been shut down properly (see library documentation for */
/* further details). */
Nd_Void
Example_User_Interrupt_Handler(Nd_User_Interrupt_Info *Nv_Info, Nd_Int *Nv_Abort_Renderer)
{
short keybd_status = 0;
*Nv_Abort_Renderer = Nc_FALSE;
if (Nv_Info->Nv_Mode == Nc_HANDLER_INITIALIZE) {
/* The renderer is asking us to initialize our internal variables */
} else if (Nv_Info->Nv_Mode == Nc_HANDLER_SHUTDOWN) {
/* The renderer is asking us to de-initialize our internal variables */
} else {
#ifdef MSDOS
keybd_status = _bios_keybrd(_KEYBRD_SHIFTSTATUS);
#endif
/* If the Left Shift, Right Shift, ALT, or Ctrl keys are */
/* being pressed then tell the renderer to abort. */
if (keybd_status & 0xf)
*Nv_Abort_Renderer = Nc_TRUE;
}
}