// go through every (child) object static Bool Recurse(HierarchyHelp *hh, BaseThread *bt, BaseObject *main, BaseObject *op, const Matrix &ml, Real srad, Real crad, LONG sub, Bool single) { // test if input object if polygonal if (op->GetType()==Opolygon) { BaseObject *tp = NULL; PolyInfo *pli = NULL; const Vector *padr = ToPoly(op)->GetPointR(); Vector pa,pb; LONG pcnt = ToPoly(op)->GetPointCount(),i,side,a=0,b=0; const CPolygon *vadr = ToPoly(op)->GetPolygonR(); LONG vcnt = ToPoly(op)->GetPolygonCount(); Matrix m; Neighbor n; // load names from resource String pstr = GeLoadString(IDS_ATOM_POINT); String estr = GeLoadString(IDS_ATOM_EDGE); // initialize neighbor class if (!n.Init(pcnt,vadr,vcnt,NULL)) return FALSE; // create separate objects // if this option is enabled no polygonal geometry is build - more parametric objects // are returned instead if (single) { for (i=0; i<pcnt; i++) { // alloc sphere primitive tp=BaseObject::Alloc(Osphere); if (!tp) return FALSE; // add phong tag if (!tp->MakeTag(Tphong)) return FALSE; tp->SetName(pstr+" "+LongToString(i)); // set object parameters BaseContainer *bc = tp->GetDataInstance(); bc->SetReal(PRIM_SPHERE_RAD,srad); bc->SetReal(PRIM_SPHERE_SUB,sub); // insert as last object under main tp->InsertUnderLast(main); // set position in local coordinates tp->SetRelPos(padr[i]*ml); } for (i=0; i<vcnt; i++) { // get polygon info for i-th polygon pli = n.GetPolyInfo(i); for (side=0; side<4; side++) { // only proceed if edge has not already been processed // and edge really exists (for triangles side 2 from c..d does not exist as c==d) if (pli->mark[side] || side==2 && vadr[i].c==vadr[i].d) continue; // alloc cylinder primitive tp=BaseObject::Alloc(Ocylinder); if (!tp) return FALSE; // add phong tag if (!tp->MakeTag(Tphong)) return FALSE; switch (side) { case 0: a=vadr[i].a; b=vadr[i].b; break; case 1: a=vadr[i].b; b=vadr[i].c; break; case 2: a=vadr[i].c; b=vadr[i].d; break; case 3: a=vadr[i].d; b=vadr[i].a; break; } tp->SetName(estr+" "+LongToString(pli->edge[side])); pa = padr[a]*ml; pb = padr[b]*ml; // set object parameters BaseContainer *bc = tp->GetDataInstance(); bc->SetReal(PRIM_CYLINDER_RADIUS,crad); bc->SetReal(PRIM_CYLINDER_HEIGHT,Len(pb-pa)); bc->SetReal(PRIM_AXIS,4); bc->SetLong(PRIM_CYLINDER_CAPS,FALSE); bc->SetLong(PRIM_CYLINDER_HSUB,1); bc->SetLong(PRIM_CYLINDER_SEG,sub); // place cylinder at edge center tp->SetRelPos((pa+pb)*0.5); // build edge matrix m.v3=!(pb-pa); RectangularSystem(m.v3,&m.v1,&m.v2); tp->SetRelRot(MatrixToHPB(m, tp->GetRotationOrder())); // insert as last object under main tp->InsertUnderLast(main); } } } else { // check if polygonal geometry has to be built tp = BuildPolyHull(ToPoly(op),ml,srad,crad,sub,hh->GetLOD(),&n,bt); if (tp) { tp->SetName(op->GetName()); tp->InsertUnderLast(main); // check if isoparm geometry has to be built if (hh->GetBuildFlags()&BUILDFLAGS_ISOPARM) { LineObject *ip = BuildIsoHull(ToPoly(op),ml,srad,crad,sub,hh->GetLOD(),&n,bt); // isoparm always needs to be set into a polygon object if (ip) tp->SetIsoparm(ip); } } } } for (op=op->GetDown(); op; op=op->GetNext()) if (!Recurse(hh,bt,main,op,ml*op->GetMl(),srad,crad,sub,single)) return FALSE; // check for user break return !bt || !bt->TestBreak(); }
void DropEffector::ModifyPoints(BaseObject* op, BaseObject* gen, BaseDocument* doc, EffectorDataStruct* data, MoData* md, BaseThread* thread) { if (!ed.target || !rcol || data->strength == 0.0) return; C4D_Falloff* falloff = GetFalloff(); if (!falloff) return; Int32 i = 0; Float fall = 0.0; Vector off = Vector(0.0); Vector ray_p = Vector(0.0), ray_dir = Vector(0.0); Vector targ_off = Vector(0.0), targ_hpb = Vector(0.0); MDArray<Int32> flag_array = md->GetLongArray(MODATA_FLAGS); MDArray<Matrix> mat_array = md->GetMatrixArray(MODATA_MATRIX); MDArray<Float> weight_array = md->GetRealArray(MODATA_WEIGHT); if (!mat_array) return; Int32 mdcount = (Int32)md->GetCount(); for (i = 0; i < mdcount; i++) { //If the particle isn't visible, don't calculate if (!(flag_array[i] & MOGENFLAG_CLONE_ON) || (flag_array[i] & MOGENFLAG_DISABLE)) continue; //Multiply into global space off = mat_array[i].off; off = ed.genmg * off; //Sample the falloff falloff->Sample(off, &fall, true, weight_array[i]); if (fall == 0.0) continue; //Set up the ray for the collision ray_p = ed.itargmg * off; switch (ed.mode) { default: case DROPEFFECTOR_MODE_PNORMAL: ray_dir = ed.genmg.TransformVector(mat_array[i].v3); break; case DROPEFFECTOR_MODE_NNORMAL: ray_dir = ed.genmg.TransformVector(-mat_array[i].v3); break; case DROPEFFECTOR_MODE_AXIS: ray_dir = (ed.targmg.off - off); break; case DROPEFFECTOR_MODE_SELFAXIS: ray_dir = (ed.genmg.off - off); break; case DROPEFFECTOR_MODE_PX: ray_dir = Vector(1.0, 0.0, 0.0); break; case DROPEFFECTOR_MODE_PY: ray_dir = Vector(0.0, 1.0, 0.0); break; case DROPEFFECTOR_MODE_PZ: ray_dir = Vector(0.0, 0.0, 1.0); break; case DROPEFFECTOR_MODE_NX: ray_dir = Vector(-1.0, 0.0, 0.0); break; case DROPEFFECTOR_MODE_NY: ray_dir = Vector(0.0, -1.0, 0.0); break; case DROPEFFECTOR_MODE_NZ: ray_dir = Vector(0.0, 0.0, -1.0); break; } ray_dir = ed.itargmg.TransformVector(ray_dir); //Calculate an intersection if (rcol->Intersect(ray_p, !ray_dir, ed.maxdist, false)) { if (rcol->GetNearestIntersection(&rcolres)) { fall *= data->strength; targ_off = Blend(mat_array[i].off, ed.igenmg * (ed.targmg * rcolres.hitpos), fall); targ_hpb = VectorToHPB(ed.igenmg.TransformVector(ed.targmg.TransformVector(rcolres.s_normal))); mat_array[i] = HPBToMatrix(Blend(MatrixToHPB(mat_array[i], ROTATIONORDER_DEFAULT), targ_hpb, fall), ROTATIONORDER_DEFAULT); mat_array[i].off = targ_off; } } } }