void GR2ImportImpl::ImportAnimations() { if (info.Animations.size() == 0 || !enableAnimation) return; ClearAnimation(); //for (int anim=0, nanim=info.Animations.size(); anim<nanim; ++anim) //{ // Animation& anim = (*info.Animations[anim]); //} Interval range; range.SetInstant(0); float time = FrameToTime(0); for (int ianim=0, nanim=info.Animations.size(); ianim<nanim; ++ianim) { Animation& anim = (*info.Animations[ianim]); TimeValue animEnd = TimeToFrame(time + anim.Duration); if (animEnd > range.End()) range.SetEnd(animEnd); // Build Default Time int nkeys = anim.Duration / anim.TimeStep; GR2Array<granny_real32> defaultKeys(nkeys); granny_real32 curtime = 0.0f; for (int ikeys=0; ikeys<nkeys; ++ikeys, curtime += anim.TimeStep) defaultKeys[ikeys] = curtime; for (int grp=0, ngrp=anim.TrackGroups.size(); grp<ngrp; ++grp) { TrackGroup& group = (*anim.TrackGroups[grp]); if (INode *root = o->gi->GetINodeByName(group.Name)) { Point3 s( group.InitialPlacement.Scale.m[0][0] , group.InitialPlacement.Scale.m[1][1] , group.InitialPlacement.Scale.m[2][2] ); for (int itrack=0, ntrack=group.TransformTracks.size(); itrack<ntrack; ++itrack) { TransformTrack& track = group.TransformTracks[itrack]; if (INode *node = o->gi->GetINodeByName(track.Name)) { if (Control *c = node->GetTMController()) { DWORD flags=INHERIT_ALL; c->SetInheritanceFlags(INHERIT_ALL,FALSE); ImportPosition(c, track, time, defaultKeys); ImportRotation(c, track, time, defaultKeys); ImportScale(c, track, time, defaultKeys); } } } Matrix3 rot(true); group.InitialPlacement.Rotation.MakeMatrix(rot); Matrix3 m = TransMatrix(group.InitialPlacement.Origin) * Inverse(rot) * ScaleMatrix( s ); PosRotScaleNode(root, m); // TODO: Move to initial transform } } } o->gi->SetAnimRange(range); }
void AudioPositionControl::GetValueLocalTime(TimeValue t, void *val, Interval &valid, GetSetMethod method) { valid.SetInstant(t); // This controller is always changing. // Multiply the target-base with sample and add base *((Point3*)val) = basePoint + (targetPoint - basePoint) * SampleAtTime(t - range.Start(), 0, FALSE); }
void PFTestGoToRotation::UpdatePViewUI(ParamID updateID) const { for(int i=0; i<NumPViewParamMaps(); i++) { IParamMap2* map = GetPViewParamMap(i); map->Invalidate(updateID); Interval currentTimeInterval; currentTimeInterval.SetInstant(GetCOREInterface()->GetTime()); map->Validity() = currentTimeInterval; } }
//+--------------------------------------------------------------------------+ //| From ReferenceMaker | //+--------------------------------------------------------------------------+ void PFOperatorForceSpaceWarp::UpdatePViewUI(IParamBlock2* pblock, ParamID updateID) { for(int i=0; i<NumPViewParamMaps(); i++) { IParamMap2* map = GetPViewParamMap(i); if (pblock != map->GetParamBlock()) continue; map->Invalidate(updateID); Interval currentTimeInterval; currentTimeInterval.SetInstant(GetCOREInterface()->GetTime()); map->Validity() = currentTimeInterval; } }
void LinkTimeControl::GetValueLocalTime(TimeValue t, void *val, Interval &valid, GetSetMethod method) { *(float*)val = 0.0f; if ( !fOwner ) return; const int num = fOwner->GetNumTargets(); if ( num == 0 ) return; for ( int i=1; i<num; ++i ) { if ( fOwner->GetLinkTime( i ) > t ) { *(float*)val = (float)(i-1); return; } } *(float*)val = (float)(num-1); valid.SetInstant(t); }
void ExtrudeMod::ModifyObject(TimeValue t, ModContext &mc, ObjectState * os, INode *node) { //DebugPrint(_T("Extrude modifying object\n")); // Get our personal validity interval... Interval valid = GetValidity(t); // and intersect it with the channels we use as input (see ChannelsUsed) valid &= os->obj->ChannelValidity(t,TOPO_CHAN_NUM); valid &= os->obj->ChannelValidity(t,GEOM_CHAN_NUM); int output; pblock->GetValue(PB_OUTPUT, TimeValue(0), output, FOREVER); switch (output) { case NURBS_OUTPUT: #ifndef NO_NURBS { // Here is where all the fun stuff happens -- GenerateExtrudeSurface fills in the EM, // then we stuff the EditableSurface into the pipeline. ShapeObject *shape = (ShapeObject *)os->obj; float amount; BOOL texturing, genMatIds, useShapeIDs; pblock->GetValue(PB_MAPPING, TimeValue(0), texturing, FOREVER); pblock->GetValue(PB_GEN_MATIDS, TimeValue(0), genMatIds, FOREVER); pblock->GetValue(PB_USE_SHAPEIDS, TimeValue(0), useShapeIDs, FOREVER); int levels,capStart,capEnd,capType; 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); pblock->GetValue(PB_AMOUNT,t,amount,FOREVER); LimitValue(amount, -1000000.0f, 1000000.0f); BOOL suspended = FALSE; if (theHold.Holding()) { theHold.Suspend(); suspended = TRUE; } Object *nobj = CreateNURBSExtrudeShape(ip, GetString(IDS_RB_EXTRUDE), t, shape, amount, capStart, capEnd, capType, texturing, genMatIds, useShapeIDs); if (suspended) { theHold.Resume(); } // We only set geom validity because we preserve animation on clone // and copying other cahnnels causes problems -- SCM 9/2/97 nobj->SetChannelValidity(GEOM_CHAN_NUM, valid); os->obj = nobj; break;} #endif #ifndef NO_PATCHES case PATCH_OUTPUT: { // Here is where all the fun stuff happens -- BuildPatchFromShape fills in the PatchObject's patch mesh, // then we stuff the PatchObject into the pipeline. PatchObject *pat = new PatchObject; BuildPatchFromShape(t, mc, os, pat->patch); pat->SetChannelValidity(TOPO_CHAN_NUM, valid); pat->SetChannelValidity(GEOM_CHAN_NUM, valid); pat->SetChannelValidity(TEXMAP_CHAN_NUM, valid); pat->SetChannelValidity(MTL_CHAN_NUM, valid); pat->SetChannelValidity(SELECT_CHAN_NUM, valid); pat->SetChannelValidity(SUBSEL_TYPE_CHAN_NUM, valid); pat->SetChannelValidity(DISP_ATTRIB_CHAN_NUM, valid); os->obj = pat; break;} #endif // NO_PATCHES case MESH_OUTPUT: { // Here is where all the fun stuff happens -- BuildMeshFromShape fills in the TriObject's mesh, // then we stuff the TriObj into the pipeline. TriObject *tri = CreateNewTriObject(); BuildMeshFromShape(t, mc, os, tri->GetMesh()); tri->SetChannelValidity(TOPO_CHAN_NUM, valid); tri->SetChannelValidity(GEOM_CHAN_NUM, valid); tri->SetChannelValidity(TEXMAP_CHAN_NUM, valid); tri->SetChannelValidity(MTL_CHAN_NUM, valid); tri->SetChannelValidity(SELECT_CHAN_NUM, valid); tri->SetChannelValidity(SUBSEL_TYPE_CHAN_NUM, valid); tri->SetChannelValidity(DISP_ATTRIB_CHAN_NUM, valid); os->obj = tri; break; } #ifdef XXDESIGN_VER case AMSOLID_OUTPUT: { //Create an extrusion solid using Facet Modeler Object* solid = (Object*)CreateInstance(GEOMOBJECT_CLASS_ID, GENERIC_AMSOLID_CLASS_ID); assert(solid); if(solid) { IGeomImp* cacheptr = (IGeomImp*)(solid->GetInterface(I_GEOMIMP)); assert(cacheptr); if(cacheptr) { bool res = BuildAMSolidFromShape(t, mc, os, cacheptr); solid->ReleaseInterface(I_GEOMIMP, cacheptr); if(!res) { valid.SetInstant(t); // assert(!cacheptr->isNull()); } for(int i=0; i<NUM_OBJ_CHANS;i++) solid->SetChannelValidity(i, valid); os->obj = solid; } } break; } #endif } os->obj->UnlockObject(); }
void BombMod::ModifyObject( TimeValue t, ModContext &mc, ObjectState *os, INode *node) { BombObject *bobj = GetWSMObject(t); if (bobj && nodeRef && (bobj->ClassID() == Class_ID(BOMB_OBJECT_CLASS_ID,0))) { assert(os->obj->IsSubClassOf(triObjectClassID)); TriObject *triOb = (TriObject *)os->obj; Interval valid = FOREVER; if (os->GetTM()) { Matrix3 tm = *(os->GetTM()); for (int i=0; i<triOb->GetMesh().getNumVerts(); i++) { triOb->GetMesh().verts[i] = triOb->GetMesh().verts[i] * tm; } os->obj->UpdateValidity(GEOM_CHAN_NUM,os->tmValid()); os->SetTM(NULL,FOREVER); } if (waitPostLoad) { valid.SetInstant(t); triOb->UpdateValidity(GEOM_CHAN_NUM,valid); triOb->UpdateValidity(TOPO_CHAN_NUM,valid); return; } Matrix3 tm; TimeValue det = bobj->GetDetonation(t,valid); float strength = bobj->GetStrength(t,valid) * STRENGTH_CONSTANT; float grav = bobj->GetGravity(t,valid); float chaos = bobj->GetChaos(t,valid); float chaosBase = (float(1)-chaos/2); float rotSpeed = bobj->GetSpin(t,valid) * TWOPI/float(TIME_TICKSPERSEC); int minClust = bobj->GetMinFrag(t,valid), maxClust = bobj->GetMaxFrag(t,valid); if (minClust<1) minClust = 1; if (maxClust<1) maxClust = 1; int clustVar = maxClust-minClust+1; float falloff = bobj->GetFalloff(t,valid); int useFalloff = bobj->GetFalloffOn(t,valid); int seed = bobj->GetSeed(t,valid); //tm = nodeRef->GetNodeTM(t,&valid); tm = nodeRef->GetObjectTM(t,&valid); if (t<det) { valid.Set(TIME_NegInfinity,det-1); triOb->UpdateValidity(GEOM_CHAN_NUM,valid); triOb->UpdateValidity(TOPO_CHAN_NUM,valid); triOb->PointsWereChanged(); return; } float dt = float(t-det); valid.SetInstant(t); int n0=0,n1=1,n2=2,nv; Point3 v, p0, p1, g(0.0f,0.0f,grav*GRAVITY_CONSTANT); Tab<Point3> l_newVerts ; Face *f = triOb->GetMesh().faces; float dot; Mesh &mesh = triOb->GetMesh(); // First, segment the faces. srand((unsigned int)seed); Tab<DWORD> vclust; Tab<DWORD> vmap; Tab<Point3> nverts; vclust.SetCount(mesh.getNumVerts()); vmap.SetCount(mesh.getNumVerts()); int numClust = 0; if (minClust==1 && maxClust==1) { // Simple case... 1 face per cluster nv = triOb->GetMesh().getNumFaces() * 3; l_newVerts.SetCount(nv); vclust.SetCount(nv); for (int i=0; i<nv; i++) { vclust[i] = i/3; } for (int i=0,j=0; i<mesh.getNumFaces(); i++) { l_newVerts[j] = mesh.verts[mesh.faces[i].v[0]]; l_newVerts[j+1] = mesh.verts[mesh.faces[i].v[1]]; l_newVerts[j+2] = mesh.verts[mesh.faces[i].v[2]]; mesh.faces[i].v[0] = j; mesh.faces[i].v[1] = j+1; mesh.faces[i].v[2] = j+2; j += 3; } numClust = triOb->GetMesh().getNumFaces(); } else { // More complex case... clusters are randomely sized for (int i=0; i<mesh.getNumVerts(); i++) { vclust[i] = UNDEFINED; vmap[i] = i; } int cnum = 0; for (int i=0; i<mesh.getNumFaces(); ) { int csize = int(Rand1()*float(clustVar)+float(minClust)); if (i+csize>mesh.getNumFaces()) { csize = mesh.getNumFaces()-i; } // Make sure each face in the cluster has at least 2 verts in common with another face. BOOL verified = FALSE; while (!verified) { verified = TRUE; if (csize<2) break; for (int j=0; j<csize; j++) { BOOL match = FALSE; for (int k=0; k<csize; k++) { if (k==j) continue; int common = 0; for (int i1=0; i1<3; i1++) { for (int i2=0; i2<3; i2++) { if (mesh.faces[i+j].v[i1]== mesh.faces[i+k].v[i2]) common++; } } if (common>=2) { match = TRUE; break; } } if (!match) { csize = j; verified = FALSE; // Have to check again break; } } } if (csize==0) csize = 1; // Clear the vert map for (int j=0; j<mesh.getNumVerts(); j++) vmap[j] = UNDEFINED; // Go through the cluster and remap verts. for (int j=0;j<csize; j++) { for (int k=0; k<3; k++) { if (vclust[mesh.faces[i+j].v[k]]==UNDEFINED) { vclust[mesh.faces[i+j].v[k]] = cnum; } else if (vclust[mesh.faces[i+j].v[k]]!=(DWORD)cnum) { if (vmap[mesh.faces[i+j].v[k]]==UNDEFINED) { vclust.Append(1,(DWORD*)&cnum,50); nverts.Append(1,&mesh.verts[mesh.faces[i+j].v[k]],50); mesh.faces[i+j].v[k] = vmap[mesh.faces[i+j].v[k]] = mesh.getNumVerts()+nverts.Count()-1; } else { mesh.faces[i+j].v[k] = vmap[mesh.faces[i+j].v[k]]; } } } } cnum++; numClust++; i += csize; } nv = mesh.getNumVerts() + nverts.Count(); l_newVerts.SetCount(nv); int i; for (i=0; i<mesh.getNumVerts(); i++) l_newVerts[i] = mesh.verts[i]; for ( ; i<mesh.getNumVerts()+nverts.Count(); i++) l_newVerts[i] = nverts[i-mesh.getNumVerts()]; } // Find the center of all clusters Tab<Point3> clustCent; Tab<DWORD> clustCounts; clustCent.SetCount(numClust); clustCounts.SetCount(numClust); for (int i=0; i<numClust; i++) { clustCent[i] = Point3(0,0,0); clustCounts[i] = 0; } for (int i=0; i<nv; i++) { if (vclust[i]==UNDEFINED) continue; clustCent[vclust[i]] += l_newVerts[i]; clustCounts[vclust[i]]++; } // Build transformations for all clusters Tab<Matrix3> mats; mats.SetCount(numClust); srand((unsigned int)seed); for (int i=0; i<numClust; i++) { if (clustCounts[i]) clustCent[i] /= float(clustCounts[i]); v = clustCent[i] - tm.GetTrans(); float u = 1.0f; if (useFalloff) { u = 1.0f - Length(v)/falloff; if (u<0.0f) u = 0.0f; } dot = DotProd(v,v); if (dot==0.0f) dot = 0.000001f; v = v / dot * strength * u; v.x *= chaosBase + chaos * Rand1(); v.y *= chaosBase + chaos * Rand1(); v.z *= chaosBase + chaos * Rand1(); p1 = v*dt + 0.5f*g*dt*dt; // projectile motion // Set rotation Point3 axis; axis.x = -1.0f + 2.0f*Rand1(); axis.y = -1.0f + 2.0f*Rand1(); axis.z = -1.0f + 2.0f*Rand1(); axis = Normalize(axis); float angle = dt*rotSpeed*(chaosBase + chaos * Rand1())*u; Quat q = QFromAngAxis(angle, axis); q.MakeMatrix(mats[i]); mats[i].PreTranslate(-clustCent[i]); mats[i].Translate(clustCent[i]+p1); } // Now transform the clusters for (int i=0; i<nv; i++) { if (vclust[i]==UNDEFINED) continue; l_newVerts[i] = l_newVerts[i] * mats[vclust[i]]; } triOb->UpdateValidity(GEOM_CHAN_NUM,valid); triOb->UpdateValidity(TOPO_CHAN_NUM,valid); triOb->PointsWereChanged(); triOb->GetMesh().setNumVerts(nv,FALSE,TRUE); //assign the new vertices to the mesh for ( int i=0; i < nv; i++) triOb->GetMesh().setVert( i,l_newVerts[i]); } }