#include #include #include #include #include "ri.h" #include "types.h" #include "matrix.h" #include "linklist.h" #include "vars.h" #include "grid.h" #include "graph_state.h" #include "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]; } }