void AnimExportUtil::resamplePositionAnimation( const Vector<Matrix4x4>& tm, Interval animRange, KeyFrameContainer* pos ) { // find out maximum acceptable error float maxErrPercent = MAX_POSITION_RESAMPLING_ERROR; float defr = 1e9f; Vector3 minbox( defr, defr, defr ); Vector3 maxbox(-defr,-defr,-defr ); for ( int k = 0 ; k < tm.size() ; k += 2 ) { Vector3 pos = tm[k].translation(); minbox = pos.minElements( minbox ); maxbox = pos.maxElements( maxbox ); } float maxErr = (minbox-maxbox).length()/100.f * maxErrPercent; if ( maxErr < 1e-6f ) maxErr = 1e-6f; int firstFrame = animRange.Start() / SGEXPORT_TICKS_PER_SAMPLE; require( firstFrame >= 0 && firstFrame < tm.size() ); AnimExportUtil::addPositionKey( *pos, tm[firstFrame], TicksToSec(animRange.Start()) ); AnimExportUtil::addPositionKey( *pos, tm.lastElement(), TicksToSec(animRange.End()) ); Debug::println( "max position error = {0}", maxErr ); resamplePositionKeys( *pos, animRange, maxErr, tm ); if ( pos->keys() == 2 && isEqualValue(pos->getKey(0),pos->getKey(1),3) ) pos->removeKey( 1 ); }
/** * Resamples animation until maximum error is smaller than specified value. * @param maxErr Maximum absolute error */ static void resampleFloatKeys( KeyFrameContainer& anim, Interval range, float maxErr, const Vector<float>& frames ) { TimeValue dticks = SGEXPORT_TICKS_PER_SAMPLE; int frame = range.Start() / dticks; require( frame >= 0 && frame < frames.size() ); TimeValue rangeLen = (range.Duration()/SGEXPORT_TICKS_PER_SAMPLE)*SGEXPORT_TICKS_PER_SAMPLE; for ( TimeValue ticks = range.Start() ; ticks < range.End() ; ticks += dticks ) { if ( ticks > range.End() ) ticks = range.End(); // find out error (distance) between real and sampled animation require( frame >= 0 && frame < frames.size() ); float realValue = frames[frame++]; float sampledValue = 0.f; anim.getValue( TicksToSec(ticks), &sampledValue, 1 ); float err = Math::abs( realValue - sampledValue ); // sample more accurately if needed if ( err > maxErr && rangeLen > dticks ) { TimeValue halfRange = alignTicks( (range.End() + range.Start())/2 ); anim.insertKey( KeyFrame( TicksToSec(halfRange), INTERP_TYPE, &frames[halfRange/dticks], 1 ) ); if ( ticks <= halfRange ) resampleFloatKeys( anim, Interval(range.Start(),halfRange), maxErr, frames ); else resampleFloatKeys( anim, Interval(halfRange,range.End()), maxErr, frames ); } if ( ticks == range.End() ) break; } }
void AnimExportUtil::addScaleAnimation( const Vector<Matrix4x4>& tm, Interval animRange, KeyFrameContainer* scale ) { int firstFrame = animRange.Start() / SGEXPORT_TICKS_PER_SAMPLE; for ( TimeValue ticks = animRange.Start() ; ticks <= animRange.End() ; ticks += SGEXPORT_TICKS_PER_SAMPLE ) { require( firstFrame >= 0 && firstFrame < tm.size() ); AnimExportUtil::addScaleKey( *scale, tm[firstFrame++], TicksToSec(ticks) ); } }
void AnimExportUtil::addFloatAnimation( const util::Vector<float>& frames, Interval animRange, KeyFrameContainer* anim, float maxErr ) { int firstFrame = animRange.Start() / SGEXPORT_TICKS_PER_SAMPLE; for ( TimeValue ticks = animRange.Start() ; ticks <= animRange.End() ; ticks += SGEXPORT_TICKS_PER_SAMPLE ) { require( firstFrame >= 0 && firstFrame < frames.size() ); anim->insertKey( KeyFrame(TicksToSec(ticks),INTERP_TYPE,&frames[firstFrame++],1) ); } }
INT_PTR CALLBACK TrackPropDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { BlockControl *blk = (BlockControl*)GetWindowLongPtr(hWnd,GWLP_USERDATA); ISpinnerControl *spin; static TSTR zero = FormatUniverseValue(0.0f); Rect rect; switch (msg) { case WM_INITDIALOG: { blk = (BlockControl*)lParam; SetWindowLongPtr(hWnd,GWLP_USERDATA,lParam); Interval range = GetCOREInterface()->GetAnimRange(); spin = GetISpinner(GetDlgItem(hWnd,IDC_STARTSPIN)); spin->SetLimits(-999999.0f,9999999.0f, FALSE); spin->SetAutoScale(); spin->LinkToEdit(GetDlgItem(hWnd,IDC_START), EDITTYPE_INT); spin->SetValue(range.Start()/GetTicksPerFrame(),FALSE); ReleaseISpinner(spin); blk->propStart = range.Start()/GetTicksPerFrame(); CenterWindow(hWnd,GetParent(hWnd)); break; } case CC_SPINNER_CHANGE: spin = (ISpinnerControl*)lParam; switch (LOWORD(wParam)) { case IDC_STARTSPIN: blk->propStart = spin->GetIVal(); break; } break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: { EndDialog(hWnd,1); blk->NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE); break; } case IDCANCEL: EndDialog(hWnd,0); break; } break; default: return FALSE; } return TRUE; }
void AnimExportUtil::resampleFloatAnimation( const util::Vector<float>& frames, Interval animRange, KeyFrameContainer* anim, float maxErr ) { int firstFrame = animRange.Start() / SGEXPORT_TICKS_PER_SAMPLE; require( firstFrame >= 0 && firstFrame < frames.size() ); anim->insertKey( KeyFrame(TicksToSec(animRange.Start()),INTERP_TYPE,&frames[firstFrame],1) ); anim->insertKey( KeyFrame(TicksToSec(animRange.End()),INTERP_TYPE,&frames.lastElement(),1) ); resampleFloatKeys( *anim, animRange, maxErr, frames ); if ( anim->keys() == 2 && isEqualValue(anim->getKey(0),anim->getKey(1),3) ) anim->removeKey( 1 ); }
void AnimExportUtil::resampleRotationAnimation( const Vector<Matrix4x4>& tm, Interval animRange, KeyFrameContainer* rot ) { float maxErr = Math::toRadians(MAX_ROTATION_RESAMPLING_ERROR); int firstFrame = animRange.Start() / SGEXPORT_TICKS_PER_SAMPLE; require( firstFrame >= 0 && firstFrame < tm.size() ); AnimExportUtil::addRotationKey( *rot, tm[firstFrame], TicksToSec(animRange.Start()) ); AnimExportUtil::addRotationKey( *rot, tm.lastElement(), TicksToSec(animRange.End()) ); Debug::println( "max rotation error = {0} degrees", Math::toDegrees(maxErr) ); resampleRotationKeys( *rot, animRange, maxErr, tm ); if ( rot->keys() == 2 && isEqualValue(rot->getKey(0),rot->getKey(1),4) ) rot->removeKey( 1 ); }
void AnimExportUtil::resampleScaleAnimation( const Vector<Matrix4x4>& tm, Interval animRange, KeyFrameContainer* scale ) { float maxErrPercent = MAX_SCALE_RESAMPLING_ERROR; int firstFrame = animRange.Start() / SGEXPORT_TICKS_PER_SAMPLE; require( firstFrame >= 0 && firstFrame < tm.size() ); AnimExportUtil::addScaleKey( *scale, tm[firstFrame], TicksToSec(animRange.Start()) ); AnimExportUtil::addScaleKey( *scale, tm.lastElement(), TicksToSec(animRange.End()) ); Debug::println( "max scale error = {0}%", maxErrPercent ); resampleScaleKeys( *scale, animRange, maxErrPercent/100.f, tm ); if ( scale->keys() == 2 && isEqualValue(scale->getKey(0),scale->getKey(1),3) ) scale->removeKey( 1 ); }
void AnimExportUtil::getTransformAnimation( INode* node, Interval animRange, Vector<math::Matrix4x4>* anim ) { require( animRange.Start() <= animRange.End() ); anim->clear(); TimeValue dt = SGEXPORT_TICKS_PER_SAMPLE; for ( TimeValue t = animRange.Start() ; t <= animRange.End() ; t += dt ) { Matrix4x4 tm = TmUtil::getModelToParentLH( node, t ); anim->add( tm ); } require( anim->size() > 0 ); }
//--------------------------------------------------------------- bool DocumentExporter::showExportOptions(bool suppressPrompts) { if (!suppressPrompts) { // Prompt the user with our dialogbox, and get all the options. // The user may cancel the export at this point. if (!mOptions.ShowDialog()) return false; } else { mOptions.LoadOptions(); if (!mOptions.getSampleAnimation()) { Interval animRange = GetCOREInterface()->GetAnimRange(); int sceneStart = animRange.Start(); int sceneEnd = animRange.End(); mOptions.setAnimBounds(sceneStart, sceneEnd); } } // Set relative/absolute export // colladaDocument->GetFileManager()->SetForceAbsoluteFlag(!options->ExportRelativePaths()); return true; }
// Dialog proc static INT_PTR CALLBACK ExportDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { Interval animRange; ISpinnerControl *spin; AscOut *exp = (AscOut*)GetWindowLongPtr(hWnd,GWLP_USERDATA); switch (msg) { case WM_INITDIALOG: exp = (AscOut*)lParam; SetWindowLongPtr(hWnd,GWLP_USERDATA,lParam); CenterWindow(hWnd, GetParent(hWnd)); // Setup the spinner controls for the floating point precision spin = GetISpinner(GetDlgItem(hWnd, IDC_PREC_SPIN)); spin->LinkToEdit(GetDlgItem(hWnd,IDC_PREC), EDITTYPE_INT ); spin->SetLimits(1, 10, TRUE); spin->SetScale(1.0f); spin->SetValue(exp->GetPrecision() ,FALSE); ReleaseISpinner(spin); // Setup the spinner control for the static frame# // We take the frame 0 as the default value animRange = exp->GetInterface()->GetAnimRange(); spin = GetISpinner(GetDlgItem(hWnd, IDC_STATIC_FRAME_SPIN)); spin->LinkToEdit(GetDlgItem(hWnd,IDC_STATIC_FRAME), EDITTYPE_INT ); spin->SetLimits(animRange.Start() / GetTicksPerFrame(), animRange.End() / GetTicksPerFrame(), TRUE); spin->SetScale(1.0f); spin->SetValue(0, FALSE); ReleaseISpinner(spin); break; case CC_SPINNER_CHANGE: spin = (ISpinnerControl*)lParam; break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: spin = GetISpinner(GetDlgItem(hWnd, IDC_PREC_SPIN)); exp->SetPrecision(spin->GetIVal()); ReleaseISpinner(spin); spin = GetISpinner(GetDlgItem(hWnd, IDC_STATIC_FRAME_SPIN)); exp->SetStaticFrame(spin->GetIVal() * GetTicksPerFrame()); ReleaseISpinner(spin); EndDialog(hWnd, 1); break; case IDCANCEL: EndDialog(hWnd, 0); break; } break; default: return FALSE; } return TRUE; }
Interval Interval::Union(const Interval &i) const { Interval ret; ret.m_start = std::min(Start(), i.Start()); ret.m_end = std::max(End(), i.End()); return ret; }
/** * Resamples animation until maximum error is smaller than specified angle (radians). * @param maxErr Maximum absolute error (radians). */ static void resampleRotationKeys( KeyFrameContainer& anim, Interval range, float maxErr, const Vector<Matrix4x4>& tm ) { TimeValue dticks = SGEXPORT_TICKS_PER_SAMPLE; int frame = range.Start() / dticks; require( frame >= 0 && frame < tm.size() ); TimeValue rangeLen = (range.Duration()/SGEXPORT_TICKS_PER_SAMPLE)*SGEXPORT_TICKS_PER_SAMPLE; for ( TimeValue ticks = range.Start() ; ticks < range.End() ; ticks += dticks ) { if ( ticks > range.End() ) ticks = range.End(); // find out error (distance) between real and sampled animation require( frame >= 0 && frame < tm.size() ); const Matrix4x4& m = tm[frame++]; Matrix3x3 ref = m.rotation().orthonormalize(); float q[4]; anim.getValue( TicksToSec(ticks), q, 4 ); Matrix3x3 cmp( Quaternion(q[0],q[1],q[2],q[3]) ); float xang = Math::abs( Math::acos( clamp(cmp.getColumn(0).dot(ref.getColumn(0)), -1.f, 1.f) ) ); float yang = Math::abs( Math::acos( clamp(cmp.getColumn(1).dot(ref.getColumn(1)), -1.f, 1.f) ) ); float zang = Math::abs( Math::acos( clamp(cmp.getColumn(2).dot(ref.getColumn(2)), -1.f, 1.f) ) ); float err = xang; if ( yang > err ) err = yang; if ( zang > err ) err = zang; // sample more accurately if needed if ( err > maxErr && rangeLen > dticks ) { TimeValue halfRange = alignTicks( (range.End() + range.Start())/2 ); AnimExportUtil::addRotationKey( anim, tm[halfRange/dticks], TicksToSec(halfRange) ); if ( ticks <= halfRange ) resampleRotationKeys( anim, Interval(range.Start(),halfRange), maxErr, tm ); else resampleRotationKeys( anim, Interval(halfRange,range.End()), maxErr, tm ); } if ( ticks == range.End() ) break; } }
void FloatMC::BeginCapture(Interval record,TimeValue sampSize) { // Set the base point to the controller value at the start time. cont->GetValue(record.Start(),&base,FOREVER,CTRL_ABSOLUTE); // Allocate a data buffer sampleCount = record.Duration()/sampSize + 1; data = new float[sampleCount]; for (int i=0; i<sampleCount; i++) data[i] = 0.0f; }
// SAMPLENODEMOTION // top level function for sampling all the motion on a single node plSampleVec * SampleNodeMotion(INode* node, INode* parent, int sampleRate, Interface *theInterface) { Interval interval = theInterface->GetAnimRange(); TimeValue start = interval.Start(); // in ticks TimeValue end = interval.End(); sampleRate *= GetTicksPerFrame(); // convert sample rate to ticks return SampleNodeMotion(node, parent, sampleRate, start, end); }
void ValuesTable::Move(const Interval &in) { if (in.End() < 0 || in.Start() >= (int)m_values.size()) { m_values.resize(0); m_values.resize(in.End() - in.Start() + 1); return; } while ((in.End() + 1) < (int)m_values.size()) PopBack(); for (int i = 0; i < in.Start(); ++i) PopFront(); for (int i = 0; i > in.Start(); --i) PushFront(); for (int i = m_values.size(); i <= in.End() - in.Start(); ++i) PushBack(); }
/** * Resamples animation until maximum error is smaller than specified value. * @param maxErr Maximum relative error, i.e. 0.05f == 5%. */ static void resampleScaleKeys( KeyFrameContainer& anim, Interval range, float maxErr, const Vector<Matrix4x4>& tm ) { TimeValue dticks = SGEXPORT_TICKS_PER_SAMPLE; int frame = range.Start() / dticks; require( frame >= 0 && frame < tm.size() ); TimeValue rangeLen = (range.Duration()/SGEXPORT_TICKS_PER_SAMPLE)*SGEXPORT_TICKS_PER_SAMPLE; for ( TimeValue ticks = range.Start() ; ticks < range.End() ; ticks += dticks ) { if ( ticks > range.End() ) ticks = range.End(); // find out error (distance) between real and sampled animation require( frame >= 0 && frame < tm.size() ); const Matrix4x4& m = tm[frame++]; Vector3 ref; Vector3 a; a = getAxis(m,0); ref[0] = a.dot(normalize0(a)); a = getAxis(m,1); ref[1] = a.dot(normalize0(a)); a = getAxis(m,2); ref[2] = a.dot(normalize0(a)); float cmp[3]; anim.getValue( TicksToSec(ticks), cmp, 3 ); float err = (Vector3(cmp[0],cmp[1],cmp[2]) - ref).length(); if ( ref.length() > Float::MIN_VALUE ) err /= ref.length(); // sample more accurately if needed if ( err > maxErr && rangeLen > dticks ) { TimeValue halfRange = alignTicks( (range.End() + range.Start())/2 ); AnimExportUtil::addScaleKey( anim, tm[halfRange/dticks], TicksToSec(halfRange) ); if ( ticks <= halfRange ) resampleScaleKeys( anim, Interval(range.Start(),halfRange), maxErr, tm ); else resampleScaleKeys( anim, Interval(halfRange,range.End()), maxErr, tm ); } if ( ticks == range.End() ) break; } }
void RandKeysUtil::SetStates() { if (doTime) { iPosTime->Enable(); EnableWindow(GetDlgItem(hWnd,IDC_RANDKEYS_POSTIMELABEL),TRUE); iNegTime->Enable(); EnableWindow(GetDlgItem(hWnd,IDC_RANDKEYS_NEGTIMELABEL),TRUE); } else { iPosTime->Disable(); EnableWindow(GetDlgItem(hWnd,IDC_RANDKEYS_POSTIMELABEL),FALSE); iNegTime->Disable(); EnableWindow(GetDlgItem(hWnd,IDC_RANDKEYS_NEGTIMELABEL),FALSE); } if (doVal) { iPosVal->Enable(); EnableWindow(GetDlgItem(hWnd,IDC_RANDKEYS_POSVALLABEL),TRUE); iNegVal->Enable(); EnableWindow(GetDlgItem(hWnd,IDC_RANDKEYS_NEGVALLABEL),TRUE); } else { iPosVal->Disable(); EnableWindow(GetDlgItem(hWnd,IDC_RANDKEYS_POSVALLABEL),FALSE); iNegVal->Disable(); EnableWindow(GetDlgItem(hWnd,IDC_RANDKEYS_NEGVALLABEL),FALSE); } switch (iu->GetMajorMode()) { case TVMODE_EDITKEYS: case TVMODE_EDITFCURVE: SetDlgItemText(hWnd,IDC_RANDKEYS_TEXT, GetString(IDS_RANDKEYS_KEYTEXT)); EnableWindow(GetDlgItem(hWnd,IDC_RANDKEYS_APPLY),TRUE); break; case TVMODE_EDITTIME: { Interval iv = iu->GetTimeSelection(); TSTR buf, start, end; TimeToString(iv.Start(),start); TimeToString(iv.End(),end); buf.printf(GetString(IDS_RANDKEYS_TIMETEXT),start,end); SetDlgItemText(hWnd,IDC_RANDKEYS_TEXT,buf); EnableWindow(GetDlgItem(hWnd,IDC_RANDKEYS_APPLY),TRUE); break; } case TVMODE_EDITRANGES: case TVMODE_POSRANGES: SetDlgItemText(hWnd,IDC_RANDKEYS_TEXT,_T("")); EnableWindow(GetDlgItem(hWnd,IDC_RANDKEYS_APPLY),FALSE); break; } }
void RotationMC::BeginCapture(Interval record,TimeValue sampSize) { // Set the base point to the controller value at the start time. Quat q; cont->GetValue(record.Start(),&q,FOREVER,CTRL_ABSOLUTE); QuatToEuler(q,base); // Allocate a data buffer sampleCount = record.Duration()/sampSize + 1; data = new Point3[sampleCount]; for (int i=0; i<sampleCount; i++) data[i] = Point3(0,0,0); }
void ScaleMC::BeginCapture(Interval record,TimeValue sampSize) { // Set the base point to the controller value at the start time. ScaleValue s; cont->GetValue(record.Start(),&s,FOREVER,CTRL_ABSOLUTE); base = s.s; // Allocate a data buffer sampleCount = record.Duration()/sampSize + 1; data = new Point3[sampleCount]; for (int i=0; i<sampleCount; i++) data[i] = Point3(1,1,1); }
void ValuesTable::MoveView(int d) { m_view.Move(d); if (!m_draw->m_draws_controller->GetDoubleCursor()) m_stats.Move(d); Interval in = m_view.Union(m_stats); Interval fin = in; fin.m_start = fin.Start() - m_draw->m_draws_controller->GetFilter(); fin.m_end = fin.End() + m_draw->m_draws_controller->GetFilter(); Move(fin); m_view.Move(-in.Start() + m_draw->m_draws_controller->GetFilter()); m_stats.Move(-in.Start() + m_draw->m_draws_controller->GetFilter()); if (!m_draw->m_draws_controller->GetDoubleCursor()) { RecalculateStats(); m_draw->m_observers->NotifyStatsChanged(m_draw); } }
void ValuesTable::DragStats(int d) { if (!m_draw->m_draws_controller->GetDoubleCursor()) return; if (m_draw->GetDrawInfo() == NULL) return; m_stats.Drag(d); Interval in = m_view.Union(m_stats); Interval fin = in; fin.m_start -= m_draw->m_draws_controller->GetFilter(); fin.m_end += m_draw->m_draws_controller->GetFilter(); Move(fin); m_view.Move(-in.Start() + m_draw->m_draws_controller->GetFilter()); m_stats.Move(-in.Start() + m_draw->m_draws_controller->GetFilter()); RecalculateStats(); m_draw->m_observers->NotifyStatsChanged(m_draw); }
void FloatMC::EndCapture(Interval record,TimeValue sampSize, KeyReduceStatus *stat) { // Clear any keys out of the record interval cont->DeleteTime(record,TIME_INCLEFT|TIME_INCRIGHT|TIME_NOSLIDE); // Make keys out of the data SuspendAnimate(); AnimateOn(); for (int i=0; i<sampleCount; i++) { TimeValue t = record.Start() + i * sampSize; cont->SetValue(t,&data[i],1,CTRL_ABSOLUTE); if (i%UPDATE_RATE==0) if (stat->Progress(i)!=KEYREDUCE_CONTINUE) goto abort; } abort: ResumeAnimate(); delete[] data; base = 0.0f; }
Interval AnimExportUtil::getKeyFramedRotationRange( INode* node3ds, Interval animRange ) { require( node3ds->GetTMController() ); TimeValue start = animRange.Start(); TimeValue end = animRange.End(); // target defines rotation if ( node3ds->GetTarget() ) return Interval( start, start ); Control* cont = node3ds->GetTMController()->GetRotationController(); IKeyControl* ikeys = cont ? GetKeyControlInterface( cont ) : 0; if ( ikeys ) { ITCBRotKey key1; IBezQuatKey key2; ILinRotKey key3; IKey* keyp = 0; if ( cont->ClassID() == Class_ID(TCBINTERP_ROTATION_CLASS_ID, 0) ) keyp = &key1; else if ( cont->ClassID() == Class_ID(HYBRIDINTERP_ROTATION_CLASS_ID, 0) ) keyp = &key2; else if ( cont->ClassID() == Class_ID(LININTERP_ROTATION_CLASS_ID, 0) ) keyp = &key3; if ( keyp ) { if ( 0 == ikeys->GetNumKeys() ) return Interval( start, start ); ikeys->GetKey( 0, keyp ); start = keyp->time; ikeys->GetKey( ikeys->GetNumKeys()-1, keyp ); end = keyp->time; } } return Interval( start, end ); }
TEST(basic, should_measure_intervals) { const int iterations = 10000; Interval interval; for (int i = 0; i < iterations; i++) { std::string s(""); interval.Start("FOO"); for (int j = 0; j < iterations; j++) { s += "a"; } interval.End("FOO"); } auto v = interval.Intervals("FOO"); ASSERT_EQ(v.size(), iterations); float sum = 0; for (auto d : v) { ASSERT_GT(d.count(), 0); sum += d.count(); } printf("avg per concatenation: %.10f\n", sum / v.size() / iterations); }
void Import::SetSceneParameters() { Interval range; range.SetStart(0); range.SetEnd(30); SetFrameRate(30); SetTicksPerFrame(160); range.SetStart(range.Start() * GetTicksPerFrame()); range.SetEnd(range.End() * GetTicksPerFrame()); m_ip->SetAnimRange(range); Point3 bkColor (0.0f, 0.0f, 0.0f); m_impip->SetBackGround(0, bkColor); Point3 amColor (0.3f, 0.3f, 0.3f); m_impip->SetAmbient(0, amColor); }
//from IUnReplaceableControl Control * EulerExposeControl::GetReplacementClone() { Control *control = NewDefaultRotationController(); if(control) { // set key per frame Interval range =GetCOREInterface()->GetAnimRange(); TimeValue tpf = GetTicksPerFrame(); SuspendAnimate(); AnimateOn(); Quat v; for(TimeValue t= range.Start(); t<=range.End();t+=tpf) { GetValue(t,&v,Interval(t,t)); control->SetValue(t,&v,1,CTRL_ABSOLUTE); } ResumeAnimate(); } return control; }
// ########################################################### // ####### EXPORTERs DI SINGOLE ENTITA' DELLA SCENA ####### // ########################################################### void SkeletonExporter::export_general_info(void) { int ff, lf, fs; Interval range = ip->GetAnimRange(); Box3 bbox; fprintf(fTXT, "[AD]Turbo ROX as usual !! \n\n"); INode *root = ip->GetRootNode(); bbox.pmin.x=bbox.pmin.y=bbox.pmin.z=(float)1E10; bbox.pmax.x=bbox.pmax.y=bbox.pmax.z=(float)-1E10; GetSceneBoundingBox(root, 0, &bbox); ff=range.Start() / GetTicksPerFrame(); lf=range.End() / GetTicksPerFrame(); fs=GetFrameRate(); // Start with a file identifier and format version fprintf(fTXT, "First frame : %d\n", ff); fprintf(fTXT, "Last frame : %d\n", lf); fprintf(fTXT, "Frame speed : %d\n", fs); fprintf(fTXT, "Scene Bounding Box at time 0\n"); fprintf(fTXT, "min : %f, %f, %f\n", bbox.pmin.x, bbox.pmin.y, bbox.pmin.z); fprintf(fTXT, "max : %f, %f, %f\n", bbox.pmax.x, bbox.pmax.y, bbox.pmax.z); write_chunk_header(fA3D, SCENE_GENERAL_INFO_ID, "Scene Root", 36); fwrite(&ff, sizeof(int), 1, fA3D); fwrite(&lf, sizeof(int), 1, fA3D); fwrite(&fs, sizeof(int), 1, fA3D); write_bbox(&bbox, fA3D); if (makeRAY) write_chunk_header(fRAY, SCENE_GENERAL_INFO_ID, "Scene Root", 36); if (makeRAY) fwrite(&ff, sizeof(int), 1, fRAY); if (makeRAY) fwrite(&lf, sizeof(int), 1, fRAY); if (makeRAY) fwrite(&fs, sizeof(int), 1, fRAY); if (makeRAY) write_bbox(&bbox, fRAY); }
// Output float keys if this is a known float controller that // supports key operations. Otherwise we will sample the controller // once for each frame to get the value. void AsciiExp::DumpFloatKeys(Control* cont, int indentLevel) { if (!cont) return; int i; TSTR indent = GetIndent(indentLevel); IKeyControl *ikc = NULL; // If the user wants us to always sample, we will ignore the KeyControlInterface if (!GetAlwaysSample()) ikc = GetKeyControlInterface(cont); // TCB float if (ikc && cont->ClassID() == Class_ID(TCBINTERP_FLOAT_CLASS_ID, 0)) { _ftprintf(pStream, _T("%s\t\t%s {\n"), indent.data(), ID_CONTROL_FLOAT_TCB); for (i=0; i<ikc->GetNumKeys(); i++) { ITCBFloatKey key; ikc->GetKey(i, &key); _ftprintf(pStream, _T("%s\t\t\t%s %d\t%s"), indent.data(), ID_TCB_FLOAT_KEY, key.time, Format(key.val)); _ftprintf(pStream, _T("\t%s\t%s\t%s\t%s\t%s\n"), Format(key.tens), Format(key.cont), Format(key.bias), Format(key.easeIn), Format(key.easeOut)); } _ftprintf(pStream, _T("%s\t\t}\n"), indent.data()); } // Bezier float else if (ikc && cont->ClassID() == Class_ID(HYBRIDINTERP_FLOAT_CLASS_ID, 0)) { _ftprintf(pStream, _T("%s\t\t%s {\n"), indent.data(), ID_CONTROL_FLOAT_BEZIER); for (i=0; i<ikc->GetNumKeys(); i++) { IBezFloatKey key; ikc->GetKey(i, &key); _ftprintf(pStream, _T("%s\t\t\t%s %d\t%s"), indent.data(), ID_BEZIER_FLOAT_KEY, key.time, Format(key.val)); _ftprintf(pStream, _T("\t%s\t%s\t%d\n"), Format(key.intan), Format(key.outtan), key.flags); } _ftprintf(pStream, _T("%s\t\t}\n"), indent.data()); } else if (ikc && cont->ClassID() == Class_ID(LININTERP_FLOAT_CLASS_ID, 0)) { _ftprintf(pStream, _T("%s\t\t%s {\n"), indent.data(), ID_CONTROL_FLOAT_LINEAR); for (i=0; i<ikc->GetNumKeys(); i++) { ILinFloatKey key; ikc->GetKey(i, &key); _ftprintf(pStream, _T("%s\t\t\t%s %d\t%s\n"), indent.data(), ID_FLOAT_KEY, key.time, Format(key.val)); } _ftprintf(pStream, _T("%s\t\t}\n"), indent.data()); } else { // Unknown controller, no key interface or sample on demand - // This might be a procedural controller or something else we // don't know about. The last resort is to get the value from the // controller at every n frames. TSTR name; cont->GetClassName(name); TSTR className = FixupName(name); Interface14 *iface = GetCOREInterface14(); UINT codepage = iface-> DefaultTextSaveCodePage(true); const char* className_locale = className.ToCP(codepage); _ftprintf(pStream, _T("%s\t\t%s \"%hs\" {\n"), indent.data(), ID_CONTROL_FLOAT_SAMPLE, className_locale); // If it is animated at all... if (cont->IsAnimated()) { // Get the range of the controller animation Interval range; // Get range of full animation Interval animRange = ip->GetAnimRange(); TimeValue t = cont->GetTimeRange(TIMERANGE_ALL).Start(); float value; // While we are inside the animation... while (animRange.InInterval(t)) { // Sample the controller range = FOREVER; cont->GetValue(t, &value, range); // Set time to start of controller validity interval t = range.Start(); // Output the sample _ftprintf(pStream, _T("%s\t\t\t%s %d\t%s\n"), indent.data(), ID_FLOAT_KEY, t, Format(value)); // If the end of the controller validity is beyond the // range of the animation if (range.End() > cont->GetTimeRange(TIMERANGE_ALL).End()) { break; } else { t = (range.End()/GetTicksPerFrame()+GetKeyFrameStep()) * GetTicksPerFrame(); } } } _ftprintf(pStream, _T("%s\t\t}\n"), indent.data()); } }
int LinkTimeControl::PaintFCurves( ParamDimensionBase *dim, HDC hdc, Rect& rcGraph, Rect& rcPaint, float tzoom, int tscroll, float vzoom, int vscroll, DWORD flags ) { const int n = NumKeys(); if ( n == 0 ) return 0; Interval valid; int h = rcGraph.h()-1; HPEN dpen,spen; BOOL init=FALSE; Interval range = GetTimeRange(TIMERANGE_ALL); SetBkMode(hdc,TRANSPARENT); dpen = CreatePen(PS_DOT,0,GetColorManager()->GetColor(kFunctionCurveFloat)); spen = CreatePen(PS_SOLID,0,GetColorManager()->GetColor(kFunctionCurveFloat)); SIZE size; GetTextExtentPoint( hdc, _T("0"), 1, &size ); float val; TimeValue leftTime = ScreenToTime(rcPaint.left,tzoom,tscroll); TimeValue rightTime = ScreenToTime(rcPaint.right,tzoom,tscroll); int x, y; // dotted line to left of keys if ( leftTime < range.Start() ) { SelectObject(hdc,dpen); GetValue(range.Start(),&val,valid); y = ValueToScreen(dim->Convert(val),h,vzoom,vscroll); MoveToEx(hdc,rcPaint.left,y,NULL); LineTo(hdc,TimeToScreen(range.Start(),tzoom,tscroll),y); } SelectObject(hdc,spen); // first node text { TimeValue t = GetKeyTime( 0 ); if ( t >= leftTime && t <= rightTime ) { GetValue(t,&val,valid); y = ValueToScreen(dim->Convert(val),h,vzoom,vscroll); x = TimeToScreen(t,tzoom,tscroll); INode* node = fOwner->GetNode( 0 ); DLTextOut( hdc, x, y-1-size.cy, node ? node->GetName() : _T("World") ); } } // solid line between keys for ( int i=1; i<n; ++i ) { TimeValue t0 = GetKeyTime( i-1 ); TimeValue t1 = GetKeyTime( i ); if ( t1 < leftTime || t0 > rightTime ) continue; GetValue(t0,&val,valid); y = ValueToScreen(dim->Convert(val),h,vzoom,vscroll); MoveToEx(hdc,TimeToScreen(t0,tzoom,tscroll),y,NULL); x = TimeToScreen(t1,tzoom,tscroll); LineTo(hdc,x,y); GetValue(t1,&val,valid); y = ValueToScreen(dim->Convert(val),h,vzoom,vscroll); LineTo(hdc,x,y); INode* node = fOwner->GetNode( i ); DLTextOut( hdc, x, y-1-size.cy, node ? node->GetName() : _T("World") ); } // dotted line to right of keys if ( rightTime > range.End() ) { SelectObject(hdc,dpen); GetValue(range.End(),&val,valid); y = ValueToScreen(dim->Convert(val),h,vzoom,vscroll); MoveToEx(hdc,TimeToScreen(range.End(),tzoom,tscroll),y,NULL); LineTo(hdc,rcPaint.right,y); } SelectObject( hdc, spen ); HBRUSH hUnselBrush = CreateSolidBrush(GetColorManager()->GetColor(kTrackbarKeys)); HBRUSH hSelBrush = CreateSolidBrush(GetColorManager()->GetColor(kTrackbarSelKeys)); // render keys themselves for ( int i=0; i<n; ++i ) { TimeValue t = GetKeyTime( i ); if ( t < leftTime || t > rightTime ) continue; GetValue(t,&val,valid); y = ValueToScreen(dim->Convert(val),h,vzoom,vscroll); x = TimeToScreen(t,tzoom,tscroll); SelectObject( hdc, IsKeySelected( i ) ? hSelBrush : hUnselBrush ); Rectangle(hdc,x-3,y-3,x+3,y+3); } SetBkMode(hdc,OPAQUE); SelectObject(hdc,GetStockObject(BLACK_PEN)); DeleteObject(spen); DeleteObject(dpen); DeleteObject(hUnselBrush); DeleteObject(hSelBrush); return 0; }