int _echoRayIntx_TriMesh(RAYINTX_ARGS(TriMesh)) { echoPos_t *pos, vert0[3], edge0[3], edge1[3], pvec[3], qvec[3], tvec[3], det, t, tmax, u, v, tmp; echoTriMesh *trim; int i, ret; AIR_UNUSED(parm); trim = TRIMESH(obj); if (!_echoRayIntx_CubeSolid(&t, &tmax, trim->min[0], trim->max[0], trim->min[1], trim->max[1], trim->min[2], trim->max[2], ray)) { if (tstate->verbose) { fprintf(stderr, "%s%s: trimesh bbox (%g,%g,%g) --> (%g,%g,%g) not hit\n", _echoDot(tstate->depth), "_echoRayIntx_TriMesh", trim->min[0], trim->min[1], trim->min[2], trim->max[0], trim->max[1], trim->max[2]); } return AIR_FALSE; } /* stupid linear search for now */ ret = AIR_FALSE; for (i=0; i<trim->numF; i++) { pos = trim->pos + 3*trim->vert[0 + 3*i]; ELL_3V_COPY(vert0, pos); pos = trim->pos + 3*trim->vert[1 + 3*i]; ELL_3V_SUB(edge0, pos, vert0); pos = trim->pos + 3*trim->vert[2 + 3*i]; ELL_3V_SUB(edge1, pos, vert0); TRI_INTX(ray, vert0, edge0, edge1, pvec, qvec, tvec, det, t, u, v, (v < 0.0 || u + v > 1.0), continue); if (ray->shadow) { return AIR_TRUE; } intx->t = ray->faar = t; ELL_3V_CROSS(intx->norm, edge0, edge1); ELL_3V_NORM(intx->norm, intx->norm, tmp); intx->obj = (echoObject *)obj; intx->face = i; ret = AIR_TRUE; } /* does NOT set u, v */ return ret; }
echoObject * echoRoughSphereNew(echoScene *scene, int theRes, int phiRes, echoPos_t *matx) { echoObject *trim; echoPos_t *_pos, *pos, tmp[3]; int *_vert, *vert, thidx, phidx, n; echoPos_t th, ph; trim = echoObjectNew(scene, echoTypeTriMesh); TRIMESH(trim)->numV = 2 + (phiRes-1)*theRes; TRIMESH(trim)->numF = (2 + 2*(phiRes-2))*theRes; _pos = pos = (echoPos_t *)calloc(3*TRIMESH(trim)->numV, sizeof(echoPos_t)); _vert = vert = (int *)calloc(3*TRIMESH(trim)->numF, sizeof(int)); ELL_3V_SET(tmp, 0, 0, 1); _echoPosSet(pos, matx, tmp); pos += 3; for (phidx=1; phidx<phiRes; phidx++) { ph = AIR_AFFINE(0, phidx, phiRes, 0.0, AIR_PI); for (thidx=0; thidx<theRes; thidx++) { th = AIR_AFFINE(0, thidx, theRes, 0.0, 2*AIR_PI); ELL_3V_SET(tmp, cos(th)*sin(ph), sin(th)*sin(ph), cos(ph)); _echoPosSet(pos, matx, tmp); pos += 3; } } ELL_3V_SET(tmp, 0, 0, -1); _echoPosSet(pos, matx, tmp); for (thidx=0; thidx<theRes; thidx++) { n = AIR_MOD(thidx+1, theRes); ELL_3V_SET(vert, 0, 1+thidx, 1+n); vert += 3; } for (phidx=0; phidx<phiRes-2; phidx++) { for (thidx=0; thidx<theRes; thidx++) { n = AIR_MOD(thidx+1, theRes); ELL_3V_SET(vert, 1+phidx*theRes+thidx, 1+(1+phidx)*theRes+thidx, 1+phidx*theRes+n); vert += 3; ELL_3V_SET(vert, 1+(1+phidx)*theRes+thidx, 1+(1+phidx)*theRes+n, 1+phidx*theRes+n); vert += 3; } } for (thidx=0; thidx<theRes; thidx++) { n = AIR_MOD(thidx+1, theRes); ELL_3V_SET(vert, 1+(phiRes-2)*theRes+thidx, TRIMESH(trim)->numV-1, 1+(phiRes-2)*theRes+n); vert += 3; } echoTriMeshSet(trim, TRIMESH(trim)->numV, _pos, TRIMESH(trim)->numF, _vert); return(trim); }
void _echoRayIntxUV_TriMesh(echoIntx *intx) { echoPos_t u, v, norm[3], len; echoTriMesh *trim; trim = TRIMESH(intx->obj); ELL_3V_SUB(norm, intx->pos, trim->meanvert); ELL_3V_NORM(norm, norm, len); if (norm[0] || norm[1]) { u = atan2(norm[1], norm[0]); intx->u = AIR_AFFINE(-AIR_PI, u, AIR_PI, 0.0, 1.0); v = -asin(norm[2]); intx->v = AIR_AFFINE(-AIR_PI/2, v, AIR_PI/2, 0.0, 1.0); } else { intx->u = 0; intx->v = AIR_AFFINE(1.0, norm[2], -1.0, 0.0, 1.0); } }
/* ******** echoTriMeshSet() ** ** This has to be called any time that the locations of the points are ** changing, even if the connectivity is not changed, because of how ** the bounding box and mean vert position is calculated here. ** ** NB: the TriMesh will directly use the given pos[] and vert[] arrays, ** so don't go freeing them after they've been passed here. */ void echoTriMeshSet(echoObject *trim, int numV, echoPos_t *pos, int numF, int *vert) { int i; if (trim && echoTypeTriMesh == trim->type) { TRIMESH(trim)->numV = numV; TRIMESH(trim)->numF = numF; TRIMESH(trim)->pos = pos; TRIMESH(trim)->vert = vert; ELL_3V_SET(TRIMESH(trim)->min, ECHO_POS_MAX, ECHO_POS_MAX, ECHO_POS_MAX); ELL_3V_SET(TRIMESH(trim)->max, ECHO_POS_MIN, ECHO_POS_MIN, ECHO_POS_MIN); ELL_3V_SET(TRIMESH(trim)->meanvert, 0.0, 0.0, 0.0); for (i=0; i<numV; i++) { ELL_3V_MIN(TRIMESH(trim)->min, TRIMESH(trim)->min, pos + 3*i); ELL_3V_MAX(TRIMESH(trim)->max, TRIMESH(trim)->max, pos + 3*i); ELL_3V_INCR(TRIMESH(trim)->meanvert, pos + 3*i); } ELL_3V_SCALE(TRIMESH(trim)->meanvert, 1.0/numV, TRIMESH(trim)->meanvert); } return; }