1039 lines
24 KiB
C
1039 lines
24 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include "ri.h"
|
|
#include "types.h"
|
|
#include "matrix.h"
|
|
#include "stack.h"
|
|
#include "graph_state.h"
|
|
#include "object.h"
|
|
#include "vars.h"
|
|
#include "engine.h"
|
|
#include "linklist.h"
|
|
#include "ribgen.h"
|
|
|
|
// Globals
|
|
engine_t engine = {0};
|
|
graph_state_t *pG;
|
|
scene_t *pW;
|
|
scene_t *pL;
|
|
|
|
RtToken RI_FRAMEBUFFER = "framebuffer";
|
|
RtToken RI_FILE = "file";
|
|
RtToken RI_RGB = "rgb";
|
|
RtToken RI_RGBA = "rgba";
|
|
RtToken RI_RGBZ = "rgbz";
|
|
RtToken RI_RGBAZ = "rgbaz";
|
|
RtToken RI_A = "a";
|
|
RtToken RI_Z = "z";
|
|
RtToken RI_AZ = "az";
|
|
RtToken RI_PERSPECTIVE = "perspective";
|
|
RtToken RI_ORTHOGRAPHIC = "orthographic";
|
|
RtToken RI_FOV = "fov";
|
|
RtToken RI_BILINEAR = "bilinear";
|
|
RtToken RI_BICUBIC = "bicubic";
|
|
RtToken RI_LINEAR = "linear";
|
|
RtToken RI_CUBIC = "cubic";
|
|
RtToken RI_PERIODIC = "periodic";
|
|
RtToken RI_NONPERIODIC = "nonperiodic";
|
|
|
|
RtBasis RiBezierBasis = { {-1, 3, -3, 1},
|
|
{3, -6, 3, 0},
|
|
{-3, 3, 0, 0},
|
|
{1, 0, 0, 0}};
|
|
|
|
RtBasis RiBSplineBasis = {{-(RtFloat)1/6, (RtFloat)3/6, -(RtFloat)3/6, (RtFloat)1/6}
|
|
,{(RtFloat)3/6, -(RtFloat)6/6, (RtFloat)3/6, 0},
|
|
{-(RtFloat)3/6, 0, (RtFloat)3/6, 0},
|
|
{(RtFloat)1/6, (RtFloat)4/6, (RtFloat)1/6, 0}};
|
|
|
|
RtBasis RiCatmullRomBasis = { {-(RtFloat)1/2, (RtFloat)3/2, -(RtFloat)3/2, (RtFloat)1/2},
|
|
{(RtFloat)2/2, -(RtFloat)5/2, (RtFloat)4/2, -(RtFloat)1/2},
|
|
{-(RtFloat)1/2, 0, (RtFloat)1/2, 0},
|
|
{0, (RtFloat)2/2, 0, 0}};
|
|
|
|
RtBasis RiHermiteBasis = { {2, 1, -2, 1},
|
|
{-3, -2, 3, -1},
|
|
{0, 1, 0, 0},
|
|
{1, 0, 0, 0}};
|
|
|
|
RtBasis RiPowerBasis = { {1, 0, 0, 0},
|
|
{0, 1, 0, 0},
|
|
{0, 0, 1, 0},
|
|
{0, 0, 0, 1}};
|
|
|
|
// --------------------------------------------------------------
|
|
// RenderMan interface
|
|
// --------------------------------------------------------------
|
|
/* Basic control flow, scoping, stacks */
|
|
RtVoid RiBegin (RtToken name)
|
|
{
|
|
if (Engine_context_get(&engine, ENGINE_CONTEXT_LEVEL_MAIN) != ENGINE_CONTEXT_INVALID)
|
|
{
|
|
fprintf(stderr, "RiBegin() cannot be nested!\n");
|
|
return;
|
|
}
|
|
|
|
Engine_init(&engine, name);
|
|
pG = &engine.gs;
|
|
pW = &engine.geometry;
|
|
pL = &engine.lights;
|
|
|
|
GS_init(pG);
|
|
|
|
// Init scene
|
|
pW->pObjs = NULL;
|
|
pL->pObjs = NULL;
|
|
|
|
// Set camera as current coordinate system
|
|
GS_xform_set(pG, camera_space);
|
|
|
|
Engine_context_set(&engine, ENGINE_CONTEXT_MAIN, ENGINE_CONTEXT_LEVEL_MAIN);
|
|
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtVoid RiEnd (void)
|
|
{
|
|
if (Engine_context_get(&engine, ENGINE_CONTEXT_LEVEL_MAIN) == ENGINE_CONTEXT_INVALID)
|
|
{
|
|
fprintf(stderr, "RiBegin() not declared previously!\n");
|
|
return;
|
|
}
|
|
|
|
Engine_DeleteScene(&engine);
|
|
GS_free(pG);
|
|
Engine_free(&engine);
|
|
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtVoid RiFrameBegin (RtInt number)
|
|
{
|
|
uint32_t i;
|
|
|
|
if (Engine_context_get(&engine, ENGINE_CONTEXT_LEVEL_MAIN) == ENGINE_CONTEXT_INVALID)
|
|
{
|
|
fprintf(stderr, "RiBegin() not declared previously!\n");
|
|
return;
|
|
}
|
|
|
|
if (Engine_context_get(&engine, ENGINE_CONTEXT_LEVEL_MAIN) == ENGINE_CONTEXT_FRAME)
|
|
{
|
|
fprintf(stderr, "RiFrameBegin() cannot be nested!\n");
|
|
return;
|
|
}
|
|
|
|
if (Engine_context_get(&engine, ENGINE_CONTEXT_LEVEL_MAIN) == ENGINE_CONTEXT_WORLD)
|
|
{
|
|
fprintf(stderr, "RiFrameBegin() is invalid within world block!\n");
|
|
return;
|
|
}
|
|
|
|
pG->frame = number;
|
|
|
|
// Initialize coordinate systems
|
|
for (i=0; i < NUM_COORD_SYSTEMS; i++)
|
|
{
|
|
IdentityMatrix(&pG->pXform->space[i]);
|
|
}
|
|
Engine_context_push(&engine);
|
|
Engine_context_set(&engine, ENGINE_CONTEXT_FRAME, ENGINE_CONTEXT_LEVEL_MAIN);
|
|
Ribgen_FrameBegin(&engine, number);
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtVoid RiFrameEnd (void)
|
|
{
|
|
if (Engine_context_get(&engine, ENGINE_CONTEXT_LEVEL_MAIN) < ENGINE_CONTEXT_FRAME)
|
|
{
|
|
fprintf(stderr, "RiFrameBegin() not declared previously!\n");
|
|
return;
|
|
}
|
|
|
|
Engine_DeleteScene(&engine);
|
|
Engine_context_pop(&engine);
|
|
Ribgen_FrameEnd(&engine);
|
|
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtVoid RiWorldBegin (void)
|
|
{
|
|
if (Engine_context_get(&engine, ENGINE_CONTEXT_LEVEL_MAIN) == ENGINE_CONTEXT_INVALID)
|
|
{
|
|
fprintf(stderr, "RiBegin() not declared previously!\n");
|
|
return;
|
|
}
|
|
|
|
if (Engine_context_get(&engine, ENGINE_CONTEXT_LEVEL_MAIN) == ENGINE_CONTEXT_WORLD)
|
|
{
|
|
fprintf(stderr, "RiWorldBegin() cannot be nested!\n");
|
|
return;
|
|
}
|
|
|
|
// Set world as current coordinate system
|
|
GS_xform_set(pG, world_space);
|
|
|
|
Engine_context_push(&engine);
|
|
Engine_context_set(&engine, ENGINE_CONTEXT_WORLD, ENGINE_CONTEXT_LEVEL_MAIN);
|
|
|
|
GS_opt_push(pG);
|
|
GS_attr_push(pG);
|
|
GS_xform_push(pG);
|
|
|
|
Ribgen_WorldBegin(&engine);
|
|
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtVoid RiWorldEnd (void)
|
|
{
|
|
if (Engine_context_get(&engine, ENGINE_CONTEXT_LEVEL_MAIN) < ENGINE_CONTEXT_WORLD)
|
|
{
|
|
fprintf(stderr, "RiWorldBegin() not declared previously!\n");
|
|
return;
|
|
}
|
|
|
|
// Set camera as current coordinate system
|
|
GS_xform_set(pG, camera_space);
|
|
|
|
Engine_Render(&engine);
|
|
Engine_SceneInfo(&engine);
|
|
Engine_DeleteScene(&engine);
|
|
Engine_context_pop(&engine);
|
|
GS_opt_pop(pG);
|
|
GS_attr_pop(pG);
|
|
GS_xform_pop(pG);
|
|
|
|
Ribgen_WorldEnd(&engine);
|
|
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtVoid RiAttributeBegin (void)
|
|
{
|
|
if (Engine_context_get(&engine, ENGINE_CONTEXT_LEVEL_MAIN) == ENGINE_CONTEXT_INVALID)
|
|
{
|
|
fprintf(stderr, "RiBegin() not declared previously!\n");
|
|
return;
|
|
}
|
|
|
|
GS_attr_push(pG);
|
|
GS_xform_push(pG);
|
|
Engine_context_push(&engine);
|
|
Engine_context_set(&engine, ENGINE_CONTEXT_ATTRIBUTE, ENGINE_CONTEXT_LEVEL_SUB);
|
|
|
|
Ribgen_AttributeBegin(&engine);
|
|
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtVoid RiAttributeEnd (void)
|
|
{
|
|
if (Engine_context_get(&engine, ENGINE_CONTEXT_LEVEL_MAIN) == ENGINE_CONTEXT_INVALID)
|
|
{
|
|
fprintf(stderr, "RiWorldBegin() not declared previously!\n");
|
|
return;
|
|
}
|
|
if (Engine_context_get(&engine, ENGINE_CONTEXT_LEVEL_SUB) != ENGINE_CONTEXT_ATTRIBUTE)
|
|
{
|
|
fprintf(stderr, "RiAttributeBegin() not declared previously!\n");
|
|
return;
|
|
}
|
|
|
|
GS_attr_pop(pG);
|
|
GS_xform_pop(pG);
|
|
Engine_context_pop(&engine);
|
|
|
|
Ribgen_AttributeEnd(&engine);
|
|
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtVoid RiTransformBegin (void)
|
|
{
|
|
if (Engine_context_get(&engine, ENGINE_CONTEXT_LEVEL_MAIN) == ENGINE_CONTEXT_INVALID)
|
|
{
|
|
fprintf(stderr, "RiBegin() not declared previously!\n");
|
|
return;
|
|
}
|
|
|
|
GS_xform_push(pG);
|
|
Engine_context_push(&engine);
|
|
Engine_context_set(&engine, ENGINE_CONTEXT_TRANSFORM, ENGINE_CONTEXT_LEVEL_SUB);
|
|
|
|
Ribgen_TransformBegin(&engine);
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtVoid RiTransformEnd (void)
|
|
{
|
|
if (Engine_context_get(&engine, ENGINE_CONTEXT_LEVEL_MAIN) == ENGINE_CONTEXT_INVALID)
|
|
{
|
|
fprintf(stderr, "RiWorldBegin() not declared previously!\n");
|
|
return;
|
|
}
|
|
if (Engine_context_get(&engine, ENGINE_CONTEXT_LEVEL_SUB) != ENGINE_CONTEXT_TRANSFORM)
|
|
{
|
|
fprintf(stderr, "RiTransformBegin() not declared previously!\n");
|
|
return;
|
|
}
|
|
|
|
GS_xform_pop(pG);
|
|
Engine_context_pop(&engine);
|
|
|
|
Ribgen_TransformEnd(&engine);
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtToken RiDeclare (char *name, char *declaration)
|
|
{
|
|
uint32_t i, len;
|
|
RtToken pVar;
|
|
|
|
char *pClass;
|
|
char *pType;
|
|
|
|
|
|
len = strlen(declaration);
|
|
pClass = jmalloc(len);
|
|
memset(pClass, 0, len);
|
|
pType = jmalloc(len);
|
|
memset(pType, 0, len);
|
|
|
|
i=0;
|
|
while(*declaration != ' ')
|
|
pClass[i++] = *declaration++;
|
|
|
|
declaration++;
|
|
i=0;
|
|
while(*declaration)
|
|
pType[i++] = *declaration++;
|
|
|
|
pVar = (RtToken)VarListDeclare(&engine.varList, name, pClass, pType);
|
|
|
|
jfree(pClass);
|
|
jfree(pType);
|
|
|
|
return pVar;
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
/* Transformations */
|
|
RtVoid RiConcatTransform (RtMatrix transform)
|
|
{
|
|
RtMatrix T;
|
|
|
|
GS_xform_push(pG);
|
|
|
|
memcpy(T, *pG->pXform_curr, sizeof(RtMatrix));
|
|
MultiplyMatrices(T, transform, pG->pXform_curr);
|
|
|
|
Ribgen_ConcatTransform(&engine, transform);
|
|
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtVoid RiCoordinateSystem (RtToken space)
|
|
{
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtVoid RiCoordSysTransform (RtToken space)
|
|
{
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtVoid RiIdentity (void)
|
|
{
|
|
GS_xform_push(pG);
|
|
|
|
IdentityMatrix(pG->pXform_curr);
|
|
|
|
Ribgen_Identity(&engine);
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtVoid RiPerspective (RtFloat fov)
|
|
{
|
|
pG->pOpt->projection.fov = fov;
|
|
|
|
Ribgen_Perspective(&engine, fov);
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtVoid RiRotate (RtFloat angle, RtFloat dx, RtFloat dy, RtFloat dz)
|
|
{
|
|
RtFloat v[3];
|
|
RtMatrix R, T;
|
|
RtFloat c, s, n, x, y, z;
|
|
RtFloat a;
|
|
|
|
GS_xform_push(pG);
|
|
|
|
v[0] = dx;
|
|
v[1] = dy;
|
|
v[2] = dz;
|
|
|
|
n = Norm(v, 3);
|
|
x = v[0]/n;
|
|
y = v[1]/n;
|
|
z = v[2]/n;
|
|
|
|
a = (RtFloat)(PI*angle/180.0);
|
|
c = (RtFloat)(1.0 - cos(a));
|
|
s = (RtFloat)-sin(a);
|
|
|
|
IdentityMatrix(&R);
|
|
|
|
R[0][0] = 1 + c*(x*x-1);
|
|
R[0][1] = z*s + c*x*y;
|
|
R[0][2] = -y*s + c*x*z;
|
|
|
|
R[1][0] = -z*s + c*x*y;
|
|
R[1][1] = 1 + c*(y*y-1);
|
|
R[1][2] = x*s + c*y*z;
|
|
|
|
R[2][0] = y*s + c*x*z;
|
|
R[2][1] = -x*s + c*y*z;
|
|
R[2][2] = 1 + c*(z*z-1);
|
|
|
|
memcpy(T, *pG->pXform_curr, sizeof(RtMatrix));
|
|
MultiplyMatrices(T, R, pG->pXform_curr);
|
|
|
|
Ribgen_Rotate(&engine, angle, dx, dy, dz);
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtVoid RiScale (RtFloat dx, RtFloat dy, RtFloat dz)
|
|
{
|
|
RtMatrix R, T;
|
|
|
|
GS_xform_push(pG);
|
|
|
|
IdentityMatrix(&R);
|
|
|
|
R[0][0] = dx;
|
|
R[1][1] = dy;
|
|
R[2][2] = dz;
|
|
|
|
memcpy(T, *pG->pXform_curr, sizeof(RtMatrix));
|
|
MultiplyMatrices(T, R, pG->pXform_curr);
|
|
|
|
Ribgen_Scale(&engine, dx, dy, dz);
|
|
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtVoid RiSkew (RtFloat angle, RtFloat dx1, RtFloat dy1, RtFloat dz1,
|
|
RtFloat dx2, RtFloat dy2, RtFloat dz2)
|
|
{
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtVoid RiTransform (RtMatrix transform)
|
|
{
|
|
uint32_t i, j;
|
|
|
|
GS_xform_push(pG);
|
|
|
|
for (i=0; i < 4; i++)
|
|
for (j=0; j < 4; j++)
|
|
*pG->pXform_curr[i][j] = transform[i][j];
|
|
|
|
Ribgen_Transform(&engine, transform);
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtVoid RiTranslate (RtFloat dx, RtFloat dy, RtFloat dz)
|
|
{
|
|
RtMatrix R, T;
|
|
|
|
GS_xform_push(pG);
|
|
|
|
IdentityMatrix(&R);
|
|
|
|
R[0][3] = dx;
|
|
R[1][3] = dy;
|
|
R[2][3] = dz;
|
|
|
|
memcpy(T, *pG->pXform_curr, sizeof(RtMatrix));
|
|
MultiplyMatrices(T, R, pG->pXform_curr);
|
|
|
|
Ribgen_Translate(&engine, dx, dy, dz);
|
|
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtPoint *RiTransformPoints (RtToken fromspace, RtToken tospace,
|
|
RtInt npoints, RtPoint *points)
|
|
{
|
|
return RI_NULL;
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
/* Options */
|
|
RtVoid RiCropWindow (RtFloat xmin, RtFloat xmax, RtFloat ymin, RtFloat ymax)
|
|
{
|
|
GS_opt_push(pG);
|
|
|
|
pG->pOpt->crop[0] = xmin;
|
|
pG->pOpt->crop[1] = xmax;
|
|
pG->pOpt->crop[2] = ymin;
|
|
pG->pOpt->crop[3] = ymax;
|
|
|
|
Ribgen_CropWindow(&engine, xmin, xmax, ymin, ymax);
|
|
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtVoid RiDisplay (char *name, RtToken type, RtToken mode, ...)
|
|
{
|
|
RtToken token;
|
|
RtPointer arg;
|
|
|
|
va_list args;
|
|
va_start(args, mode);
|
|
|
|
GS_opt_push(pG);
|
|
|
|
pG->pOpt->display.name = name;
|
|
pG->pOpt->display.type = type;
|
|
pG->pOpt->display.mode = mode;
|
|
|
|
while((token = va_arg(args, RtToken)) != RI_NULL)
|
|
{
|
|
arg = va_arg(args, RtPointer);
|
|
}
|
|
|
|
va_start(args, mode);
|
|
Ribgen_Display(&engine, name, type, mode, args);
|
|
va_end(args);
|
|
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtVoid RiFormat (RtInt xres, RtInt yres, RtFloat aspect)
|
|
{
|
|
GS_opt_push(pG);
|
|
|
|
pG->pOpt->format.xres = xres;
|
|
pG->pOpt->format.yres = yres;
|
|
if (aspect > 0)
|
|
pG->pOpt->format.ar_p = (RtFloat)aspect;
|
|
|
|
pG->pOpt->format.ar_f = pG->pOpt->format.ar_p*xres/yres;
|
|
|
|
Ribgen_Format(&engine, xres, yres, aspect);
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtVoid RiFrameAspectRatio (RtFloat aspect)
|
|
{
|
|
GS_opt_push(pG);
|
|
|
|
pG->pOpt->format.ar_f = aspect;
|
|
|
|
Ribgen_FrameAspectRatio(&engine, aspect);
|
|
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtVoid RiProjection (char *name, ...)
|
|
{
|
|
RtToken token;
|
|
RtPointer arg;
|
|
va_list args;
|
|
va_start(args, name);
|
|
|
|
GS_opt_push(pG);
|
|
|
|
pG->pOpt->projection.type = name;
|
|
|
|
while((token = va_arg(args, RtToken)) != RI_NULL)
|
|
{
|
|
if (token == RI_FOV)
|
|
{
|
|
arg = va_arg(args, RtPointer);
|
|
pG->pOpt->projection.fov = *((RtFloat*)arg);
|
|
}
|
|
}
|
|
va_start(args, name);
|
|
Ribgen_Projection(&engine, name, args);
|
|
va_end(args);
|
|
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtVoid RiScreenWindow (RtFloat left, RtFloat right, RtFloat bot, RtFloat top)
|
|
{
|
|
GS_opt_push(pG);
|
|
|
|
pG->pOpt->screen[0] = left;
|
|
pG->pOpt->screen[1] = right;
|
|
pG->pOpt->screen[2] = bot;
|
|
pG->pOpt->screen[3] = top;
|
|
|
|
Ribgen_ScreenWindow(&engine, left, right, bot, top);
|
|
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtVoid RiClipping (RtFloat hither, RtFloat yon)
|
|
{
|
|
pG->pOpt->clipping[0] = hither;
|
|
pG->pOpt->clipping[1] = yon;
|
|
|
|
Ribgen_Clipping(&engine, hither, yon);
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
/* Attributes */
|
|
RtVoid RiColor (RtColor Cs)
|
|
{
|
|
GS_attr_push(pG);
|
|
|
|
pG->pAttr->cs[0] = Cs[0];
|
|
pG->pAttr->cs[1] = Cs[1];
|
|
pG->pAttr->cs[2] = Cs[2];
|
|
|
|
Ribgen_Color(&engine, Cs);
|
|
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtVoid RiShadingRate (RtFloat size)
|
|
{
|
|
GS_attr_push(pG);
|
|
|
|
pG->pAttr->shadingrate = size;
|
|
|
|
Ribgen_ShadingRate(&engine, size);
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtVoid RiIlluminate (RtLightHandle light, RtBoolean onoff)
|
|
{
|
|
light_t *pLight;
|
|
|
|
pLight = (light_t*)light;
|
|
pLight->onoff = onoff;
|
|
|
|
Ribgen_Illuminate(&engine, pLight->id, onoff);
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtVoid RiSides (RtInt nsides)
|
|
{
|
|
pG->pAttr->nsides = nsides;
|
|
Ribgen_Sides(&engine, nsides);
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
/* Geometric Primitives (and a couple gprim-specific attributes) */
|
|
RtVoid RiPointsPolygons (RtInt npolys, RtInt *nverts, RtInt *verts, ...)
|
|
{
|
|
uint32_t j, v, n, k;
|
|
object_t *pObj;
|
|
RtToken token;
|
|
RtPoint *pPoint, *pVert;
|
|
ri_var_t *pVar;
|
|
|
|
va_list args;
|
|
va_start(args, verts);
|
|
|
|
if (Engine_context_get(&engine, ENGINE_CONTEXT_LEVEL_MAIN) < ENGINE_CONTEXT_WORLD)
|
|
{
|
|
fprintf(stderr, "RiPolygon(): Invalid context!\n");
|
|
return;
|
|
}
|
|
|
|
pObj = (object_t*)jmalloc(npolys*sizeof(object_t));
|
|
for (n=0; n < (uint32_t)npolys; n++)
|
|
{
|
|
Polygon_init(&pObj[n], ++pW->stat.num_polygons, nverts[n]);
|
|
}
|
|
|
|
while((token = va_arg(args, RtToken)) != RI_NULL)
|
|
{
|
|
if (token == RI_P)
|
|
{
|
|
pPoint = (RtPoint*)va_arg(args, RtPointer);
|
|
|
|
v = 0;
|
|
for (n=0; n < (uint32_t)npolys; n++)
|
|
{
|
|
pVar = VarListFindByName(&engine.varList, token);
|
|
if (!pVar)
|
|
{
|
|
fprintf(stderr, "RiPointsPolygons(): Variable \"%s\" not found!\n", token);
|
|
return;
|
|
}
|
|
pVar = VarListAdd(&pObj[n].vars, pVar);
|
|
pVert = (RtPoint*)VarSet(pVar, NULL, nverts[n]);
|
|
|
|
for (j=0; j < (uint32_t)nverts[n]; j++)
|
|
{
|
|
k = verts[v++];
|
|
pVert[j][0] = pPoint[k][0];
|
|
pVert[j][1] = pPoint[k][1];
|
|
pVert[j][2] = pPoint[k][2];
|
|
}
|
|
}
|
|
}
|
|
};
|
|
for (n=0; n < (uint32_t)npolys; n++)
|
|
{
|
|
Object_set_xform(&pObj[n], pG->pXform_curr);
|
|
Object_set_attr(&pObj[n], pG->pAttr);
|
|
Scene_Add(pW, &pObj[n]);
|
|
}
|
|
|
|
jfree(pObj);
|
|
va_start(args, verts);
|
|
Ribgen_PointsPolygons(&engine, npolys, nverts, verts, args);
|
|
va_end(args);
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtVoid RiPolygon (RtInt nvertices, ...)
|
|
{
|
|
object_t obj = {0};
|
|
RtToken token;
|
|
RtPointer arg;
|
|
ri_var_t *pVar;
|
|
|
|
va_list args;
|
|
va_start(args, nvertices);
|
|
|
|
if (Engine_context_get(&engine, ENGINE_CONTEXT_LEVEL_MAIN) < ENGINE_CONTEXT_WORLD)
|
|
{
|
|
fprintf(stderr, "RiPolygon(): Invalid context!\n");
|
|
return;
|
|
}
|
|
|
|
Polygon_init(&obj, ++pW->stat.num_polygons, nvertices);
|
|
while((token = va_arg(args, RtToken)) != RI_NULL)
|
|
{
|
|
arg = va_arg(args, RtPointer);
|
|
pVar = VarListFindByName(&engine.varList, token);
|
|
if (!pVar)
|
|
{
|
|
fprintf(stderr, "RiPolygon(): Variable \"%s\" not found!\n", token);
|
|
return;
|
|
}
|
|
pVar = VarListAdd(&obj.vars, pVar);
|
|
VarSet(pVar, arg, nvertices);
|
|
};
|
|
|
|
Object_set_xform(&obj, pG->pXform_curr);
|
|
Object_set_attr(&obj, pG->pAttr);
|
|
Scene_Add(pW, &obj);
|
|
va_start(args, nvertices);
|
|
Ribgen_Polygon(&engine, &obj, args);
|
|
va_end(args);
|
|
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtVoid RiBasis (RtBasis ubasis, RtInt ustep, RtBasis vbasis, RtInt vstep)
|
|
{
|
|
if (Engine_context_get(&engine, ENGINE_CONTEXT_LEVEL_MAIN) < ENGINE_CONTEXT_WORLD)
|
|
{
|
|
fprintf(stderr, "RiBasis(): Invalid context!\n");
|
|
return;
|
|
}
|
|
GS_attr_push(pG);
|
|
|
|
pG->pAttr->ubasis = (RtPointer)ubasis;
|
|
pG->pAttr->vbasis = (RtPointer)vbasis;
|
|
pG->pAttr->ustep = ustep;
|
|
pG->pAttr->vstep = vstep;
|
|
|
|
Ribgen_Basis(&engine, ubasis, ustep, vbasis, vstep);
|
|
|
|
}
|
|
|
|
RtVoid RiCurves (RtToken degree, RtInt ncurves, RtInt nverts[], RtToken wrap, ...)
|
|
{
|
|
uint32_t n;
|
|
object_t *pObj;
|
|
RtToken token;
|
|
RtPointer arg;
|
|
ri_var_t *pVar, *pKnownVar;
|
|
va_list args;
|
|
|
|
va_start(args, wrap);
|
|
|
|
if (Engine_context_get(&engine, ENGINE_CONTEXT_LEVEL_MAIN) < ENGINE_CONTEXT_WORLD)
|
|
{
|
|
fprintf(stderr, "RiCurves(): Invalid context!\n");
|
|
return;
|
|
}
|
|
|
|
pObj = (object_t*)jmalloc(ncurves*sizeof(object_t));
|
|
for (n=0; n < ncurves; n++)
|
|
{
|
|
Curve_init(&pObj[n], ++pW->stat.num_curves, degree, nverts[n], wrap);
|
|
}
|
|
|
|
while((token = va_arg(args, RtToken)) != RI_NULL)
|
|
{
|
|
arg = va_arg(args, RtPointer);
|
|
pKnownVar = VarListFindByName(&engine.varList, token);
|
|
if (!pKnownVar)
|
|
{
|
|
fprintf(stderr, "RiCurves(): Variable \"%s\" not found!\n", token);
|
|
return;
|
|
}
|
|
for (n=0; n < ncurves; n++)
|
|
{
|
|
pVar = VarListAdd(&pObj[n].vars, pKnownVar);
|
|
VarSet(pVar, arg, nverts[n]);
|
|
}
|
|
|
|
};
|
|
for (n=0; n < ncurves; n++)
|
|
{
|
|
Object_set_xform(&pObj[n], pG->pXform_curr);
|
|
Object_set_attr(&pObj[n], pG->pAttr);
|
|
Scene_Add(pW, &pObj[n]);
|
|
}
|
|
|
|
va_start(args, wrap);
|
|
Ribgen_Curves(&engine, pObj, degree, ncurves, nverts, wrap, args);
|
|
va_end(args);
|
|
|
|
jfree(pObj);
|
|
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtVoid RiPatch (RtToken type, ...)
|
|
{
|
|
RtInt npoints;
|
|
object_t obj;
|
|
RtToken token;
|
|
RtPointer arg;
|
|
ri_var_t *pVar;
|
|
va_list args;
|
|
|
|
va_start(args, type);
|
|
|
|
if (Engine_context_get(&engine, ENGINE_CONTEXT_LEVEL_MAIN) < ENGINE_CONTEXT_WORLD)
|
|
{
|
|
fprintf(stderr, "RiPatch(): Invalid context!\n");
|
|
return;
|
|
}
|
|
|
|
Patch_init(&obj, ++pW->stat.num_patches, type);
|
|
|
|
npoints = 4;
|
|
if (type == RI_BICUBIC)
|
|
npoints = 16;
|
|
|
|
while((token = va_arg(args, RtToken)) != RI_NULL)
|
|
{
|
|
arg = va_arg(args, RtPointer);
|
|
pVar = VarListFindByName(&engine.varList, token);
|
|
if (!pVar)
|
|
{
|
|
fprintf(stderr, "RiPatch(): Variable \"%s\" not found!\n", token);
|
|
return;
|
|
}
|
|
pVar = VarListAdd(&obj.vars, pVar);
|
|
VarSet(pVar, arg, npoints);
|
|
};
|
|
|
|
Object_set_xform(&obj, pG->pXform_curr);
|
|
Object_set_attr(&obj, pG->pAttr);
|
|
Scene_Add(pW, &obj);
|
|
|
|
va_start(args, type);
|
|
Ribgen_Patch(&engine, &obj, type, args);
|
|
va_end(args);
|
|
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtVoid RiPatchMesh (RtToken type, RtInt nu, RtToken uwrap, RtInt nv, RtToken vwrap, ...)
|
|
{
|
|
object_t obj;
|
|
RtToken token;
|
|
RtPointer arg;
|
|
ri_var_t *pVar;
|
|
va_list args;
|
|
|
|
va_start(args, vwrap);
|
|
|
|
if (Engine_context_get(&engine, ENGINE_CONTEXT_LEVEL_MAIN) < ENGINE_CONTEXT_WORLD)
|
|
{
|
|
fprintf(stderr, "RiPatchMesh(): Invalid context!\n");
|
|
return;
|
|
}
|
|
|
|
Patchmesh_init(&obj, ++pW->stat.num_patchmeshes, type, nu, uwrap, nv, vwrap, NULL);
|
|
while((token = va_arg(args, RtToken)) != RI_NULL)
|
|
{
|
|
arg = va_arg(args, RtPointer);
|
|
pVar = VarListFindByName(&engine.varList, token);
|
|
if (!pVar)
|
|
{
|
|
fprintf(stderr, "RiPatch(): Variable \"%s\" not found!\n", token);
|
|
return;
|
|
}
|
|
pVar = VarListAdd(&obj.vars, pVar);
|
|
VarSet(pVar, arg, nu*nv);
|
|
|
|
};
|
|
|
|
Object_set_xform(&obj, pG->pXform_curr);
|
|
Object_set_attr(&obj, pG->pAttr);
|
|
Scene_Add(pW, &obj);
|
|
|
|
va_start(args, vwrap);
|
|
Ribgen_Patchmesh(&engine, &obj, type, nu, uwrap, nv, vwrap, args);
|
|
va_end(args);
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
RtVoid RiSphere (RtFloat radius, RtFloat zmin, RtFloat zmax, RtFloat thetamax, ...)
|
|
{
|
|
object_t obj = {0};
|
|
RtToken token;
|
|
RtPointer arg;
|
|
ri_var_t *pVar;
|
|
|
|
va_list args;
|
|
va_start(args, thetamax);
|
|
|
|
if (Engine_context_get(&engine, ENGINE_CONTEXT_LEVEL_MAIN) < ENGINE_CONTEXT_WORLD)
|
|
{
|
|
fprintf(stderr, "RiSphere(): Invalid context!\n");
|
|
return;
|
|
}
|
|
|
|
Sphere_init(&obj, ++pW->stat.num_spheres, radius, zmin, zmax, thetamax);
|
|
|
|
while((token = va_arg(args, RtToken)) != RI_NULL)
|
|
{
|
|
arg = va_arg(args, RtPointer);
|
|
pVar = VarListFindByName(&engine.varList, token);
|
|
if (!pVar)
|
|
{
|
|
fprintf(stderr, "RiSphere(): Variable \"%s\" not found!\n", token);
|
|
return;
|
|
}
|
|
pVar = VarListAdd(&obj.vars, pVar);
|
|
VarSet(pVar, arg, 1);
|
|
};
|
|
|
|
Object_set_xform(&obj, pG->pXform_curr);
|
|
Object_set_attr(&obj, pG->pAttr);
|
|
Scene_Add(pW, &obj);
|
|
|
|
va_start(args, thetamax);
|
|
Ribgen_Sphere(&engine, &obj, radius, zmin, zmax, thetamax, args);
|
|
va_end(args);
|
|
|
|
}
|
|
|
|
/* Shaders */
|
|
RtLightHandle RiLightSource (char *name, ...)
|
|
{
|
|
light_t *pLight ;
|
|
object_t obj = {0};
|
|
RtToken token;
|
|
RtPointer arg;
|
|
ri_var_t *pVar;
|
|
|
|
va_list args;
|
|
va_start(args, name);
|
|
|
|
Light_init(&obj, ++pL->stat.num_lights);
|
|
|
|
while((token = va_arg(args, RtToken)) != RI_NULL)
|
|
{
|
|
arg = va_arg(args, RtPointer);
|
|
pVar = VarListFindByName(&engine.varList, token);
|
|
if (!pVar)
|
|
{
|
|
fprintf(stderr, "RiLightSource(): Variable \"%s\" not found!\n", token);
|
|
return NULL;
|
|
}
|
|
pVar = VarListAdd(&obj.vars, pVar);
|
|
VarSet(pVar, arg, 1);
|
|
}
|
|
Object_set_xform(&obj, pG->pXform_curr);
|
|
Object_set_attr(&obj, pG->pAttr);
|
|
|
|
Scene_Add(pL, &obj);
|
|
|
|
pLight = (light_t*)obj.pObjData;
|
|
|
|
va_start(args, name);
|
|
Ribgen_LightSource(&engine, &obj, name, pLight->id, args);
|
|
va_end(args);
|
|
|
|
return (RtLightHandle)pLight;
|
|
}
|
|
|
|
RtVoid RiSurface (char *name, ...)
|
|
{
|
|
RtToken token;
|
|
RtPointer arg;
|
|
ri_var_t *pVar;
|
|
|
|
va_list args;
|
|
va_start(args, name);
|
|
|
|
while((token = va_arg(args, RtToken)) != RI_NULL)
|
|
{
|
|
arg = va_arg(args, RtPointer);
|
|
pVar = VarListFindByName(&engine.varList, token);
|
|
if (!pVar)
|
|
{
|
|
fprintf(stderr, "RiSurface(): Variable \"%s\" not found!\n", token);
|
|
return;
|
|
}
|
|
// pVar = VarListAdd(&obj.vars, pVar);
|
|
// VarSet(pVar, arg, 1);
|
|
}
|
|
|
|
va_start(args, name);
|
|
Ribgen_Surface(&engine, name, args);
|
|
va_end(args);
|
|
|
|
}
|
|
|
|
RtVoid RiDisplacement (char *name, ...)
|
|
{
|
|
RtToken token;
|
|
RtPointer arg;
|
|
ri_var_t *pVar;
|
|
|
|
va_list args;
|
|
va_start(args, name);
|
|
|
|
while((token = va_arg(args, RtToken)) != RI_NULL)
|
|
{
|
|
arg = va_arg(args, RtPointer);
|
|
pVar = VarListFindByName(&engine.varList, token);
|
|
if (!pVar)
|
|
{
|
|
fprintf(stderr, "RiSurface(): Variable \"%s\" not found!\n", token);
|
|
return;
|
|
}
|
|
// pVar = VarListAdd(&obj.vars, pVar);
|
|
// VarSet(pVar, arg, 1);
|
|
}
|
|
|
|
va_start(args, name);
|
|
Ribgen_Displacement(&engine, name, args);
|
|
va_end(args);
|
|
|
|
}
|