int o_face( /* determine if face intersects cube */ OBJREC *o, CUBE *cu ) { FVECT cumin, cumax; FVECT v1, v2; double d1, d2; int vloc; register FACE *f; register int i, j; /* get face arguments */ f = getface(o); if (f->area == 0.0) /* empty face */ return(O_MISS); /* compute cube boundaries */ for (j = 0; j < 3; j++) cumax[j] = (cumin[j] = cu->cuorg[j]-FTINY) + cu->cusize + 2.0*FTINY; vloc = ABOVE | BELOW; /* check vertices */ for (i = 0; i < f->nv; i++) if ( (j = plocate(VERTEX(f,i), cumin, cumax)) ) vloc &= j; else return(O_HIT); /* vertex inside */ if (vloc) /* all to one side */ return(O_MISS); for (i = 0; i < f->nv; i++) { /* check edges */ if ((j = i + 1) >= f->nv) j = 0; /* wrap around */ VCOPY(v1, VERTEX(f,i)); /* clip modifies */ VCOPY(v2, VERTEX(f,j)); /* the vertices! */ if (clip(v1, v2, cumin, cumax)) return(O_HIT); /* edge inside */ } /* see if cube cuts plane */ for (j = 0; j < 3; j++) if (f->norm[j] > 0.0) { v1[j] = cumin[j]; v2[j] = cumax[j]; } else { v1[j] = cumax[j]; v2[j] = cumin[j]; } if ((d1 = DOT(v1, f->norm) - f->offset) > FTINY) return(O_MISS); if ((d2 = DOT(v2, f->norm) - f->offset) < -FTINY) return(O_MISS); /* intersect face */ for (j = 0; j < 3; j++) v1[j] = (v1[j]*d2 - v2[j]*d1)/(d2 - d1); if (inface(v1, f)) return(O_HIT); return(O_MISS); /* no intersection */ }
void equipcache::loadcharlook(maplelook* plook) { if (!(plook->isloaded())) { lookinfo* info = plook->getinfo(); for (map<char, int>::iterator equip = info->equips.begin(); equip != info->equips.end(); equip++) { int equipid = equip->second; if (equipid != 0) { plook->addcloth(getcloth(equipid)); } } for (equiplayer l = EQL_CAP; l <= EQL_MEDAL; l = static_cast<equiplayer>(l + 1)) { if (!plook->getcloth(l)) { plook->addcloth(&emptycloth, l); } } plook->setbody(getbody(info->skin)); plook->setface(getface(info->faceid)); plook->sethair(gethair(info->hairid)); plook->init(&bodyinfo); } }
extern int o_face( /* compute intersection with polygonal face */ OBJREC *o, register RAY *r ) { double rdot; /* direction . normal */ double t; /* distance to intersection */ FVECT pisect; /* intersection point */ register FACE *f; /* face record */ f = getface(o); /* * First, we find the distance to the plane containing the * face. If this distance is less than zero or greater * than a previous intersection, we return. Otherwise, * we determine whether in fact the ray intersects the * face. The ray intersects the face if the * point of intersection with the plane of the face * is inside the face. */ /* compute dist. to plane */ rdot = -DOT(r->rdir, f->norm); if (rdot <= FTINY && rdot >= -FTINY) /* ray parallels plane */ t = FHUGE; else t = (DOT(r->rorg, f->norm) - f->offset) / rdot; if (t <= FTINY || t >= r->rot) /* not good enough */ return(0); /* compute intersection */ VSUM(pisect, r->rorg, r->rdir, t); if (!inface(pisect, f)) /* ray intersects face? */ return(0); r->ro = o; r->rot = t; VCOPY(r->rop, pisect); VCOPY(r->ron, f->norm); r->rod = rdot; r->pert[0] = r->pert[1] = r->pert[2] = 0.0; r->uv[0] = r->uv[1] = 0.0; r->rox = NULL; return(1); /* hit */ }
void Equipcache::loadlook(CharLook& toload, const LookEntry& look) { toload.setbody(getbody(look.getskin())); toload.sethair(gethair(look.gethair())); toload.setface(getface(look.getface())); for (Equipslot e = Character::EQL_CAP; e <= Character::EQL_WEAPON; e = static_cast<Equipslot>(e + 1)) { int32_t equipid = look.getequip(e); if (equipid > 0) { toload.addequip(getequip(equipid)); } } toload.init(&drawinfo); }
void lookfactory::loadcharlook(maplelook* plook) { if (!(plook->isloaded())) { lookinfo* info = plook->getinfo(); for (map<char, int>::iterator equip = info->equips.begin(); equip != info->equips.end(); equip++) { int equipid = equip->second; if (equipid != 0) { plook->addcloth(getcloth(equipid)); } } plook->setbody(getbody(info->skin)); plook->setface(getface(info->faceid)); plook->sethair(gethair(info->hairid)); plook->init(bodydelays, bodyactions, bodyheadmap); } }
int /* create an extended triangle */ cvtri( OBJECT mo, FVECT vp1, FVECT vp2, FVECT vp3, FVECT vn1, FVECT vn2, FVECT vn3, RREAL vc1[2], RREAL vc2[2], RREAL vc3[2] ) { static OBJECT fobj = OVOID; char buf[32]; int flags; TRIDATA *ts; FACE *f; OBJREC *fop; int j; flags = MT_V; /* check what we have */ if (vn1 != NULL && vn2 != NULL && vn3 != NULL) { RREAL *rp; switch (flat_tri(vp1, vp2, vp3, vn1, vn2, vn3)) { case ISBENT: flags |= MT_N; /* fall through */ case ISFLAT: break; case RVBENT: flags |= MT_N; rp = vn1; vn1 = vn3; vn3 = rp; /* fall through */ case RVFLAT: rp = vp1; vp1 = vp3; vp3 = rp; rp = vc1; vc1 = vc3; vc3 = rp; break; case DEGEN: error(WARNING, "degenerate triangle"); return(0); default: error(INTERNAL, "bad return from flat_tri()"); } } if (vc1 != NULL && vc2 != NULL && vc3 != NULL) flags |= MT_UV; if (fobj == OVOID) { /* create new triangle object */ fobj = newobject(); if (fobj == OVOID) goto nomem; fop = objptr(fobj); fop->omod = mo; fop->otype = OBJ_FACE; sprintf(buf, "t%ld", (long)fobj); fop->oname = savqstr(buf); fop->oargs.nfargs = 9; fop->oargs.farg = (RREAL *)malloc(9*sizeof(RREAL)); if (fop->oargs.farg == NULL) goto nomem; } else { /* else reuse failed one */ fop = objptr(fobj); if (fop->otype != OBJ_FACE || fop->oargs.nfargs != 9) error(CONSISTENCY, "code error 1 in cvtri"); } for (j = 3; j--; ) { fop->oargs.farg[j] = vp1[j]; fop->oargs.farg[3+j] = vp2[j]; fop->oargs.farg[6+j] = vp3[j]; } /* create face record */ f = getface(fop); if (f->area == 0.) { free_os(fop); return(0); } if (fop->os != (char *)f) error(CONSISTENCY, "code error 2 in cvtri"); /* follow with auxliary data */ f = (FACE *)realloc((void *)f, sizeof(FACE)+tdsize(flags)); if (f == NULL) goto nomem; fop->os = (char *)f; ts = (TRIDATA *)(f+1); ts->fl = flags; ts->obj = OVOID; if (flags & MT_N) for (j = 3; j--; ) { ts->vn[0][j] = vn1[j]; ts->vn[1][j] = vn2[j]; ts->vn[2][j] = vn3[j]; } if (flags & MT_UV) for (j = 2; j--; ) { ts->vc[0][j] = vc1[j]; ts->vc[1][j] = vc2[j]; ts->vc[2][j] = vc3[j]; } else vc1 = vc2 = vc3 = NULL; /* update bounds */ add2bounds(vp1, vc1); add2bounds(vp2, vc2); add2bounds(vp3, vc3); fobj = OVOID; /* we used this one */ return(1); nomem: error(SYSTEM, "out of memory in cvtri"); return(0); }
void add2bbox( /* expand bounding box to fit object */ register OBJREC *o, FVECT bbmin, FVECT bbmax ) { CONE *co; FACE *fo; INSTANCE *io; MESHINST *mi; FVECT v; register int i, j; switch (o->otype) { case OBJ_SPHERE: case OBJ_BUBBLE: if (o->oargs.nfargs != 4) objerror(o, USER, "bad arguments"); for (i = 0; i < 3; i++) { VCOPY(v, o->oargs.farg); v[i] -= o->oargs.farg[3]; point2bbox(v, bbmin, bbmax); v[i] += 2.0 * o->oargs.farg[3]; point2bbox(v, bbmin, bbmax); } break; case OBJ_FACE: fo = getface(o); j = fo->nv; while (j--) point2bbox(VERTEX(fo,j), bbmin, bbmax); break; case OBJ_CONE: case OBJ_CUP: case OBJ_CYLINDER: case OBJ_TUBE: case OBJ_RING: co = getcone(o, 0); if (o->otype != OBJ_RING) circle2bbox(CO_P0(co), co->ad, CO_R0(co), bbmin, bbmax); circle2bbox(CO_P1(co), co->ad, CO_R1(co), bbmin, bbmax); break; case OBJ_INSTANCE: io = getinstance(o, IO_BOUNDS); for (j = 0; j < 8; j++) { for (i = 0; i < 3; i++) { v[i] = io->obj->scube.cuorg[i]; if (j & 1<<i) v[i] += io->obj->scube.cusize; } multp3(v, v, io->x.f.xfm); point2bbox(v, bbmin, bbmax); } break; case OBJ_MESH: mi = getmeshinst(o, IO_BOUNDS); for (j = 0; j < 8; j++) { for (i = 0; i < 3; i++) { v[i] = mi->msh->mcube.cuorg[i]; if (j & 1<<i) v[i] += mi->msh->mcube.cusize; } multp3(v, v, mi->x.f.xfm); point2bbox(v, bbmin, bbmax); } break; } }
pcstable::pcstable ( double stability, const char *name, char type, bool BD ) : pcvf(name,type,BD), R(stability) { int i,j; fstat = new bool[faces()]; for ( i=0; i<faces(); i++ ) fstat[i] = (f[i].norm()<=R); // we need to update aflow, rflow, eflow // aflow and rflow first for ( i=0; i<faces(); i++ ) { mesh_element *ff = getface(i); for ( j=0; j<ff->faces; j+=2 ) { vec3dd ev = v[ff->face[j+1]->ID] - v[ff->face[(j+ff->faces-1)%(ff->faces)]->ID]; vec3dd ei = n[i]^ev; double tst = ei*(v[ff->face[(j+3)%ff->faces]->ID]-v[ff->face[j+1]->ID]); assert(tst!=0); if (tst<0) ei = -ei; ei.normalize(); aflow[i][j] |= fstat[i] || (ei*f[i]<=R); rflow[i][j] |= fstat[i] || (ei*f[i]>=-R); } aflow[i][ff->faces-1] = aflow[i][ff->faces-2] && aflow[i][0]; rflow[i][ff->faces-1] = rflow[i][ff->faces-2] && rflow[i][0]; for ( j=1; j<ff->faces-2; j+=2 ) { aflow[i][j] = aflow[i][j-1] && aflow[i][j+1]; rflow[i][j] = rflow[i][j-1] && rflow[i][j+1]; } } // time for eflow for ( i=0; i<edges(); i++ ) { mesh_element *ee = mesh::getedge(i); vec3dd evc = v[ee->face[1]->ID]-v[ee->face[0]->ID]; evc.normalize(); switch(ee->cofaces) { case 1: { // boundary edge if (BD) { if (evc*f[ee->coface[0]->ID]>=-R || fstat[ee->coface[0]->ID]) eflow[i] |= 1; if (evc*f[ee->coface[0]->ID]<= R || fstat[ee->coface[0]->ID]) eflow[i] |= 2; } } break; case 2: { if (fstat[ee->coface[0]->ID] || fstat[ee->coface[1]->ID]) { eflow[i] |= 3; continue; } vec3dd an = n[ee->coface[1]->ID]+n[ee->coface[0]->ID]; double shrink = an.norm()/2; an.normalize(); vec3dd f1 = f[ee->coface[0]->ID]-(f[ee->coface[0]->ID]*an)*an; vec3dd f2 = f[ee->coface[1]->ID]-(f[ee->coface[1]->ID]*an)*an; vec3dd ev = v[ee->face[1]->ID] - v[ee->face[0]->ID]; ev.normalize(); vec3dd pp = ev^an; double x2 = f2*ev; double x1 = f1*ev; double y2 = (f2*pp)/shrink; double y1 = (f1*pp)/shrink; int ct = 0; if (fabs(y1)<=R) { double delta = sqrt(R*R-y1*y1); if (x1-delta<=0) eflow[i] |= 2; if (x1+delta>=0) eflow[i] |= 1; ct++; } if (fabs(y2)<=R) { double delta = sqrt(R*R-y2*y2); if (x2-delta<=0) eflow[i] |= 2; if (x2+delta>=0) eflow[i] |= 1; ct++; } if (ct==2) continue; if (ct==0 && y1*y2>0) continue; double x12 = x2-x1; double y12 = y2-y1; double px = -y12; double py = x12; double nm = sqrt(y12*y12+x12*x12); if (nm==0) continue; px *= R/nm; py *= R/nm; double a1 = x1+px; double b1 = y1+py; double c1 = x2+px; double d1 = y2+py; double a2 = x1-px; double b2 = y1-py; double c2 = x2-px; double d2 = y2-py; // check for intersections of intervals a1b1--c1d1 and a2b2--c2d2 // with the x-axis if (b1*d1<0) { double xis = fabs(b1)*c1+fabs(d1)*a1; if (xis<=0) eflow[i] |= 2; if (xis>=0) eflow[i] |= 1; } if (b2*d2<0) { double xis = fabs(b2)*c2+fabs(d2)*a2; if (xis<=0) eflow[i] |= 2; if (xis>=0) eflow[i] |= 1; } } break; default: assert(0); break; } } testvec1 = new vec3dd[faces()]; testvec2 = new vec3dd[faces()]; for ( i=0; i<faces(); i++ ) { if (fstat[i]) continue; double sinalpha = R/f[i].norm(); if (sinalpha>1) sinalpha = 1; double cosalpha = sqrt(1-sinalpha*sinalpha); if (cosalpha<EPS) cosalpha = EPS; double tanalpha = sinalpha/cosalpha; vec3dd tv1 = f[i]+(/*sinalpha**/tanalpha)*(n[i]^f[i]); vec3dd tv2 = f[i]-(/*sinalpha**/tanalpha)*(n[i]^f[i]); vec3dd tst1 = tv1^n[i]; vec3dd tst2 = tv2^n[i]; if (tst1*tv2>0) tst1 = -tst1; if (tst2*tv1>0) tst2 = -tst2; testvec1[i] = tst1; testvec2[i] = tst2; // cout << f[i] << " " << n[i] << " / " << tv1 << " " << tv2 << " / " << testvec1[i] << " " << testvec2[i] << // sinalpha << " " << cosalpha << " " << tanalpha << endl; } }
bool pcstable::connects ( int fce, int eix1, int eix2, double s1, double e1, double s2, double e2 ) { bool res; // if fce stationary, return false if (fstat[fce]) return false; if ( (eix1&1) && (eix2&1) ) { vec3dd w = v[getface(fce)->face[eix2]->ID]-v[getface(fce)->face[eix1]->ID]; res = (w*testvec1[fce]<=0) && (w*testvec2[fce]<=0); } if ( (eix1&1) && !(eix2&1) ) { // vertex and edge piece vec3dd e2s = edgepoint(getface(fce)->face[eix2]->ID,s2); vec3dd e2e = edgepoint(getface(fce)->face[eix2]->ID,e2); vec3dd p1 = v[getface(fce)->face[eix1]->ID]; vec3dd v1 = e2s-p1; vec3dd v2 = e2e-p1; res = !( (v1*testvec1[fce]>=0 && v2*testvec1[fce]>=0) || (v1*testvec2[fce]>=0 && v2*testvec2[fce]>=0) ); } if ( !(eix1&1) && (eix2&1) ) { // vertex and edge piece vec3dd e1s = edgepoint(getface(fce)->face[eix1]->ID,s1); vec3dd e1e = edgepoint(getface(fce)->face[eix1]->ID,e1); vec3dd p2 = v[getface(fce)->face[eix2]->ID]; vec3dd v1 = p2-e1s; vec3dd v2 = p2-e1e; res = !( (v1*testvec1[fce]>=0 && v2*testvec1[fce]>=0) || (v1*testvec2[fce]>=0 && v2*testvec2[fce]>=0) ); } if ( !(eix1&1) && !(eix2&1) ) { // both edges vec3dd e2s = edgepoint(getface(fce)->face[eix2]->ID,s2); vec3dd e2e = edgepoint(getface(fce)->face[eix2]->ID,e2); vec3dd e1s = edgepoint(getface(fce)->face[eix1]->ID,s1); vec3dd e1e = edgepoint(getface(fce)->face[eix1]->ID,e1); vec3dd v1 = e2s-e1s; vec3dd v2 = e2s-e1e; vec3dd v3 = e2e-e1s; vec3dd v4 = e2e-e1e; res = !( (v1*testvec1[fce]>=0 && v2*testvec1[fce]>=0 && v3*testvec1[fce]>=0 && v4*testvec1[fce]>=0) || (v1*testvec2[fce]>=0 && v2*testvec2[fce]>=0 && v3*testvec2[fce]>=0 && v4*testvec2[fce]>=0) ); } // if (res) cout << "Y" << endl; return res; }
extern int load_os( /* load associated data for object */ register OBJREC *op ) { DATARRAY *dp; switch (op->otype) { case OBJ_FACE: /* polygon */ getface(op); return(1); case OBJ_CONE: /* cone */ case OBJ_RING: /* disk */ case OBJ_CYLINDER: /* cylinder */ case OBJ_CUP: /* inverted cone */ case OBJ_TUBE: /* inverted cylinder */ getcone(op, 1); return(1); case OBJ_INSTANCE: /* octree instance */ getinstance(op, IO_ALL); return(1); case OBJ_MESH: /* mesh instance */ getmeshinst(op, IO_ALL); return(1); case PAT_CPICT: /* color picture */ if (op->oargs.nsargs < 4) goto sargerr; getpict(op->oargs.sarg[3]); getfunc(op, 4, 0x3<<5, 0); return(1); case PAT_CDATA: /* color data */ dp = getdata(op->oargs.sarg[3]); getdata(op->oargs.sarg[4]); getdata(op->oargs.sarg[5]); getfunc(op, 6, ((1<<dp->nd)-1)<<7, 0); return(1); case PAT_BDATA: /* brightness data */ if (op->oargs.nsargs < 2) goto sargerr; dp = getdata(op->oargs.sarg[1]); getfunc(op, 2, ((1<<dp->nd)-1)<<3, 0); return(1); case PAT_BFUNC: /* brightness function */ getfunc(op, 1, 0x1, 0); return(1); case PAT_CFUNC: /* color function */ getfunc(op, 3, 0x7, 0); return(1); case TEX_DATA: /* texture data */ if (op->oargs.nsargs < 6) goto sargerr; dp = getdata(op->oargs.sarg[3]); getdata(op->oargs.sarg[4]); getdata(op->oargs.sarg[5]); getfunc(op, 6, ((1<<dp->nd)-1)<<7, 1); return(1); case TEX_FUNC: /* texture function */ getfunc(op, 3, 0x7, 1); return(1); case MIX_DATA: /* mixture data */ dp = getdata(op->oargs.sarg[3]); getfunc(op, 4, ((1<<dp->nd)-1)<<5, 0); return(1); case MIX_PICT: /* mixture picture */ getpict(op->oargs.sarg[3]); getfunc(op, 4, 0x3<<5, 0); return(1); case MIX_FUNC: /* mixture function */ getfunc(op, 3, 0x4, 0); return(1); case MAT_PLASTIC2: /* anisotropic plastic */ case MAT_METAL2: /* anisotropic metal */ getfunc(op, 3, 0x7, 1); return(1); case MAT_BRTDF: /* BRDTfunc material */ getfunc(op, 9, 0x3f, 0); return(1); case MAT_BSDF: /* BSDF material */ if (op->oargs.nsargs < 6) goto sargerr; getfunc(op, 5, 0x1d, 1); loadBSDF(op->oargs.sarg[1]); return(1); case MAT_PDATA: /* plastic BRDF data */ case MAT_MDATA: /* metal BRDF data */ case MAT_TDATA: /* trans BRDF data */ if (op->oargs.nsargs < 2) goto sargerr; getdata(op->oargs.sarg[1]); getfunc(op, 2, 0, 0); return(1); case MAT_PFUNC: /* plastic BRDF func */ case MAT_MFUNC: /* metal BRDF func */ case MAT_TFUNC: /* trans BRDF func */ getfunc(op, 1, 0, 0); return(1); case MAT_DIRECT1: /* prism1 material */ getfunc(op, 4, 0xf, 1); return(1); case MAT_DIRECT2: /* prism2 material */ getfunc(op, 8, 0xff, 1); return(1); } /* nothing to load for the remaining types */ return(0); sargerr: objerror(op, USER, "too few string arguments"); return 0; /* pro forma return */ }