void APITestUtil::PointTests() { // now let's build a test object NURBSSet nset; Matrix3 mat; mat.IdentityMatrix(); // 6 types of points... // 1: build an independent point int indPnt = MakeTestPoint(nset); // 2: now a constrained point int ptPnt = MakeTestPointCPoint(nset, indPnt); // build a cv curve int cvCrv = MakeTestCVCurve(nset, mat); // 3: a constrained point on that curve int crvPnt = MakeTestCurveCPoint(nset, cvCrv); // build a cv surface int cvSurf = MakeTestCVSurface(nset, mat); // 4: a constrained point on that surface int srfPnt = MakeTestSurfCPoint(nset, cvSurf); // 5: Curve Curve intersection point int cvCrv1 = MakeTestCVCurve(nset, TransMatrix(Point3(65, 0, 0)) * RotateZMatrix(0.5)); int intPoint = MakeTestCurveCurve(nset, cvCrv, cvCrv1, FALSE); // 6: Curve Surface intersection point. int cvCrv2 = MakeTestCVCurve(nset, RotateXMatrix(PI/2.0f) * TransMatrix(Point3(0, 0, -175))); int srfIntPoint = MakeTestCurveSurface(nset, cvSurf, cvCrv2); Object *obj = CreateNURBSObject(mpIp, &nset, mat); INode *node = mpIp->CreateObjectNode(obj); node->SetName(GetString(IDS_PNT_TEST_OBJECT)); mpIp->RedrawViews(mpIp->GetTime()); }
int APITestUtil::MakeTestUVLoftSurface(NURBSSet &nset) { Matrix3 scale = ScaleMatrix(Point3(50, 50, 50)); Matrix3 rotate = RotateZMatrix(PI/2.0f); int cu0 = P1Curve(nset, scale * TransMatrix(Point3(0, 0, 0))); int cu1 = P1Curve(nset, scale * TransMatrix(Point3(0, 0, 20))); int cu2 = P1Curve(nset, scale * TransMatrix(Point3(0, 0, 40))); int cv0 = P2Curve(nset, TransMatrix(Point3(50, 50, 0))); int cv1 = P2Curve(nset, TransMatrix(Point3(-50, 50, 0))); int cv2 = P2Curve(nset, TransMatrix(Point3(-50, -50, 0))); int cv3 = P2Curve(nset, TransMatrix(Point3(50, -50, 0))); NURBSUVLoftSurface *s = new NURBSUVLoftSurface(); s->SetName(GetString(IDS_UVLOFT_SURFACE)); s->SetNSet(&nset); s->AppendUCurve(cu0); s->AppendUCurve(cu1); s->AppendUCurve(cu2); s->AppendVCurve(cv0); s->AppendVCurve(cv1); s->AppendVCurve(cv2); s->AppendVCurve(cv3); return nset.AppendObject(s); }
void APITestUtil::COSTests() { // now let's build a test object NURBSSet nset; Matrix3 mat; mat.IdentityMatrix(); // build a cv surface int cvSurf = MakeTestCVSurface(nset, mat); // Now an Iso Curve on the CV surface int isoCrv1 = MakeTestIsoCurveU(nset, cvSurf); // Now an Iso Curve on the CV surface int isoCrv2 = MakeTestIsoCurveV(nset, cvSurf); // build a CV Curve on Surface int cvCOS = MakeTestCurveOnSurface(nset, cvSurf); // build a Point Curve on Surface int pntCOS = MakeTestPointCurveOnSurface(nset, cvSurf); // build a Surface Normal Offset Curve int cnoCrf = MakeTestSurfaceNormalCurve(nset, cvCOS); // build a surface surface intersection curve int cvSurf1 = MakeTestCVSurface(nset, TransMatrix(Point3(0.0, 0.0, -30.0)) * RotateYMatrix(0.5)); int intCrv = MakeTestSurfSurfIntersectionCurve(nset, cvSurf, cvSurf1); // Vector Projection Curve int cvCrv1 = MakeTestCVCurve(nset, TransMatrix(Point3(-100, -200, 40))); int vecCrv = MakeTestProjectVectorCurve(nset, cvSurf, cvCrv1); // Normal Normal Curve int cvCrv2 = MakeTestCVCurve(nset, TransMatrix(Point3(0, -250, 10))); int nrmCrv = MakeTestProjectNormalCurve(nset, cvSurf1, cvCrv2); Object *obj = CreateNURBSObject(mpIp, &nset, mat); INode *node = mpIp->CreateObjectNode(obj); node->SetName(GetString(IDS_COS_TEST_OBJECT)); mpIp->RedrawViews(mpIp->GetTime()); }
int APITestUtil::MakeTestLatheSurface(NURBSSet &nset) { int p = MakeCurveToLathe(nset); NURBSLatheSurface *s = new NURBSLatheSurface(); s->SetName(GetString(IDS_LATHE_SURFACE)); s->SetNSet(&nset); s->SetParent(p); Matrix3 mat = TransMatrix(Point3(200, 200, 0)); s->SetAxis(0, mat); s->FlipNormals(TRUE); return nset.AppendObject(s); }
////////////////////////////////////////////////////////////////////////// // lookAt void BcMat4d::lookAt( const BcVec3d& Position, const BcVec3d& LookAt, const BcVec3d& UpVec ) { const BcVec3d Front = ( Position - LookAt ).normal(); const BcVec3d Side = Front.cross( UpVec ).normal(); const BcVec3d Up = Side.cross( Front ).normal(); BcMat4d RotMatrix( BcVec4d( Side.x(), Up.x(), -Front.x(), 0.0f ), BcVec4d( Side.y(), Up.y(), -Front.y(), 0.0f ), BcVec4d( Side.z(), Up.z(), -Front.z(), 0.0f ), BcVec4d( 0.0f, 0.0f, 0.0f, 1.0f ) ); BcMat4d TransMatrix( BcVec4d( 1.0f, 0.0f, 0.0f, 0.0f ), BcVec4d( 0.0f, 1.0f, 0.0f, 0.0f ), BcVec4d( 0.0f, 0.0f, 1.0f, 0.0f ), BcVec4d( -Position.x(), -Position.y(), -Position.z(), 1.0f ) ); (*this) = TransMatrix * RotMatrix; }
int APITestUtil::MakeTest2RailSweepSurface(NURBSSet &nset) { int rail1 = P1Curve(nset, ScaleMatrix(Point3(70, 70, 70))); int rail2 = P1Curve(nset, ScaleMatrix(Point3(90, 90, 90))); int cross = P1Curve(nset, ScaleMatrix(Point3(5, 5, 5)) * RotateYMatrix(PI/2.0f) * TransMatrix(Point3(70, 70, 0))); NURBS2RailSweepSurface *s = new NURBS2RailSweepSurface(); s->SetName(GetString(IDS_2RAIL_SURFACE)); s->SetNSet(&nset); s->SetRailParent(0, rail1); s->SetRailParent(1, rail2); s->AppendCurve(cross, FALSE); return nset.AppendObject(s); }
int APITestUtil::MakeTest1RailSweepSurface(NURBSSet &nset) { int rail = P1Curve(nset, ScaleMatrix(Point3(50, 50, 50))); int cross = P1Curve(nset, ScaleMatrix(Point3(5, 5, 5)) * RotateYMatrix(PI/2.0f) * TransMatrix(Point3(50, 50, 0))); NURBS1RailSweepSurface *s = new NURBS1RailSweepSurface(); s->SetName(GetString(IDS_1RAIL_SURFACE)); s->SetNSet(&nset); s->SetParentRail(rail); s->AppendCurve(cross, FALSE); s->SetParallel(FALSE); s->FlipNormals(TRUE); return nset.AppendObject(s); }
int APITestUtil::MakeTestMultiCurveTrimSurface(NURBSSet &nset) { int srf = MakeTestCVSurface(nset, TransMatrix(Point3(100, 100, 150))); int cos1 = COS1(nset, srf); int cos2 = COS2(nset, srf); NURBSMultiCurveTrimSurface *s = new NURBSMultiCurveTrimSurface(); s->SetName(GetString(IDS_MULTI_TRIM_SURFACE)); s->SetNSet(&nset); s->SetSurfaceParent(srf); s->AppendCurve(cos1); s->AppendCurve(cos2); // Tell the surface to flip the orientation of the trim. s->SetFlipTrim(TRUE); return nset.AppendObject(s); }
void APITestUtil::CombinedTests() { // now let's build a test object NURBSSet nset; Matrix3 mat; mat.IdentityMatrix(); // build an independent point int indPnt = MakeTestPoint(nset); // now a constrained point int ptPnt = MakeTestPointCPoint(nset, indPnt); // build a cv curve int cvCrv = MakeTestCVCurve(nset, mat); // and a constrained point on that curve int crvPnt = MakeTestCurveCPoint(nset, cvCrv); // now a point curve int ptCrv = MakeTestPointCurve(nset, mat); // Blend the two curves int blendCrv = MakeTestBlendCurve(nset, cvCrv, ptCrv); // make an offset of the CV curve int offCrv = MakeTestOffsetCurve(nset, cvCrv); // make a Transform curve of the point curve int xformCrv = MakeTestXFormCurve(nset, ptCrv); // make a mirror of the blend int mirCrv = MakeTestMirrorCurve(nset, blendCrv); // make a fillet curve (It makes it's own point curves to fillet) int fltCrv = MakeTestFilletCurve(nset); // make a chamfer curve (It makes it's own point curves to fillet) int chmCrv = MakeTestChamferCurve(nset); // build a cv surface int cvSurf = MakeTestCVSurface(nset, mat); // and a constrained point on that surface int srfPnt = MakeTestSurfCPoint(nset, cvSurf); // Curve Surface intersection point. int cvCrv2 = MakeTestCVCurve(nset, RotateXMatrix(PI/2.0f) * TransMatrix(Point3(0, 0, -175))); int srfIntPoint = MakeTestCurveSurface(nset, cvSurf, cvCrv2); // Now an Iso Curve on the CV surface int isoCrv1 = MakeTestIsoCurveU(nset, cvSurf); // Now an Iso Curve on the CV surface int isoCrv2 = MakeTestIsoCurveV(nset, cvSurf); // Now a Surface Edge Curve on the CV surface int surfEdgeCrv = MakeTestSurfaceEdgeCurve(nset, cvSurf); // build a CV Curve on Surface int cvCOS = MakeTestCurveOnSurface(nset, cvSurf); // build a Point Curve on Surface int pntCOS = MakeTestPointCurveOnSurface(nset, cvSurf); // build a Surface Normal Offset Curve int cnoCrf = MakeTestSurfaceNormalCurve(nset, cvCOS); // Make a curve-curve intersection point int curveCurve = MakeTestCurveCurve(nset, isoCrv1, isoCrv2, TRUE); // build a point surface int ptSurf = MakeTestPointSurface(nset, mat); // Blend the two surfaces int blendSurf = MakeTestBlendSurface(nset, cvSurf, ptSurf); // Offset of the blend int offSurf = MakeTestOffsetSurface(nset, blendSurf); // Transform of the Offset int xformSurf = MakeTestXFormSurface(nset, offSurf); // Mirror of the transform surface int mirSurf = MakeTestMirrorSurface(nset, xformSurf); // Make a Ruled surface between two curves int rulSurf = MakeTestRuledSurface(nset, cvCrv, ptCrv); // Make a ULoft surface int uLoftSurf = MakeTestULoftSurface(nset, ptCrv, offCrv, xformCrv); // Make a Extrude surface int extSurf = MakeTestExtrudeSurface(nset, xformCrv); // Make a lathe int lthSurf = MakeTestLatheSurface(nset); // these will build their own curves to work with // UV Loft int uvLoftSurf = MakeTestUVLoftSurface(nset); // 1 Rail Sweep int oneRailSurf = MakeTest1RailSweepSurface(nset); // 2 Rail Sweep int twoRailSurf = MakeTest2RailSweepSurface(nset); // MultiCurveTrim Surface int multiTrimSurf = MakeTestMultiCurveTrimSurface(nset); // Now make the curves and surfaces that we'll use later for the join tests int jc1, jc2, js1, js2; AddObjectsForJoinTests(nset, jc1, jc2, js1, js2); int bc, bs; AddObjectsForBreakTests(nset, bc, bs); Object *obj = CreateNURBSObject(mpIp, &nset, mat); INode *node = mpIp->CreateObjectNode(obj); node->SetName(GetString(IDS_TEST_OBJECT)); NURBSSet addNset; // build a point surface int addptSurf = AddTestPointSurface(addNset); // add an iso curve to the previously created CV Surface NURBSId id = nset.GetNURBSObject(cvSurf)->GetId(); int addIsoCrv = AddTestIsoCurve(addNset, id); AddNURBSObjects(obj, mpIp, &addNset); // now test some changing functionality // Let's change the name of the CVSurface NURBSObject* nObj = nset.GetNURBSObject(cvSurf); nObj->SetName(_T("New CVSurf Name")); // testing only, no need to localize // now let's change the position of one of the points in the point curve NURBSPointCurve* ptCrvObj = (NURBSPointCurve*)nset.GetNURBSObject(ptCrv); ptCrvObj->GetPoint(0)->SetPosition(0, Point3(10, 160, 0)); // moved from 0,150,0 // now let's change the position and weight of one of the CVs // in the CV Surface NURBSCVSurface* cvSurfObj = (NURBSCVSurface*)nset.GetNURBSObject(cvSurf); cvSurfObj->GetCV(0, 0)->SetPosition(0, Point3(-150.0, -100.0, 20.0)); // moved from 0,0,0 cvSurfObj->GetCV(0, 0)->SetWeight(0, 2.0); // from 1.0 // now let's do a transform of a curve. NURBSIdTab xfmTab; NURBSId nid = nset.GetNURBSObject(jc1)->GetId(); xfmTab.Append(1, &nid); Matrix3 xfmMat; xfmMat = TransMatrix(Point3(10, 10, -10)); SetXFormPacket xPack(xfmMat); NURBSResult res = Transform(obj, xfmTab, xPack, xfmMat, 0); // Now let's Join two curves NURBSId jc1id = nset.GetNURBSObject(jc1)->GetId(), jc2id = nset.GetNURBSObject(jc2)->GetId(); JoinCurves(obj, jc1id, jc2id, FALSE, TRUE, 20.0, 1.0f, 1.0f, 0); // Now let's Join two surfaces NURBSId js1id = nset.GetNURBSObject(js1)->GetId(), js2id = nset.GetNURBSObject(js2)->GetId(); JoinSurfaces(obj, js1id, js2id, 1, 0, 20.0, 1.0f, 1.0f, 0); // Break a Curve NURBSId bcid = nset.GetNURBSObject(bc)->GetId(); BreakCurve(obj, bcid, .5, 0); // Break a Surface NURBSId bsid = nset.GetNURBSObject(bs)->GetId(); BreakSurface(obj, bsid, TRUE, .5, 0); mpIp->RedrawViews(mpIp->GetTime()); nset.DeleteObjects(); addNset.DeleteObjects(); // now do a detach NURBSSet detset; Matrix3 detmat; detmat.IdentityMatrix(); // build a cv curve int detcvCrv = MakeTestCVCurve(detset, detmat); // now a point curve int detptCrv = MakeTestPointCurve(detset, detmat); // Blend the two curves int detblendCrv = MakeTestBlendCurve(detset, detcvCrv, detptCrv); Object *detobj = CreateNURBSObject(mpIp, &detset, detmat); INode *detnode = mpIp->CreateObjectNode(detobj); detnode->SetName("Detach From"); BOOL copy = TRUE; BOOL relational = TRUE; NURBSIdList detlist; NURBSId oid = detset.GetNURBSObject(detblendCrv)->GetId(); detlist.Append(1, &oid); DetachObjects(GetCOREInterface()->GetTime(), detnode, detobj, detlist, "Detach Test", copy, relational); mpIp->RedrawViews(mpIp->GetTime()); }
void sphere() { SetGeomScreen(1000); MATRIX m; VECTOR trans = {0, 0, 300}; TransMatrix(&m, &trans); SetTransMatrix(&m); const int SPHERE_LATITUDE = 24; const int SPHERE_LONGITUDE = 24; const int SPHERE_RADIUS = 50; SVECTOR* sphere_vector = (SVECTOR*)MemoryManager::malloc(SPHERE_LATITUDE * SPHERE_LONGITUDE * sizeof(*sphere_vector)); POLY_G4* poly_sphere = (POLY_G4*)MemoryManager::malloc(SPHERE_LATITUDE * SPHERE_LONGITUDE * sizeof(*poly_sphere)); { /** * x <- r * sin(\alpha) * cos(\beta) * y <- r * sin(\alpha) * sin(\beta) * z <- r * cos(\alpha) * avec: * \alpha \in [0, pi] : latitude * \beta \in [0, 2*pi] : longitude */ SVECTOR* v = sphere_vector; for ( int la = 0; la < SPHERE_LATITUDE; la++ ) { int alpha = (TRIGO_PI * la) / SPHERE_LATITUDE; int sa = sin4k[alpha]; int ca = cos4k[alpha]; for ( int lo = 0; lo < SPHERE_LONGITUDE; lo++, v++ ) { int beta = (2 * TRIGO_PI * lo) / SPHERE_LONGITUDE; unsigned short x = (SPHERE_RADIUS * sa * cos4k[beta]) / (TRIGO_SCALE * TRIGO_SCALE); unsigned short y = (SPHERE_RADIUS * sa * sin4k[beta]) / (TRIGO_SCALE *TRIGO_SCALE); unsigned short z = (SPHERE_RADIUS * ca) / TRIGO_SCALE; setVector(v, x, y, z); } } POLY_G4* p = poly_sphere; for ( int la = 0; la < SPHERE_LATITUDE; la++ ) { for ( int lo = 0; lo < SPHERE_LONGITUDE; lo++, p++ ) { SetPolyG4(p); } } } set_clear_color(0); static const int SPHERE_TRANSITION_STEP = 200; static const int SPHERE_STEP_TIME = 600; enum { SCENE_LAT_FLAT = 1, SCENE_LAT_SMOOTH, SCENE_LIGHT_FIX_EDGE, SCENE_LIGHT_FIX_SQUARE, SCENE_LIGHT_FIX, SCENE_LIGHT_MOVE, SCENE_LIGHT_CUTOFF, SCENE_ZOOM, SCENE_LIGHT_SINUS_WAVE, }; int current_scene = SCENE_LAT_FLAT; int t = 0; enable_auto_clear_color_buffer(); while ( t < SCENE_LIGHT_SINUS_WAVE * SPHERE_STEP_TIME) { SVECTOR rot = {8*t%4096, 4*t%4096, 10*t%4096}; RotMatrix(&rot, &m); SetRotMatrix(&m); // update sphere POLY_G4* p = poly_sphere; // offset plasma static int off = 0; if ( t >= 100 && t % 5 == 0 ) off++; // light move static int light_move_lat = 0; static int light_move_long = 0; static int light_move_dlat = 1; static int light_move_dlong = 1; if ( t % 1 == 0 ) { if ( t % 3 == 0 ) { light_move_lat += light_move_dlat; if ( light_move_lat < 0 ) light_move_lat = 0; if ( light_move_lat >= SPHERE_LATITUDE ) light_move_lat = SPHERE_LATITUDE-1; if ( light_move_lat == 0 || light_move_lat == SPHERE_LATITUDE-1 ) light_move_dlat *= -1; } if ( t % 1 == 0 ) { light_move_long += light_move_dlong; if ( light_move_long < 0 ) light_move_long = 0; if ( light_move_long >= SPHERE_LONGITUDE ) light_move_long = SPHERE_LONGITUDE-1; if ( light_move_long == 0 || light_move_long == SPHERE_LONGITUDE-1 ) light_move_long *= -1; } } // dynamic cutoff static int light_dynamic_distance_max = 50; if ( current_scene == SCENE_LIGHT_CUTOFF && t % 1 == 0 ) { static const int LIGHT_DYNAMIC_DISTANCE_MIN = 20; static const int LIGHT_DYNAMIC_DISTANCE_MAX = 60; static int light_dynamic_ddist = -1; light_dynamic_distance_max += light_dynamic_ddist; if ( light_dynamic_distance_max <= LIGHT_DYNAMIC_DISTANCE_MIN || light_dynamic_distance_max >= LIGHT_DYNAMIC_DISTANCE_MAX ) light_dynamic_ddist *= -1; } int light_dynamic_distance_max2 = light_dynamic_distance_max * light_dynamic_distance_max; // dynamic radius if ( current_scene >= SCENE_ZOOM && t % 1 == 0 ) { static const int ZOOM_MIN = 150; static const int ZOOM_MAX = 900; static int zoom_stride = 15; static int zoom = 300; SetGeomScreen(zoom); zoom += zoom_stride; if ( zoom <= ZOOM_MIN || zoom >= ZOOM_MAX ) zoom_stride *= -1; } int dt = 1; for ( int la = 0; la < SPHERE_LATITUDE; la++ ) { for ( int lo = 0; lo < SPHERE_LONGITUDE; lo++, p++ ) { int lo_next = (lo+1)%SPHERE_LONGITUDE; int la_next = SignalProcessing::min(la+1, SPHERE_LATITUDE-1); SVECTOR* v0 = &sphere_vector[la*SPHERE_LONGITUDE+lo]; SVECTOR* v1 = &sphere_vector[la*SPHERE_LONGITUDE+lo_next]; SVECTOR* v2 = &sphere_vector[la_next*SPHERE_LONGITUDE+lo]; SVECTOR* v3 = &sphere_vector[la_next*SPHERE_LONGITUDE+lo_next]; long dmy, flag; int otz = 0; otz += RotTransPers(v0, (long*)&p->x0, &dmy, &flag); otz += RotTransPers(v1, (long*)&p->x1, &dmy, &flag); otz += RotTransPers(v2, (long*)&p->x2, &dmy, &flag); otz += RotTransPers(v3, (long*)&p->x3, &dmy, &flag); otz /= 4; limitRange(otz, 0, OT_LENGTH-1); AddPrim(ot + OT_LENGTH - 1 - otz, p); if ( t < SCENE_LAT_FLAT*SPHERE_STEP_TIME ) { // latitude same flat color current_scene = SCENE_LAT_FLAT; unsigned char b = 255 * la / SPHERE_LATITUDE; setRGB0(p, b, b, b); setRGB1(p, b, b, b); setRGB2(p, b, b, b); setRGB3(p, b, b, b); } else if ( t < SCENE_LAT_SMOOTH*SPHERE_STEP_TIME ) { // latitude same smooth color current_scene = SCENE_LAT_SMOOTH; unsigned char b = 255 * la / SPHERE_LATITUDE; unsigned char bb = 255 * ((la+1)%SPHERE_LATITUDE) / SPHERE_LATITUDE; if ( t < (SCENE_LAT_SMOOTH-1)*SPHERE_STEP_TIME + SPHERE_TRANSITION_STEP ) { int d= (t%SPHERE_TRANSITION_STEP); b = (b * d + p->r0 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP; bb = (bb * d + p->r2 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP; } setRGB0(p, b, b, b); setRGB1(p, b, b, b); setRGB2(p, bb, bb, bb); setRGB3(p, bb, bb, bb); } else if ( t < SCENE_LIGHT_FIX_EDGE*SPHERE_STEP_TIME ) { // latitude same smooth color + lighting fix dt = 3; current_scene = SCENE_LIGHT_FIX_EDGE; unsigned char b = 255; unsigned char bb = 255; const int LIGHT_LAT = 3*SPHERE_LATITUDE/4; const int LIGHT_LONG = SPHERE_LONGITUDE/4; const int LIGHT_DISTANCE_MAX = 50; const int LIGHT_DISTANCE_MAX2 = LIGHT_DISTANCE_MAX * LIGHT_DISTANCE_MAX; SVECTOR* l = &sphere_vector[LIGHT_LAT*SPHERE_LONGITUDE+LIGHT_LONG]; SVECTOR* v = &sphere_vector[la*SPHERE_LONGITUDE+lo]; SVECTOR* vv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo]; int d = SignalProcessing::dist2(l, v); int dd = SignalProcessing::dist2(l, vv); b = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - d) * b) / LIGHT_DISTANCE_MAX2; bb = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - dd) * bb) / LIGHT_DISTANCE_MAX2; // smooth if ( t < (SCENE_LIGHT_FIX-1)*SPHERE_STEP_TIME + SPHERE_TRANSITION_STEP ) { int d= (t%SPHERE_TRANSITION_STEP); b = (b * d + p->r0 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP; bb = (bb * d + p->r2 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP; } setRGB0(p, b, b, b); setRGB1(p, b, b, b); setRGB2(p, bb, bb, bb); setRGB3(p, bb, bb, bb); } else if ( t < SCENE_LIGHT_FIX_SQUARE*SPHERE_STEP_TIME ) { // latitude same smooth color + lighting fix dt = 3; current_scene = SCENE_LIGHT_FIX_SQUARE; unsigned char b = 255; unsigned char bb = 255; unsigned char bbb = 255; unsigned char bbbb = 255; const int LIGHT_LAT = 3*SPHERE_LATITUDE/4; const int LIGHT_LONG = SPHERE_LONGITUDE/4; const int LIGHT_DISTANCE_MAX = 50; const int LIGHT_DISTANCE_MAX2 = LIGHT_DISTANCE_MAX * LIGHT_DISTANCE_MAX; SVECTOR* l = &sphere_vector[LIGHT_LAT*SPHERE_LONGITUDE+LIGHT_LONG]; SVECTOR* v = &sphere_vector[la*SPHERE_LONGITUDE+lo]; SVECTOR* vv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo]; SVECTOR* vvv = &sphere_vector[la*SPHERE_LONGITUDE+lo_next]; SVECTOR* vvvv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo_next]; int d = SignalProcessing::dist2(l, v); int dd = SignalProcessing::dist2(l, vv); int ddd = SignalProcessing::dist2(l, vvv); int dddd = SignalProcessing::dist2(l, vvvv); b = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - d) * b) / LIGHT_DISTANCE_MAX2; bb = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - dd) * bb) / LIGHT_DISTANCE_MAX2; bbb = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - ddd) * bbb) / LIGHT_DISTANCE_MAX2; bbbb = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - dddd) * bbbb) / LIGHT_DISTANCE_MAX2; // smooth if ( t < (SCENE_LIGHT_FIX-1)*SPHERE_STEP_TIME + SPHERE_TRANSITION_STEP ) { int d= (t%SPHERE_TRANSITION_STEP); b = (b * d + p->r0 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP; bb = (bb * d + p->r2 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP; bbb = (bbb * d + p->r2 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP; bbbb = (bbbb * d + p->r2 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP; } setRGB0(p, b, b, b); setRGB1(p, bb, bb, bb); setRGB2(p, bbb, bbb, bbb); setRGB3(p, bbbb, bbbb, bbbb); } else if ( t < SCENE_LIGHT_FIX*SPHERE_STEP_TIME ) { // latitude same smooth color + lighting fix dt = 1; current_scene = SCENE_LIGHT_FIX; unsigned char b = 255; unsigned char bb = 255; unsigned char bbb = 255; unsigned char bbbb = 255; const int LIGHT_LAT = 3*SPHERE_LATITUDE/4; const int LIGHT_LONG = SPHERE_LONGITUDE/4; const int LIGHT_DISTANCE_MAX = 50; const int LIGHT_DISTANCE_MAX2 = LIGHT_DISTANCE_MAX * LIGHT_DISTANCE_MAX; SVECTOR* l = &sphere_vector[LIGHT_LAT*SPHERE_LONGITUDE+LIGHT_LONG]; SVECTOR* v = &sphere_vector[la*SPHERE_LONGITUDE+lo]; SVECTOR* vv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo]; SVECTOR* vvv = &sphere_vector[la*SPHERE_LONGITUDE+lo_next]; SVECTOR* vvvv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo_next]; int d = SignalProcessing::dist2(l, v); int dd = SignalProcessing::dist2(l, vv); int ddd = SignalProcessing::dist2(l, vvv); int dddd = SignalProcessing::dist2(l, vvvv); b = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - d) * b) / LIGHT_DISTANCE_MAX2; bb = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - dd) * bb) / LIGHT_DISTANCE_MAX2; bbb = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - ddd) * bbb) / LIGHT_DISTANCE_MAX2; bbbb = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - dddd) * bbbb) / LIGHT_DISTANCE_MAX2; // smooth if ( t < (SCENE_LIGHT_FIX-1)*SPHERE_STEP_TIME + SPHERE_TRANSITION_STEP ) { int d= (t%SPHERE_TRANSITION_STEP); b = (b * d + p->r0 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP; bb = (bb * d + p->r2 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP; bbb = (bbb * d + p->r1 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP; bbbb = (bbbb * d + p->r3 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP; } setRGB0(p, b, b, b); setRGB2(p, bb, bb, bb); setRGB1(p, bbb, bbb, bbb); setRGB3(p, bbbb, bbbb, bbbb); } else if ( t < SCENE_LIGHT_MOVE*SPHERE_STEP_TIME ) { // latitude same smooth color + lighting move current_scene = SCENE_LIGHT_MOVE; unsigned char b = 255; unsigned char bb = 255; unsigned char bbb = 255; unsigned char bbbb = 255; const int LIGHT_DISTANCE_MAX = 50; const int LIGHT_DISTANCE_MAX2 = LIGHT_DISTANCE_MAX * LIGHT_DISTANCE_MAX; // light { SVECTOR* l = &sphere_vector[light_move_lat*SPHERE_LONGITUDE+light_move_long]; SVECTOR* v = &sphere_vector[la*SPHERE_LONGITUDE+lo]; SVECTOR* vv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo]; SVECTOR* vvv = &sphere_vector[la*SPHERE_LONGITUDE+lo_next]; SVECTOR* vvvv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo_next]; int d = SignalProcessing::dist2(l, v); int dd = SignalProcessing::dist2(l, vv); int ddd = SignalProcessing::dist2(l, vvv); int dddd = SignalProcessing::dist2(l, vvvv); b = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - d) * b) / LIGHT_DISTANCE_MAX2; bb = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - dd) * bb) / LIGHT_DISTANCE_MAX2; bbb = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - ddd) * bbb) / LIGHT_DISTANCE_MAX2; bbbb = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - dddd) * bbbb) / LIGHT_DISTANCE_MAX2; } // smooth if ( t < (SCENE_LIGHT_MOVE-1)*SPHERE_STEP_TIME + SPHERE_TRANSITION_STEP ) { int d= (t%SPHERE_TRANSITION_STEP); b = (b * d + p->r0 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP; bb = (bb * d + p->r2 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP; bbb = (bbb * d + p->r1 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP; bbbb = (bbbb * d + p->r3 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP; } setRGB0(p, b, b, b); setRGB2(p, bb, bb, bb); setRGB1(p, bbb, bbb, bbb); setRGB3(p, bbbb, bbbb, bbbb); } else if ( t < SCENE_LIGHT_CUTOFF*SPHERE_STEP_TIME ) { // latitude same smooth color + lighting move + dynamic cutoff current_scene = SCENE_LIGHT_CUTOFF; unsigned char b = 255; unsigned char bb = 255; unsigned char bbb = 255; unsigned char bbbb = 255; // light { SVECTOR* l = &sphere_vector[light_move_lat*SPHERE_LONGITUDE+light_move_long]; SVECTOR* v = &sphere_vector[la*SPHERE_LONGITUDE+lo]; SVECTOR* vv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo]; SVECTOR* vvv = &sphere_vector[la*SPHERE_LONGITUDE+lo_next]; SVECTOR* vvvv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo_next]; int d = SignalProcessing::dist2(l, v); int dd = SignalProcessing::dist2(l, vv); int ddd = SignalProcessing::dist2(l, vvv); int dddd = SignalProcessing::dist2(l, vvvv); b = (SignalProcessing::max(0, light_dynamic_distance_max2 - d) * b) / light_dynamic_distance_max2; bb = (SignalProcessing::max(0, light_dynamic_distance_max2 - dd) * bb) / light_dynamic_distance_max2; bbb = (SignalProcessing::max(0, light_dynamic_distance_max2 - ddd) * bbb) / light_dynamic_distance_max2; bbbb = (SignalProcessing::max(0, light_dynamic_distance_max2 - dddd) * bbbb) / light_dynamic_distance_max2; } // smooth if ( t < (SCENE_LIGHT_CUTOFF-1)*SPHERE_STEP_TIME + SPHERE_TRANSITION_STEP ) { int d= (t%SPHERE_TRANSITION_STEP); b = (b * d + p->r0 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP; bb = (bb * d + p->r2 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP; bbb = (bbb * d + p->r1 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP; bbbb = (bbbb * d + p->r3 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP; } setRGB0(p, b, b, b); setRGB2(p, bb, bb, bb); setRGB1(p, bbb, bbb, bbb); setRGB3(p, bbbb, bbbb, bbbb); } else if ( t < SCENE_ZOOM*SPHERE_STEP_TIME ) { // latitude same smooth color + lighting move + dynamic cutoff + zoom current_scene = SCENE_ZOOM; unsigned char b = 255; unsigned char bb = 255; unsigned char bbb = 255; unsigned char bbbb = 255; // light { SVECTOR* l = &sphere_vector[light_move_lat*SPHERE_LONGITUDE+light_move_long]; SVECTOR* v = &sphere_vector[la*SPHERE_LONGITUDE+lo]; SVECTOR* vv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo]; SVECTOR* vvv = &sphere_vector[la*SPHERE_LONGITUDE+lo_next]; SVECTOR* vvvv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo_next]; int d = SignalProcessing::dist2(l, v); int dd = SignalProcessing::dist2(l, vv); int ddd = SignalProcessing::dist2(l, vvv); int dddd = SignalProcessing::dist2(l, vvvv); b = (SignalProcessing::max(0, light_dynamic_distance_max2 - d) * b) / light_dynamic_distance_max2; bb = (SignalProcessing::max(0, light_dynamic_distance_max2 - dd) * bb) / light_dynamic_distance_max2; bbb = (SignalProcessing::max(0, light_dynamic_distance_max2 - ddd) * bbb) / light_dynamic_distance_max2; bbbb = (SignalProcessing::max(0, light_dynamic_distance_max2 - dddd) * bbbb) / light_dynamic_distance_max2; } // smooth if ( t < (SCENE_ZOOM-1)*SPHERE_STEP_TIME + SPHERE_TRANSITION_STEP ) { int d= (t%SPHERE_TRANSITION_STEP); b = (b * d + p->r0 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP; bb = (bb * d + p->r2 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP; bbb = (bbb * d + p->r1 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP; bbbb = (bbbb * d + p->r3 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP; } setRGB0(p, b, b, b); setRGB2(p, bb, bb, bb); setRGB1(p, bbb, bbb, bbb); setRGB3(p, bbbb, bbbb, bbbb); } else { // smooth bande move + lighting move current_scene = SCENE_LIGHT_SINUS_WAVE; const int LIGHT_DISTANCE_MAX = 50; const int LIGHT_DISTANCE_MAX2 = LIGHT_DISTANCE_MAX * LIGHT_DISTANCE_MAX; const int NB_COLOR = 5; unsigned char b = (255 * (((la+off)%SPHERE_LATITUDE)%NB_COLOR)) / (NB_COLOR-1); unsigned char bb = (255 * (((la+1+off)%SPHERE_LATITUDE)%NB_COLOR)) / (NB_COLOR-1); unsigned char bbb = (255 * (((la+off)%SPHERE_LATITUDE)%NB_COLOR)) / (NB_COLOR-1); unsigned char bbbb = (255 * (((la+1+off)%SPHERE_LATITUDE)%NB_COLOR)) / (NB_COLOR-1); // light { SVECTOR* l = &sphere_vector[light_move_lat*SPHERE_LONGITUDE+light_move_long]; SVECTOR* v = &sphere_vector[la*SPHERE_LONGITUDE+lo]; SVECTOR* vv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo]; SVECTOR* vvv = &sphere_vector[la*SPHERE_LONGITUDE+lo_next]; SVECTOR* vvvv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo_next]; int d = SignalProcessing::dist2(l, v); int dd = SignalProcessing::dist2(l, vv); int ddd = SignalProcessing::dist2(l, vvv); int dddd = SignalProcessing::dist2(l, vvvv); b = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - d) * b) / LIGHT_DISTANCE_MAX2; bb = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - dd) * bb) / LIGHT_DISTANCE_MAX2; bbb = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - ddd) * bbb) / LIGHT_DISTANCE_MAX2; bbbb = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - dddd) * bbbb) / LIGHT_DISTANCE_MAX2; } // smooth if ( t < 5*SPHERE_STEP_TIME + SPHERE_TRANSITION_STEP ) { int d= (t%SPHERE_TRANSITION_STEP); b = (b * d + p->r0 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP; bb = (bb * d + p->r2 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP; bbb = (bbb * d + p->r1 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP; bbbb = (bbbb * d + p->r3 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP; } setRGB0(p, b, b, b); setRGB2(p, bb, bb, bb); setRGB1(p, bbb, bbb, bbb); setRGB3(p, bbbb, bbbb, bbbb); } } } display(); t += dt; } MemoryManager::free(sphere_vector); MemoryManager::free(poly_sphere); }
void ExtrudeMod::BuildMeshFromShape(TimeValue t,ModContext &mc, ObjectState * os, Mesh &mesh, BOOL simple) { BOOL texturing; pblock->GetValue(PB_MAPPING, TimeValue(0), texturing, FOREVER); BOOL genMatIDs; pblock->GetValue(PB_GEN_MATIDS, TimeValue(0), genMatIDs, FOREVER); BOOL useShapeIDs; pblock->GetValue(PB_USE_SHAPEIDS, TimeValue(0), useShapeIDs, FOREVER); BOOL smooth; pblock->GetValue(PB_SMOOTH, TimeValue(0), smooth, FOREVER); ShapeObject *shape = (ShapeObject *)os->obj; float amount; int levels,capStart,capEnd,capType; pblock->GetValue(PB_AMOUNT,t,amount,FOREVER); if(simple) { levels = 1; capStart = capEnd = FALSE; } else { pblock->GetValue(PB_SEGS,t,levels,FOREVER); if (levels<1) levels = 1; pblock->GetValue(PB_CAPSTART,t,capStart,FOREVER); pblock->GetValue(PB_CAPEND,t,capEnd,FOREVER); } pblock->GetValue(PB_CAPTYPE,t,capType,FOREVER); LimitValue(amount, -1000000.0f, 1000000.0f); // Get the basic dimension stuff float zSize = (float)fabs(amount); float baseZ = 0.0f; if(amount < 0.0f) baseZ = amount; // Make the shape convert itself to a PolyShape -- This makes our mesh conversion MUCH easier! PolyShape pShape; shape->MakePolyShape(t, pShape); ShapeHierarchy hier; pShape.OrganizeCurves(t, &hier); // Need to flip the reversed curves in the shape! pShape.Reverse(hier.reverse); int polys = pShape.numLines; int levelVerts = 0, levelFaces = 0, levelTVerts = 0; int verts = 0, faces = 0, tVerts = 0; int poly, piece; BOOL anyClosed = FALSE; for(poly = 0; poly < polys; ++poly) { PolyLine &line = pShape.lines[poly]; if(!line.numPts) continue; if(line.IsClosed()) { anyClosed = TRUE; levelTVerts++; } levelVerts += line.numPts; levelTVerts += line.numPts; levelFaces += (line.Segments() * 2); } int vertsPerLevel = levelVerts; int numLevels = levels; verts = levelVerts * (levels + 1); tVerts = levelTVerts * (levels + 1); faces = levelFaces * levels; mesh.setNumVerts(verts); mesh.setNumFaces(faces); if(texturing) { mesh.setNumTVerts(tVerts); mesh.setNumTVFaces(faces); } // Create the vertices! int vert = 0; int tvertex = 0; int level; Point3 offset1, offset2; for(poly = 0; poly < polys; ++poly) { PolyLine &line = pShape.lines[poly]; if(!line.numPts) continue; if(texturing) { //DebugPrint(_T("Texture Verts:\n")); BOOL usePhysUVs = GetUsePhysicalScaleUVs(); int tp; int texPts = line.numPts + (line.IsClosed() ? 1 : 0); float *texPt = new float [texPts]; float lastPt = (float)(texPts - 1); float cumLen = 0.0f; float totLen = line.CurveLength(); Point3 prevPt = line.pts[0].p; for(tp = 0; tp < texPts; ++tp) { int ltp = tp % line.numPts; if(tp == (texPts - 1)) texPt[tp] = usePhysUVs ? totLen : 1.0f; else { Point3 &pt = line.pts[ltp].p; cumLen += Length(pt - prevPt); if (usePhysUVs) texPt[tp] = cumLen; else texPt[tp] = cumLen / totLen; prevPt = pt; } } float flevels = (float)levels; for(level = 0; level <= levels; ++level) { float tV = (float)level / flevels; float vScale = usePhysUVs ? amount : 1.0f; for(tp = 0; tp < texPts; ++tp) { mesh.setTVert(tvertex++, UVVert(texPt[tp], vScale*tV, 0.0f)); } } delete [] texPt; } int lverts = line.numPts; for(level = 0; level <= levels; ++level) { Point3 offset = Point3(0.0f, 0.0f, baseZ + (float)level / (float)levels * zSize); if(level == 0) offset1 = offset; else if(level == levels) offset2 = offset; for(int v = 0; v < lverts; ++v) { line.pts[v].aux = vert; // Gives the capper this vert's location in the mesh! mesh.setVert(vert++, line.pts[v].p + offset); } } } assert(vert == verts); // If capping, do it! if(anyClosed && (capStart || capEnd)) { MeshCapInfo capInfo; pShape.MakeCap(t, capInfo, capType); // Build information for capping MeshCapper capper(pShape); if(capStart) { vert = 0; for(poly = 0; poly < polys; ++poly) { PolyLine &line = pShape.lines[poly]; if(!line.numPts) continue; MeshCapPoly &capline = capper[poly]; int lverts = line.numPts; for(int v = 0; v < lverts; ++v) capline.SetVert(v, vert++); // Gives this vert's location in the mesh! vert += lverts * levels; } // Create a work matrix for grid capping Matrix3 gridMat = TransMatrix(offset1); int oldFaces = mesh.numFaces; capper.CapMesh(mesh, capInfo, TRUE, 16, &gridMat, genMatIDs ? -1 : 0); // If texturing, create the texture faces and vertices if(texturing) MakeMeshCapTexture(mesh, Inverse(gridMat), oldFaces, mesh.numFaces, GetUsePhysicalScaleUVs()); } if(capEnd) { int baseVert = 0; for(poly = 0; poly < polys; ++poly) { PolyLine &line = pShape.lines[poly]; if(!line.numPts) continue; MeshCapPoly &capline = capper[poly]; int lverts = line.numPts; vert = baseVert + lverts * levels; for(int v = 0; v < lverts; ++v) capline.SetVert(v, vert++); // Gives this vert's location in the mesh! baseVert += lverts * (levels + 1); } // Create a work matrix for grid capping Matrix3 gridMat = TransMatrix(offset2); int oldFaces = mesh.numFaces; capper.CapMesh(mesh, capInfo, FALSE, 16, &gridMat, genMatIDs ? -1 : 0); // If texturing, create the texture faces and vertices if(texturing) MakeMeshCapTexture(mesh, Inverse(gridMat), oldFaces, mesh.numFaces, GetUsePhysicalScaleUVs()); } } // Create the faces! int face = 0; int TVface = 0; int baseVert = 0; int baseTVert = 0; for(poly = 0; poly < polys; ++poly) { PolyLine &line = pShape.lines[poly]; if(!line.numPts) continue; int pieces = line.Segments(); int closed = line.IsClosed(); int segVerts = pieces + ((closed) ? 0 : 1); int segTVerts = pieces + 1; for(level = 0; level < levels; ++level) { int sm = 0; // Initial smoothing group BOOL firstSmooth = (line.pts[0].flags & POLYPT_SMOOTH) ? TRUE : FALSE; for(piece = 0; piece < pieces; ++piece) { int v1 = baseVert + piece; int v2 = baseVert + ((piece + 1) % segVerts); int v3 = v1 + segVerts; int v4 = v2 + segVerts; // If the vertex is not smooth, go to the next group! BOOL thisSmooth = line.pts[piece].flags & POLYPT_SMOOTH; MtlID mtl = useShapeIDs ? line.pts[piece].GetMatID() : 2; if(piece > 0 && !thisSmooth) { sm++; if(sm > 2) sm = 1; } DWORD smoothGroup = 1 << sm; // Advance to the next smoothing group right away if(sm == 0) sm++; // Special case for smoothing from first segment if(piece == 1 && thisSmooth) smoothGroup |= 1; // Special case for smoothing from last segment if((piece == pieces - 1) && firstSmooth) smoothGroup |= 1; mesh.faces[face].setEdgeVisFlags(1,1,0); mesh.faces[face].setSmGroup(smooth ? smoothGroup : 0); mesh.faces[face].setMatID(genMatIDs ? mtl : 0); mesh.faces[face++].setVerts(v1, v2, v4); mesh.faces[face].setEdgeVisFlags(0,1,1); mesh.faces[face].setSmGroup(smooth ? smoothGroup : 0); mesh.faces[face].setMatID(genMatIDs ? mtl : 0); mesh.faces[face++].setVerts(v1, v4, v3); //DebugPrint(_T("BV:%d V:%d v1:%d v2:%d v3:%d v4:%d\n"),baseVert, vert, v1, v2, v3, v4); if(texturing) { int tv1 = baseTVert + piece; int tv2 = tv1 + 1; int tv3 = tv1 + segTVerts; int tv4 = tv2 + segTVerts; mesh.tvFace[TVface++].setTVerts(tv1, tv2, tv4); mesh.tvFace[TVface++].setTVerts(tv1, tv4, tv3); } } baseVert += segVerts; baseTVert += segTVerts; } baseVert += segVerts; // Increment to next poly start (skips last verts of this poly) baseTVert += segTVerts; } assert(face == faces); mesh.InvalidateGeomCache(); }
void ExtrudeMod::BuildPatchFromShape(TimeValue t,ModContext &mc, ObjectState * os, PatchMesh &pmesh) { ShapeObject *shape = (ShapeObject *)os->obj; float amount; int levels,capStart,capEnd,capType; pblock->GetValue(PB_AMOUNT,t,amount,FOREVER); pblock->GetValue(PB_SEGS,t,levels,FOREVER); if (levels<1) levels = 1; pblock->GetValue(PB_CAPSTART,t,capStart,FOREVER); pblock->GetValue(PB_CAPEND,t,capEnd,FOREVER); pblock->GetValue(PB_CAPTYPE,t,capType,FOREVER); BOOL texturing; pblock->GetValue(PB_MAPPING, TimeValue(0), texturing, FOREVER); BOOL genMatIDs; pblock->GetValue(PB_GEN_MATIDS, TimeValue(0), genMatIDs, FOREVER); BOOL useShapeIDs; pblock->GetValue(PB_USE_SHAPEIDS, TimeValue(0), useShapeIDs, FOREVER); BOOL smooth; pblock->GetValue(PB_SMOOTH, TimeValue(0), smooth, FOREVER); LimitValue(amount, -1000000.0f, 1000000.0f); // Get the basic dimension stuff float zSize = (float)fabs(amount); float baseZ = 0.0f; if(amount < 0.0f) baseZ = amount; // If the shape can convert itself to a BezierShape, have it do so! BezierShape bShape; if(shape->CanMakeBezier()) shape->MakeBezier(t, bShape); else { PolyShape pShape; shape->MakePolyShape(t, pShape); bShape = pShape; // UGH -- Convert it from a PolyShape -- not good! } //DebugPrint(_T("Extrude organizing shape\n")); ShapeHierarchy hier; bShape.OrganizeCurves(t, &hier); // Need to flip the reversed polys... bShape.Reverse(hier.reverse); // ...and tell the hierarchy they're no longer reversed! hier.reverse.ClearAll(); // Our shapes are now organized for patch-making -- Let's do the sides! int polys = bShape.splineCount; int poly, knot; int levelVerts = 0, levelVecs = 0, levelPatches = 0, nverts = 0, nvecs = 0, npatches = 0; int TVlevels = levels + 1, levelTVerts = 0, ntverts = 0, ntpatches = 0; BOOL anyClosed = FALSE; for(poly = 0; poly < polys; ++poly) { Spline3D *spline = bShape.splines[poly]; if(!spline->KnotCount()) continue; if(spline->Closed()) anyClosed = TRUE; levelVerts += spline->KnotCount(); levelTVerts += (spline->Segments() + 1); levelVecs += (spline->Segments() * 2); levelPatches += spline->Segments(); } nverts = levelVerts * (levels + 1); npatches = levelPatches * levels; nvecs = (levelVecs * (levels + 1)) + levels * levelVerts * 2 + npatches * 4; if(texturing) { ntverts = levelTVerts * TVlevels; ntpatches = npatches; } pmesh.setNumVerts(nverts); pmesh.setNumVecs(nvecs); pmesh.setNumPatches(npatches); pmesh.setNumTVerts(ntverts); pmesh.setNumTVPatches(ntpatches); // Create the vertices! int vert = 0; int level; Point3 offset1, offset2; for(poly = 0; poly < polys; ++poly) { Spline3D *spline = bShape.splines[poly]; if(!spline->KnotCount()) continue; int knots = spline->KnotCount(); for(level = 0; level <= levels; ++level) { Point3 offset = Point3(0.0f, 0.0f, baseZ + (float)level / (float)levels * zSize); if(level == 0) offset1 = offset; else if(level == levels) offset2 = offset; for(knot = 0; knot < knots; ++knot) { Point3 p = spline->GetKnotPoint(knot); pmesh.setVert(vert++, p + offset); } } } assert(vert == nverts); BOOL usePhysUVs = GetUsePhysicalScaleUVs(); // Maybe create the texture vertices if(texturing) { int tvert = 0; int level; for(poly = 0; poly < polys; ++poly) { Spline3D *spline = bShape.splines[poly]; if(!spline->KnotCount()) continue; // Make it a polyline PolyLine pline; spline->MakePolyLine(pline, 10); int knots = spline->KnotCount(); for(level = 0; level < TVlevels; ++level) { float tV = (float)level / (float)(TVlevels - 1); float vScale = usePhysUVs ? amount : 1.0f; int lverts = pline.numPts; int tp = 0; int texPts = spline->Segments() + 1; float cumLen = 0.0f; float totLen = pline.CurveLength(); float uScale = usePhysUVs ? totLen : 1.0f; Point3 prevPt = pline.pts[0].p; int plix = 0; while(tp < texPts) { Point3 &pt = pline[plix].p; cumLen += Length(pt - prevPt); prevPt = pt; if(pline[plix].flags & POLYPT_KNOT) { float tU; if(tp == (texPts - 1)) tU = 1.0f; else tU = cumLen / totLen; pmesh.setTVert(tvert++, UVVert(uScale*tU, vScale*tV, 0.0f)); tp++; } plix = (plix + 1) % pline.numPts; } } } assert(tvert == ntverts); } // Create the vectors! int seg; int vec = 0; for(poly = 0; poly < polys; ++poly) { Spline3D *spline = bShape.splines[poly]; if(!spline->KnotCount()) continue; int segs = spline->Segments(); int knots = spline->KnotCount(); // First, the vectors on each level for(level = 0; level <= levels; ++level) { Point3 offset = Point3(0.0f, 0.0f, baseZ + (float)level / (float)levels * zSize); for(seg = 0; seg < segs; ++seg) { int seg2 = (seg + 1) % knots; if(spline->GetLineType(seg) == LTYPE_CURVE) { Point3 p = spline->GetOutVec(seg); pmesh.setVec(vec++, p + offset); p = spline->GetInVec(seg2); pmesh.setVec(vec++, p + offset); } else { Point3 p = spline->InterpBezier3D(seg, 0.333333f); pmesh.setVec(vec++, p + offset); p = spline->InterpBezier3D(seg, 0.666666f); pmesh.setVec(vec++, p + offset); } } } // Now, the vectors between the levels int baseVec = vec; for(level = 0; level < levels; ++level) { Point3 offsetA = Point3(0.0f, 0.0f, baseZ + (float)level / (float)levels * zSize); Point3 offsetB = Point3(0.0f, 0.0f, baseZ + (float)(level + 1) / (float)levels * zSize); Point3 offset1 = offsetA + (offsetB - offsetA) * 0.333333333f; Point3 offset2 = offsetA + (offsetB - offsetA) * 0.666666666f; for(knot = 0; knot < knots; ++knot) { Point3 p = spline->GetKnotPoint(knot); pmesh.setVec(vec++, p + offset1); pmesh.setVec(vec++, p + offset2); } } } // Create the patches! int np = 0; int baseVert = 0; int baseVec = 0; for(poly = 0; poly < polys; ++poly) { Spline3D *spline = bShape.splines[poly]; if(!spline->KnotCount()) continue; int knots = spline->KnotCount(); int segs = spline->Segments(); int baseVec1 = baseVec; // Base vector index for this level int baseVec2 = baseVec + segs * 2 * (levels + 1); // Base vector index for between levels for(level = 0; level < levels; ++level) { int sm = 0; BOOL firstSmooth = (spline->GetLineType(0) == LTYPE_CURVE && spline->GetLineType(segs-1) == LTYPE_CURVE && (spline->GetKnotType(0) == KTYPE_AUTO || spline->GetKnotType(0) == KTYPE_BEZIER)) ? TRUE : FALSE; for(seg = 0; seg < segs; ++seg, vec += 4) { int prevseg = (seg + segs - 1) % segs; int seg2 = (seg + 1) % knots; int a,b,c,d,ab,ba,bc,cb,cd,dc,da,ad; MtlID mtl = useShapeIDs ? spline->GetMatID(seg) : 2; a = baseVert + seg; b = baseVert + seg2; c = b + knots; d = a + knots; ab = baseVec1 + seg * 2; ba = ab + 1; bc = baseVec2 + seg2 * 2; cb = bc + 1; cd = ba + (segs * 2); dc = ab + (segs * 2); da = baseVec2 + seg * 2 + 1; ad = da - 1; //DebugPrint(_T("Making patch %d: %d (%d %d) %d (%d %d) %d (%d %d) %d (%d %d)\n"),np, a, ab, ba, b, bc, cb, c, cd, dc, d, da, ad); // If the vertex is not smooth, go to the next group! if(seg > 0 && !(spline->GetLineType(prevseg) == LTYPE_CURVE && spline->GetLineType(seg) == LTYPE_CURVE && (spline->GetKnotType(seg) == KTYPE_AUTO || spline->GetKnotType(seg) == KTYPE_BEZIER))) { sm++; if(sm > 2) sm = 1; } DWORD smoothGroup = 1 << sm; if(seg == segs - 1 && firstSmooth) { smoothGroup |= 1; } pmesh.MakeQuadPatch(np, a, ab, ba, b, bc, cb, c, cd, dc, d, da, ad, vec, vec+1, vec+2, vec+3, smooth ? smoothGroup : 0); pmesh.setPatchMtlIndex(np++, genMatIDs ? mtl : 0); } baseVert += knots; baseVec1 += (segs * 2); baseVec2 += (knots * 2); } baseVert += knots; baseVec += (segs * 2 * (levels + 1) + knots * 2 * levels); } assert(vec == nvecs); assert(np == npatches); // Maybe create the texture patches! if(texturing) { int ntp = 0; int baseTVert = 0; for(poly = 0; poly < polys; ++poly) { Spline3D *spline = bShape.splines[poly]; if(!spline->KnotCount()) continue; int pknots = spline->Segments() + 1; int pverts = pknots * TVlevels; int segs = spline->Segments(); for(level = 0; level < levels; ++level) { for(seg = 0; seg < segs; ++seg) { int prevseg = (seg + segs - 1) % segs; int seg2 = seg + 1; int a,b,c,d; a = baseTVert + seg; b = baseTVert + seg2; c = b + pknots; d = a + pknots; TVPatch &tp = pmesh.getTVPatch(ntp++); tp.setTVerts(a, b, c, d); } baseTVert += pknots; } baseTVert += pknots; } assert(ntp == ntpatches); } // If capping, do it! if(anyClosed && (capStart || capEnd)) { PatchCapInfo capInfo; bShape.MakeCap(t, capInfo); // Build information for capping PatchCapper capper(bShape); if(capStart) { vert = 0; int baseVec = 0; for(poly = 0; poly < polys; ++poly) { Spline3D *spline = bShape.splines[poly]; if(!spline->KnotCount()) continue; PatchCapPoly &capline = capper[poly]; int lverts = spline->KnotCount(); for(int v = 0; v < lverts; ++v) capline.SetVert(v, vert++); // Gives this vert's location in the mesh! vert += lverts * levels; vec = baseVec; int lvecs = spline->Segments() * 2; for(int v = 0; v < lvecs; ++v) capline.SetVec(v, vec++); // Gives this vec's location in the mesh! baseVec += lvecs * (levels + 1) + spline->KnotCount() * levels * 2; } // Create a work matrix for capping Matrix3 mat = TransMatrix(offset1); int oldPatches = pmesh.numPatches; capper.CapPatchMesh(pmesh, capInfo, TRUE, 16, &mat, genMatIDs ? -1 : 0); // If texturing, create the texture patches and vertices if(texturing) MakePatchCapTexture(pmesh, Inverse(mat), oldPatches, pmesh.numPatches, usePhysUVs); } if(capEnd) { int baseVert = 0; int baseVec = 0; for(poly = 0; poly < polys; ++poly) { Spline3D *spline = bShape.splines[poly]; if(!spline->KnotCount()) continue; PatchCapPoly &capline = capper[poly]; int lverts = spline->KnotCount(); int vert = baseVert + lverts * levels; for(int v = 0; v < lverts; ++v) capline.SetVert(v, vert++); // Gives this vert's location in the mesh! baseVert += lverts * (levels + 1); int lvecs = spline->Segments()*2; int vec = baseVec + lvecs * levels; for(int v = 0; v < lvecs; ++v) capline.SetVec(v, vec++); // Gives this vec's location in the mesh! baseVec += lvecs * (levels + 1) + spline->KnotCount() * levels * 2; } // Create a work matrix for grid capping Matrix3 mat = TransMatrix(offset2); int oldPatches = pmesh.numPatches; capper.CapPatchMesh(pmesh, capInfo, FALSE, 16, &mat, genMatIDs ? -1 : 0); // If texturing, create the texture patches and vertices if(texturing) MakePatchCapTexture(pmesh, Inverse(mat), oldPatches, pmesh.numPatches, usePhysUVs); } } //watje new mapping if(texturing) { if (ver < 4) { for (int i = 0; i < pmesh.numPatches; i++) pmesh.patches[i].flags |= PATCH_LINEARMAPPING; } } // Ready the patch representation! if( !pmesh.buildLinkages() ) { assert(0); } pmesh.computeInteriors(); }
//*************************************************************************** // Calculate ambient or diffuse color at each vertex. // Pass in TRUE as the "diffuse" parameter to calculate the diffuse color. // If FALSE is passed in, ambient color is calculated. //*************************************************************************** BOOL calcMixedVertexColors(INode* node, TimeValue t, int lightModel, ColorTab& vxColTab, EvalColProgressCallback* fn) { ObjectState ostate; BOOL deleteTri; Mesh* mesh; SContext sc; DefaultLight dl1, dl2; MtlBaseLib mtls; Matrix3 tm; sc.SetNodeAndTime(node, t); tm = sc.tmAfterWSM; TriObject* tri = GetTriObjectFromNode(node, t, deleteTri); // We will only work on GeomObjects if (!tri) { return FALSE; } // Get the mesh from the object mesh = &tri->GetMesh(); if (!mesh) { return FALSE; } // If the node doesn't have a material attached, // we create a dummy material. Mtl* mtl = node->GetMtl(); if (!mtl) { mtl = new DumMtl(Color(node->GetWireColor())); } mesh->buildRenderNormals(); vxColTab.ZeroCount(); vxColTab.Shrink(); sc.SetMesh(mesh); sc.CalcBoundObj(); // Add the material to the list mtls.AddMtl(mtl); // Setup ambient light if (lightModel == LIGHT_AMBIENT) { sc.SetAmbientLight(Color(1.0f, 1.0f, 1.0f)); } else { sc.SetAmbientLight(Color(0.0f, 0.0f, 0.0f)); } // If we're using the real lights, we need to find them first if (lightModel == LIGHT_SCENELIGHT) { AddSceneLights(&sc, &mtls); // Add default lights if there are no lights in the scene if (sc.lightTab.Count() == 0) { dl1.ls.intens = 1.0f; dl1.ls.color = Color(0.8f, 0.8f, 0.8f); dl1.ls.type = OMNI_LGT; dl1.tm = TransMatrix(1000.0f * Point3(-900.0f, -1000.0f, 1500.0f)); dl2.ls.intens = 1.0f; dl2.ls.color = Color(0.8f, 0.8f, 0.8f); dl2.ls.type = OMNI_LGT; dl2.tm = TransMatrix(-1000.0f * Point3(-900.0f, -1000.0f, 1500.0f)); sc.AddLight(new LightInfo(&dl1)); sc.AddLight(new LightInfo(&dl2)); } sc.SetAmbientLight(GetCOREInterface()->GetAmbient(t, FOREVER)); } sc.UpdateLights(); // Update material mtl->Update(t, FOREVER); int numVerts = mesh->numVerts; for (unsigned int v = 0; v < (unsigned)numVerts; v++) { if (fn) { if (fn->progress(float(v)/float(numVerts))) { if (deleteTri) { delete tri; } mtls.Empty(); if (mtl->ClassID() == DUMMTL_CLASS_ID) { delete mtl; } // What to return here is up for discussion. // 1) We are aborting so FALSE might be in order. // 2) We have calculated some colors. Let's use what we've got so far. return TRUE; } } // Create a new entry Color* vxCol = new Color; Point3 tmpCol(0.0f, 0.0f, 0.0f); int numShades = 0; BitArray faceList; faceList.SetSize(mesh->numFaces, 0); // Get vertex normal // We also pass in a BitArray that will be filled in with // to inform us to which faces this vertex belongs. // We could do this manually, but we need to do it to get // the vertex normal anyway so this is done to speed things // up a bit. Point3 vxNormal = interpVertexNormal(mesh, tm, v, faceList); Point3 viewDir = -vxNormal; Point3 viewPoint = tm*mesh->verts[v] + 5.0f*vxNormal; Point3 lightPos = viewPoint; Point3 viewTarget = tm*mesh->verts[v]; // We now have a viewpoint and a view target. // Now we just have to shade this point on the mesh in order // to get it's color. // Note: // Since materials are assigned on Face basis we need to render each // vertex as many times as it has connecting faces. // the colors collected are mixed to get the resulting // color at each vertex. for (int nf = 0; nf < faceList.GetSize(); nf++) { if (faceList[nf]) { // render vertex for this face. sc.SetViewPoint(viewPoint); sc.SetTargetPoint(viewTarget); sc.SetViewDir(viewDir); sc.SetFaceNum(nf); Face* f = &mesh->faces[nf]; sc.SetMtlNum(f->getMatID()); sc.CalcNormals(); // Setup the barycentric coordinate if (mesh->faces[nf].v[0] == v) sc.SetBaryCoord(Point3(1.0f, 0.0f, 0.0f)); else if (mesh->faces[nf].v[1] == v) sc.SetBaryCoord(Point3(0.0f, 1.0f, 0.0f)); else if (mesh->faces[nf].v[2] == v) sc.SetBaryCoord(Point3(0.0f, 0.0f, 1.0f)); // Use diffuse color instead of ambient // The only difference is that we create a special light // located at the viewpoint and we set the ambient light to black. if (lightModel == LIGHT_DIFFUSE) { dl1.ls.intens = 1.0f; dl1.ls.color = Color(0.8f, 0.8f, 0.8f); dl1.ls.type = OMNI_LGT; dl1.tm = TransMatrix(lightPos); sc.ClearLights(); sc.AddLight(new LightInfo(&dl1)); sc.UpdateLights(); } // Shade the vertex mtl->Shade(sc); tmpCol.x += sc.out.c.r; tmpCol.y += sc.out.c.g; tmpCol.z += sc.out.c.b; numShades++; } } // The color mixes. We just add the colors together and // then divide with as many colors as we added. if (numShades > 0) { tmpCol = tmpCol / (float)numShades; } vxCol->r = tmpCol.x; vxCol->g = tmpCol.y; vxCol->b = tmpCol.z; vxCol->ClampMinMax(); // Append the Color to the table. If the array needs // to be realloc'ed, allocate extra space for 100 points. vxColTab.Append(1, &vxCol, 100); } // Some objects gives us a temporary mesh that we need to delete afterwards. if (deleteTri) { delete tri; } mtls.Empty(); if (mtl->ClassID() == DUMMTL_CLASS_ID) { delete mtl; } return TRUE; }
FloatArray Quadr::ComputeStress() { const double a = 1 + sqrt(3) / 2, b = -1.0 / 2, c = 1 - sqrt(3) / 2; FloatMatrix TransMatrix(4, 4); TransMatrix.at(0, 0) = a; TransMatrix.at(0, 1) = b; TransMatrix.at(0, 2) = c; TransMatrix.at(0, 3) = b; TransMatrix.at(1, 0) = b; TransMatrix.at(1, 1) = a; TransMatrix.at(1, 2) = b; TransMatrix.at(1, 3) = c; TransMatrix.at(2, 0) = c; TransMatrix.at(2, 1) = b; TransMatrix.at(2, 2) = a; TransMatrix.at(2, 3) = b; TransMatrix.at(3, 0) = b; TransMatrix.at(3, 1) = c; TransMatrix.at(3, 2) = b; TransMatrix.at(3, 3) = a; Strain.Clear(); GaussPoint B; FloatArray Coor; FloatArray TransTemp(4); Coor.SetSize(2); Coor.at(0) = 0; Coor.at(1) = 0; B.Init(0, Coor); ComputeJacobi(B); BMatrixBig = ComputeBMatrix(); //BMatrixBig.Print(); //Displacement.Print(); Strain = BMatrixBig.Mult(Displacement); Stress = DMatrix.Mult(Strain); for (int inode = 0; inode < 4; inode++) { Coor.at(0) = P4ksicor[inode]; Coor.at(1) = P4etacor[inode]; B.Init(0, Coor); ComputeJacobi(B); BMatrixBig = ComputeBMatrix(); GaussStrain[inode] = BMatrixBig.Mult(Displacement); GaussStress[inode] = DMatrix.Mult(Strain); //GaussStrain[inode].Print(); } for (int i = 0; i < 3; i++) { for (int j = 0; j < 4; j++) { TransTemp.at(j) = GaussStrain[j].at(i); } TransTemp = TransMatrix.Mult(TransTemp); for (int j = 0; j < 4; j++) { NodeStrain[j].at(i) = TransTemp.at(j); } for (int j = 0; j < 4; j++) { TransTemp.at(j) = GaussStress[j].at(i); } TransTemp = TransMatrix.Mult(TransTemp); for (int j = 0; j < 4; j++) { NodeStress[j].at(i) = TransTemp.at(j); } } return NULL; }