414 lines
9.1 KiB
C
414 lines
9.1 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include <jman/ri.h>
|
|
#include <jman/types.h>
|
|
#include <jman/matrix.h>
|
|
#include <jman/linklist.h>
|
|
#include <jman/vars.h>
|
|
#include <jman/grid.h>
|
|
#include <jman/graph_state.h>
|
|
#include <jman/object.h>
|
|
|
|
void Grid_create(grid_t *pObj, uint32_t npu, uint32_t npv)
|
|
{
|
|
uint32_t i, j, k, nu, nv;
|
|
ri_var_t *pVar;
|
|
|
|
nu = npu + 1;
|
|
nv = npv + 1;
|
|
|
|
pObj->nu = nu;
|
|
pObj->nv = nv;
|
|
pObj->npoints = nu*nv;
|
|
|
|
VarListInit(&pObj->vars);
|
|
|
|
pObj->pPointPos = (pixelpos_t*)malloc(nu*nv*sizeof(pixelpos_t));
|
|
memset(pObj->pPointPos, 0, nu*nv*sizeof(pixelpos_t));
|
|
|
|
pObj->pPointState = (point_state_t*)malloc(nu*nv*sizeof(point_state_t));
|
|
memset(pObj->pPointState, 0, nu*nv*sizeof(point_state_t));
|
|
|
|
k=0;
|
|
for (i=0; i < nv; i++)
|
|
{
|
|
for (j=0; j < nu; j++)
|
|
{
|
|
pObj->pPointPos[k][0] = j;
|
|
pObj->pPointPos[k][1] = i;
|
|
k++;
|
|
}
|
|
}
|
|
for (i=0; i < (nv-1)*nu; i += nu)
|
|
{
|
|
for (j=0; j < nu-1; j++)
|
|
{
|
|
pObj->pPointState[i+j].has_face = 1;
|
|
}
|
|
}
|
|
for (i=0; i < pObj->npoints; i ++)
|
|
{
|
|
pObj->pPointState[i].visible = 1;
|
|
}
|
|
|
|
}
|
|
|
|
void Grid_free(grid_t *pObj)
|
|
{
|
|
if (pObj->pPointPos)
|
|
free(pObj->pPointPos);
|
|
|
|
if (pObj->pPointState)
|
|
free(pObj->pPointState);
|
|
|
|
// VarListDelByName(&pObj->vars, "P");
|
|
// VarListPrint(&pObj->vars);
|
|
VarListFree(&pObj->vars);
|
|
|
|
}
|
|
|
|
void Grid_CopyVarByName(grid_t *pObj, RtToken pDstName, RtToken pSrcName)
|
|
{
|
|
ri_var_t *pSrc, *pDst;
|
|
RtPointer pSrcData, pDstData;
|
|
|
|
pSrc = VarListFindByName(&pObj->vars, pSrcName);
|
|
pDst = VarListFindByName(&pObj->vars, pDstName);
|
|
|
|
if (pDst)
|
|
{
|
|
if (pSrc->etype != pDst->etype)
|
|
{
|
|
fprintf(stderr, "Grid_CopyVar(): Variables are not of same type!\n");
|
|
return;
|
|
}
|
|
|
|
if (pSrc->nvalues != pDst->nvalues)
|
|
{
|
|
fprintf(stderr, "Grid_CopyVar(): Variables are not of same size!\n");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pDst = VarListDeclare(&pObj->vars, pDstName, pSrc->cls, pSrc->type);
|
|
VarAlloc(pDst, pSrc->nvalues);
|
|
}
|
|
|
|
pSrcData = VarGet(pSrc);
|
|
pDstData = VarGet(pDst);
|
|
|
|
memcpy(pDstData, pSrcData, pSrc->value_size*pSrc->nvalues);
|
|
|
|
}
|
|
|
|
void Grid_InitUV(grid_t *pObj)
|
|
{
|
|
uint32_t i, j, k, nu, nv;
|
|
RtFloat *pU, *pV, u, v, du, dv;
|
|
ri_var_t *pVar;
|
|
|
|
nu = pObj->nu;
|
|
nv = pObj->nv;
|
|
du = (RtFloat)1/(nu-1);
|
|
dv = (RtFloat)1/(nv-1);
|
|
|
|
pVar = VarListDeclare(&pObj->vars, "u", "varying", "float");
|
|
pU = (RtFloat*)VarAlloc(pVar, nu*nv);
|
|
|
|
pVar = VarListDeclare(&pObj->vars, "v", "varying", "float");
|
|
pV = (RtFloat*)VarAlloc(pVar, nu*nv);
|
|
|
|
pVar = VarListDeclare(&pObj->vars, "du", "uniform", "float");
|
|
VarSet(pVar, (RtPointer)&du, 1);
|
|
|
|
pVar = VarListDeclare(&pObj->vars, "dv", "uniform", "float");
|
|
VarSet(pVar, (RtPointer)&dv, 1);
|
|
|
|
// Init uv-coords
|
|
k = 0;
|
|
v = 0;
|
|
for (i=0; i < nv; i++)
|
|
{
|
|
u = 0;
|
|
for (j=0; j < nu; j++)
|
|
{
|
|
pU[k] = u;
|
|
pV[k] = v;
|
|
u += du;
|
|
k++;
|
|
}
|
|
v += dv;
|
|
}
|
|
|
|
}
|
|
|
|
void Grid_assign_derivs(grid_t *pObj)
|
|
{
|
|
uint32_t i, j, k, nu, nv;
|
|
RtPoint *pPoint, *pDPDU, *pDPDV, dpd2;
|
|
RtFloat du, dv, ik;
|
|
ri_var_t *pVar;
|
|
|
|
nu = pObj->nu;
|
|
nv = pObj->nv;
|
|
|
|
pPoint = (RtPoint*)VarGetByName(&pObj->vars, "P");
|
|
du = *((RtFloat*)VarGetByName(&pObj->vars, "du"));
|
|
dv = *((RtFloat*)VarGetByName(&pObj->vars, "dv"));
|
|
|
|
pDPDU = (RtPoint*)VarGetByName(&pObj->vars, "dpdu");
|
|
if (!pDPDU)
|
|
pDPDU = (RtPoint*)VarAlloc(VarListDeclare(&pObj->vars, "dpdu", "varying", "point"), pObj->npoints);
|
|
|
|
pDPDV = (RtPoint*)VarGetByName(&pObj->vars, "dpdv");
|
|
if (!pDPDV)
|
|
pDPDV = (RtPoint*)VarAlloc(VarListDeclare(&pObj->vars, "dpdv", "varying", "point"), pObj->npoints);
|
|
|
|
for (i=0; i < pObj->npoints; i += nu)
|
|
{
|
|
for (j=0; j < nu-1; j++)
|
|
{
|
|
ik = (RtFloat)1/du;
|
|
for (k=0; k < 3; k++)
|
|
{
|
|
pDPDU[i+j][k] = ik*(pPoint[i+j+1][k] - pPoint[i+j][k]);
|
|
}
|
|
}
|
|
for (k=0; k < 3; k++)
|
|
{
|
|
pDPDU[i+j][k] = 2*pDPDU[i+j-1][k] - pDPDU[i+j-2][k];
|
|
}
|
|
|
|
}
|
|
for (i=0; i < nu; i++)
|
|
{
|
|
for (j=0; j < (nv-1)*nu; j += nu)
|
|
{
|
|
ik = (RtFloat)1/dv;
|
|
for (k=0; k < 3; k++)
|
|
{
|
|
pDPDV[i+j][k] = ik*(pPoint[i+j+nu][k] - pPoint[i+j][k]);
|
|
}
|
|
}
|
|
for (k=0; k < 3; k++)
|
|
{
|
|
pDPDV[i+j][k] = 2*pDPDV[i+j-nu][k] - pDPDV[i+j-2*nu][k];
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void Grid_calc_normal(grid_t *pObj, RtToken name)
|
|
{
|
|
uint32_t i;
|
|
RtFloat *a, *b;
|
|
RtPoint *pPoint, *pDPDU, *pDPDV, *pN;
|
|
|
|
pDPDU = (RtPoint*)VarGetByName(&pObj->vars, "dpdu");
|
|
pDPDV = (RtPoint*)VarGetByName(&pObj->vars, "dpdv");
|
|
pN = (RtPoint*)VarGetByName(&pObj->vars, name);
|
|
if (!pN)
|
|
pN = (RtPoint*)VarAlloc(VarListDeclare(&pObj->vars, name, "varying", "point"), pObj->npoints);
|
|
|
|
for (i=0; i < pObj->npoints; i++)
|
|
{
|
|
a = pDPDU[i];
|
|
b = pDPDV[i];
|
|
pN[i][0] = a[1]*b[2] - a[2]*b[1];
|
|
pN[i][1] = a[2]*b[0] - a[0]*b[2];
|
|
pN[i][2] = a[0]*b[1] - a[1]*b[0];
|
|
}
|
|
}
|
|
|
|
void Grid_displace(grid_t *pObj)
|
|
{
|
|
uint32_t i, j, k;
|
|
RtPoint *pP, *pDPDU, *pDPDV, *pN;
|
|
RtColor *pCs, *pCi;
|
|
RtFloat *pU, *pV, fd, kn, kd;
|
|
|
|
pP = (RtPoint*)VarGetByName(&pObj->vars, "P");
|
|
pU = (RtFloat*)VarGetByName(&pObj->vars, "u");
|
|
pV = (RtFloat*)VarGetByName(&pObj->vars, "v");
|
|
pDPDU = (RtPoint*)VarGetByName(&pObj->vars, "dpdu");
|
|
pDPDV = (RtPoint*)VarGetByName(&pObj->vars, "dpdv");
|
|
pN = (RtPoint*)VarGetByName(&pObj->vars, "Ng");
|
|
|
|
kd = 0.00;
|
|
for (i=0; i < pObj->npoints; i++)
|
|
{
|
|
|
|
if (!pObj->pPointState[i].visible)
|
|
continue;
|
|
|
|
kn = (RtFloat)1/Norm((RtFloat*)pN[i], 3);
|
|
|
|
fd = cos(10*3.141592654*pV[i]);
|
|
pP[i][0] += kd*fd*pN[i][0]*kn;
|
|
pP[i][1] += kd*fd*pN[i][1]*kn;
|
|
pP[i][2] += kd*fd*pN[i][2]*kn;
|
|
}
|
|
Grid_assign_derivs(pObj);
|
|
Grid_calc_normal(pObj, "Ng");
|
|
|
|
}
|
|
|
|
void Normalize(RtPoint N, RtPoint Nn)
|
|
{
|
|
RtFloat k;
|
|
|
|
k = (RtFloat)1/Norm((RtFloat*)N, 3);
|
|
|
|
Nn[0] = N[0]*k;
|
|
Nn[1] = N[1]*k;
|
|
Nn[2] = N[2]*k;
|
|
|
|
}
|
|
|
|
void Negate(RtPoint N, RtPoint Ni)
|
|
{
|
|
|
|
Ni[0] = -N[0];
|
|
Ni[1] = -N[1];
|
|
Ni[2] = -N[2];
|
|
|
|
}
|
|
|
|
RtFloat* Diffuse(linkedlist_t *pLightList, RtPoint N, RtPoint P)
|
|
{
|
|
static RtFloat result[3];
|
|
RtPoint L, Ln, Nn;
|
|
linkedlist_t *pLights;
|
|
object_t *pLight;
|
|
RtFloat k, kn;
|
|
|
|
pLights = LinkedList_find_first(pLightList);
|
|
|
|
memset(result, 0, sizeof(RtColor));
|
|
Normalize(N, Nn);
|
|
|
|
while(pLights)
|
|
{
|
|
pLight = (object_t*)LinkedList_get(pLights);
|
|
L[0] = (*pLight->pXform)[0][3] - P[0];
|
|
L[1] = (*pLight->pXform)[1][3] - P[1];
|
|
L[2] = (*pLight->pXform)[2][3] - P[2];
|
|
Normalize(L, Ln);
|
|
k = MAX(ScalarProduct(Ln, Nn, 3), 0);
|
|
|
|
result[0] += pLight->pAttr->cs[0] * k;
|
|
result[1] += pLight->pAttr->cs[1] * k;
|
|
result[2] += pLight->pAttr->cs[2] * k;
|
|
|
|
pLights = pLights->pNext;
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
RtFloat* Specular(linkedlist_t *pLightList, RtPoint N, RtPoint P, RtPoint I, RtFloat roughness)
|
|
{
|
|
static RtFloat result[3];
|
|
RtPoint L, H, Hn, Ln, Nn, In, Ini;
|
|
linkedlist_t *pLights;
|
|
object_t *pLight;
|
|
RtFloat k, kn;
|
|
|
|
pLights = LinkedList_find_first(pLightList);
|
|
|
|
memset(result, 0, sizeof(RtColor));
|
|
Normalize(N, Nn);
|
|
Normalize(I, In);
|
|
Negate(In, Ini);
|
|
|
|
while(pLights)
|
|
{
|
|
pLight = (object_t*)LinkedList_get(pLights);
|
|
L[0] = (*pLight->pXform)[0][3] - P[0];
|
|
L[1] = (*pLight->pXform)[1][3] - P[1];
|
|
L[2] = (*pLight->pXform)[2][3] - P[2];
|
|
Normalize(L, Ln);
|
|
H[0] = Ini[0] + Ln[0];
|
|
H[1] = Ini[1] + Ln[1];
|
|
H[2] = Ini[2] + Ln[2];
|
|
Normalize(H, Hn);
|
|
|
|
k = pow(MAX(ScalarProduct(Nn, Hn, 3), 0), (RtFloat)1/roughness);
|
|
|
|
result[0] += pLight->pAttr->cs[0] * k;
|
|
result[1] += pLight->pAttr->cs[1] * k;
|
|
result[2] += pLight->pAttr->cs[2] * k;
|
|
|
|
pLights = pLights->pNext;
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
void Grid_shade(grid_t *pObj, RtMatrix *pXform, linkedlist_t *pLights)
|
|
{
|
|
uint32_t i, j, k;
|
|
RtPoint *pP, *pDPDU, *pDPDV, *pN, *pI;
|
|
RtColor *pCs, *pCi;
|
|
RtFloat *pU, *pV, fd, kn, vt, p[4], d[4], *pCl_diff, *pCl_spec;
|
|
RtFloat kd, ks;
|
|
|
|
pP = (RtPoint*)VarGetByName(&pObj->vars, "P");
|
|
pU = (RtFloat*)VarGetByName(&pObj->vars, "u");
|
|
pV = (RtFloat*)VarGetByName(&pObj->vars, "v");
|
|
pCs = (RtColor*)VarGetByName(&pObj->vars, "Cs");
|
|
pDPDU = (RtPoint*)VarGetByName(&pObj->vars, "dpdu");
|
|
pDPDV = (RtPoint*)VarGetByName(&pObj->vars, "dpdv");
|
|
pN = (RtPoint*)VarGetByName(&pObj->vars, "Ng");
|
|
pI = (RtPoint*)VarGetByName(&pObj->vars, "I");
|
|
|
|
pCi = (RtColor*)VarAlloc(VarListDeclare(&pObj->vars, "Ci", "varying", "color"), pObj->npoints);
|
|
p[3] = (RtFloat)1.0;
|
|
|
|
kd = 1;
|
|
ks = 0.4;
|
|
|
|
for (i=0; i < pObj->npoints; i++)
|
|
{
|
|
|
|
if (!pObj->pPointState[i].visible)
|
|
continue;
|
|
|
|
pCl_diff = Diffuse(pLights, pN[i], pP[i]);
|
|
pCl_spec = Specular(pLights, pN[i], pP[i], pI[i], 0.01);
|
|
|
|
fd = (RtFloat)rand()/RAND_MAX;
|
|
pCi[i][0] = (*pCs)[0]*(kd*pCl_diff[0]) + ks*pCl_spec[0];
|
|
pCi[i][1] = (*pCs)[1]*(kd*pCl_diff[1]) + ks*pCl_spec[1];
|
|
pCi[i][2] = (*pCs)[2]*(kd*pCl_diff[2]) + ks*pCl_spec[2];
|
|
}
|
|
|
|
}
|
|
|
|
void Grid_shadeConstant(grid_t *pObj)
|
|
{
|
|
uint32_t i;
|
|
RtColor *pCs, *pCi;
|
|
|
|
pCs = (RtColor*)VarGetByName(&pObj->vars, "Cs");
|
|
pCi = (RtColor*)VarAlloc(VarListDeclare(&pObj->vars, "Ci", "varying", "color"), pObj->npoints);
|
|
|
|
for (i=0; i < pObj->npoints; i++)
|
|
{
|
|
|
|
if (!pObj->pPointState[i].visible)
|
|
continue;
|
|
|
|
|
|
pCi[i][0] = (*pCs)[0];
|
|
pCi[i][1] = (*pCs)[1];
|
|
pCi[i][2] = (*pCs)[2];
|
|
}
|
|
|
|
}
|