20#include <Inventor/SbSphere.h>
22#include <Inventor/nodes/SoNode.h>
23#include <Inventor/nodes/SoCamera.h>
24#include <Inventor/nodes/SoPerspectiveCamera.h>
25#include <Inventor/nodes/SoOrthographicCamera.h>
26#include <Inventor/nodes/SoGroup.h>
28#include <Inventor/actions/SoSearchAction.h>
29#include <Inventor/actions/SoGetBoundingBoxAction.h>
30#include <Inventor/actions/SoGetMatrixAction.h>
32#include <Inventor/sensors/SoTimerSensor.h>
51 SbMatrix & matrix,SbMatrix & inverse);
105 SoSFVec3f & position, SoSFFloat & nearDistance,
106 SoSFFloat & farDistance, SoSFFloat & focalDistance,
114 static std::map<SoCamera*,VP1CameraHelper*>
helpers;
119 double duration_in_secs );
127 const SbVec3f& lookat = SbVec3f(999,999,999),
const SbVec3f& upvec = SbVec3f(999,999,999) );
129 const SbVec3f& lookat = SbVec3f(999,999,999),
const SbVec3f& upvec = SbVec3f(999,999,999) );
133 const SbVec3f& lookat = SbVec3f(999,999,999),
const SbVec3f& upvec = SbVec3f(999,999,999) );
135 void die(
bool abnormal =
true)
141 theclass->animationFinishedAbnormally();
152 std::map<SoCamera*,VP1CameraHelper*>::iterator it =
Imp::helpers.find(
m_d->camera);
155 m_d->instance_invalid =
true;
156 m_d->camera->unrefNoDelete();
165 const QString& outputdir,
169 const QString& prefix )
172 VP1Msg::messageDebug(
"VP1CameraHelper::setOutputImagesMode ERROR: Bad input. Null render area.");
176 VP1Msg::messageDebug(
"VP1CameraHelper::setOutputImagesMode ERROR: Bad input. Bad FPS = "+QString::number(fps));
179 if (!QDir(outputdir).
exists()) {
180 VP1Msg::messageDebug(
"VP1CameraHelper::setOutputImagesMode ERROR: Bad input. Output dir "+outputdir+
" does not exist.");
185 +QString::number(
width)+
"x"+QString::number(height));
188 if (prefix.isEmpty()) {
193 m_d->outputdir = outputdir;
195 m_d->height = height;
196 m_d->prefix = prefix;
197 m_d->renderArea = ra;
203 : QObject(0),
m_d(new
Imp)
207 m_d->forceCircular =
false;
209 std::map<SoCamera*,VP1CameraHelper*>::iterator it =
Imp::helpers.find(camera);
211 it->second->forceAbort();
214 m_d->sceneroot=sceneroot;
217 m_d->ntotframes = -1;
223 m_d->seekdistance = 50.0f;
224 m_d->seekdistanceabs = FALSE;
225 m_d->seektopoint = TRUE;
226 m_d->seekperiod = 2.0f;
227 m_d->inseekmode = FALSE;
230 m_d->searchaction =
new SoSearchAction;
231 m_d->matrixaction =
new SoGetMatrixAction(SbViewportRegion(100,100));
234 m_d->sceneroot->ref();
235 m_d->camera_ref=
m_d->camera->getRefCount();
236 m_d->instance_invalid =
false;
238 if (!camera||!sceneroot)
239 m_d->instance_invalid=
true;
247 if (
m_d->seeksensor->isScheduled())
248 m_d->seeksensor->unschedule();
249 delete m_d->seeksensor;
250 m_d->searchaction->reset();
delete m_d->searchaction;
251 delete m_d->matrixaction;
252 SoCamera * cam =
m_d->camera;
254 m_d->sceneroot->unref();
257 std::map<SoCamera*,VP1CameraHelper*>::iterator it =
Imp::helpers.find(cam);
267 std::map<SoCamera*,VP1CameraHelper*>::iterator it =
Imp::helpers.find(camera);
273 helper->forceAbort();
302 const QByteArray& camstate,
303 double duration_in_secs,
double clipVolPercent,
double lastClipVolPercent,
bool varySpeed,
310 helper->m_d->actual_animatedZoomToCameraState( camstate,duration_in_secs );
311 helper->m_d->varySpeed=varySpeed;
312 helper->m_d->clipVol_startPercentage=lastClipVolPercent;
313 helper->m_d->clipVol_percentage=lastClipVolPercent;
314 helper->m_d->clipVol_endPercentage=clipVolPercent;
315 helper->m_d->forceCircular = forceCircular;
321 double duration_in_secs )
323 if (!
camera||camstate==QByteArray()||duration_in_secs<0.0) {
337 const bool perspective(
camera->getTypeId().isDerivedFrom(SoPerspectiveCamera::getClassTypeId()));
338 SoCamera * targetcam = perspective ?
static_cast<SoCamera*
>(
new SoPerspectiveCamera)
339 :
static_cast<SoCamera*
>(
new SoOrthographicCamera);
341 QByteArray ba = camstate;
372 SoPath * path,
double duration_in_secs,
double ,
double slack,
373 const SbVec3f& lookat,
const SbVec3f& upvec,
bool varySpeed,
377 helper->m_d->actual_animatedZoomToPath( path,duration_in_secs, slack, lookat, upvec );
378 helper->m_d->varySpeed=varySpeed;
379 helper->m_d->forceCircular = forceCircular;
385 const SbVec3f& lookat,
const SbVec3f& upvec )
392 if (slack<=0.0||duration_in_secs<0.0) {
403 SbViewportRegion dummyvp;
404 SoGetBoundingBoxAction mybboxaction(dummyvp);
405 mybboxaction.apply(path);
406 SbBox3f box = mybboxaction.getBoundingBox();
414 SoNode*subtreeroot,
double duration_in_secs,
double ,
double ,
double slack,
415 const SbVec3f& lookat,
const SbVec3f& upvec,
bool varySpeed,
419 helper->m_d->actual_animatedZoomToSubTree( subtreeroot,duration_in_secs,slack,lookat,upvec );
420 helper->m_d->varySpeed=varySpeed;
421 helper->m_d->forceCircular = forceCircular;
427 const SbVec3f& lookat,
const SbVec3f& upvec)
434 if (slack<=0.0||duration_in_secs<0.0) {
444 SoSearchAction mysearchaction;
445 mysearchaction.setNode(subtreeroot);
447 SoPath * mypath = mysearchaction.getPath();
449 VP1Msg::messageDebug(
"VP1CameraHelper WARNING: Cancelled operation due to failure to locate path to node.");
455 mysearchaction.reset();
461 const SbBox3f& box,
double duration_in_secs,
double ,
double slack,
462 const SbVec3f& lookat,
const SbVec3f& upvec ,
bool varySpeed,
467 helper->m_d->actual_animatedZoomToBBox( box,duration_in_secs,slack,lookat,upvec );
468 helper->m_d->varySpeed=varySpeed;
469 helper->m_d->forceCircular = forceCircular;
475 const SbVec3f& lookat,
const SbVec3f& upvec )
482 if (slack<=0.0||duration_in_secs<0.0) {
496 SbBox3f actualbbox = box;
498 float minx, miny, minz, maxx, maxy, maxz;
499 actualbbox.getBounds (minx, miny, minz, maxx, maxy, maxz);
500 float dx(maxx-minx), cx(0.5*(maxx+minx));
501 float dy(maxy-miny), cy(0.5*(maxy+miny));
502 float dz(maxz-minz), cz(0.5*(maxz+minz));
503 actualbbox.setBounds (cx-0.5*slack*dx, cy-0.5*slack*dy, cz-0.5*slack*dz,
504 cx+0.5*slack*dx, cy+0.5*slack*dy, cz+0.5*slack*dz);
509 SoSFVec3f target_position;
510 SoSFFloat target_nearDistance;
511 SoSFFloat target_farDistance;
512 SoSFFloat target_focalDistance;
513 bool currentcamera_isperspective;
514 SoSFFloat target_ortho_height;
518 bool changeorient(
false);
519 if (lookat==SbVec3f(999,999,999)&&upvec==SbVec3f(999,999,999)) {
524 SbVec3f actual_lookat(lookat);
525 if (lookat==SbVec3f(999,999,999)) {
527 SbRotation camrot =
camera->orientation.getValue();
528 actual_lookat = SbVec3f(0.0f, 0.0f, -1.0f);
529 camrot.multVec(actual_lookat, actual_lookat);
531 SbVec3f actual_upvec(upvec);
532 if (upvec==SbVec3f(999,999,999)) {
534 SbRotation camrot =
camera->orientation.getValue();
535 actual_upvec = SbVec3f(0.0f, 1.0f, 0.0f);
536 camrot.multVec(actual_upvec, actual_upvec);
551 target_position, target_nearDistance,
552 target_farDistance, target_focalDistance,
553 currentcamera_isperspective,target_ortho_height)) {
571 SoOrthographicCamera * orthocam =
static_cast<SoOrthographicCamera*
>(
camera);
593 SbVec3f targetpoint,
double duration_in_secs,
double ,
bool varySpeed,
597 helper->m_d->actual_animatedZoomToPoint( targetpoint,duration_in_secs );
598 helper->m_d->varySpeed=varySpeed;
599 helper->m_d->forceCircular = forceCircular;
606 seekperiod =
static_cast<float>(duration_in_secs);
611 seeksensor->setBaseTime(SbTime::getTimeOfDay());
626 if (duration_in_secs<0.0) {
655 SbMatrix cameramatrix, camerainverse;
660 camerainverse.multVecMatrix(targetpoint, targetpoint);
663 fd *= (targetpoint -
camera->position.getValue()).length()/100.0f;
664 camera->focalDistance = fd;
672 camera->orientation.getValue().multVec(SbVec3f(0, 0, -1), olddir);
673 SbRotation diffrot(olddir, dir);
689 if (d->instanceInvalid() || d->lastParsChanged()) {
694 SoTimerSensor * sensor =
static_cast<SoTimerSensor *
>(s);
700 if (d->ntotframes<0) {
702 d->ntotframes = std::max(1,
static_cast<int>((d->fps)*(d->seekperiod)+0.5));
708 t = ( (d->iframe+1==d->ntotframes) ? 1.0f :
static_cast<float>((d->iframe+1)*1.0/(d->ntotframes*1.0)) );
712 SbTime currenttime = SbTime::getTimeOfDay();
713 t = float((currenttime - sensor->getBaseTime()).getValue()) / d->seekperiod;
716 if ((t > 1.0f) || (d->fps<=0&&(t + sensor->getInterval().getValue()/d->seekperiod > 1.0f))) t = 1.0f;
718 d->clipVol_percentage = d->clipVol_startPercentage+(d->clipVol_endPercentage - d->clipVol_startPercentage)*t;
719 emit d->theclass->clipVolumePercentageOfATLAS(d->clipVol_percentage);
721 bool end = (t == 1.0f);
724 t = (float) ((1.0 - cos(
M_PI*t)) * 0.5);
726 if (d->camera->position.getValue()!=d->cameraendposition) {
727 double rBegin=d->camerastartposition.length();
728 double rEnd=d->cameraendposition.length();
729 double lengthRatio = rEnd/rBegin;
730 SbVec3f u = d->camerastartposition; u.normalize();
731 SbVec3f v = d->cameraendposition; v.normalize();
732 double angle = acos(u.dot(v));
734 double r = rBegin + (rEnd-rBegin)*t;
735 SbVec3f w = u.cross(v);
736 SbRotation R(w,t*
angle);
740 d->camera->position=
z;
742 d->camera->position = d->camerastartposition + (d->cameraendposition - d->camerastartposition) * t;
745 if (d->camera->orientation.getValue()!=d->cameraendorient)
746 d->camera->orientation = SbRotation::slerp(d->camerastartorient,d->cameraendorient,t);
754 if (d->camera->focalDistance!=d->cameraend_focalDistance)
755 d->camera->focalDistance.setValue(d->camerastart_focalDistance.getValue()*(1-t) + d->cameraend_focalDistance.getValue()*t);
756 if (!d->camera_isperspective) {
757 SoOrthographicCamera * orthocam =
static_cast<SoOrthographicCamera*
>(d->camera);
758 if (orthocam&&orthocam->height!=d->cameraend_ortho_height)
759 orthocam->height.setValue(d->camerastart_ortho_height.getValue()*(1-t) + d->cameraend_ortho_height.getValue()*t);
764 if (d->ntotframes>0) {
765 QString dummy, filename;
767 if (d->seekperiod>0.0) {
770 d->width,d->height,
false);
774 if (!pm.save(filename))
781 if (d->targetCamState!=QByteArray()) {
794 QString& lastOfExistingFiles,
795 QString& nextAvailableFile )
797 lastOfExistingFiles=
"";
801 filename=outputdir+
"/"+prefix+
"_"+QString::number(i++).rightJustified(6,
'0')+
".png";
802 if (!QFile::exists(filename)) {
803 nextAvailableFile=filename;
806 lastOfExistingFiles = filename;
822 VP1Msg::messageDebug(
"VP1CameraHelper WARNING: Cancelled operation due to sceneroot being unref'ed.");
841 matrix = inverse = SbMatrix::identity();
852 SoSFVec3f & position, SoSFFloat & nearDistance,
853 SoSFFloat & farDistance, SoSFFloat & focalDistance,
857 float aspect =
camera->aspectRatio.getValue();
861 if (
camera->getTypeId() == SoPerspectiveCamera::getClassTypeId()) {
863 }
else if (
camera->getTypeId() == SoOrthographicCamera::getClassTypeId()) {
870 SbVec3f cameradirection;
871 camera->orientation.getValue().multVec(SbVec3f(0, 0, -1), cameradirection);
872 position.setValue(box.getCenter() + -cameradirection);
876 bs.circumscribe(box);
877 float radius = bs.getRadius();
882 float aspectradius = radius / (aspect < 1.0f ? aspect : 1.0f);
884 SoPerspectiveCamera * perspcam =
static_cast<SoPerspectiveCamera*
>(
camera);
889 SbVec3f direction = position.getValue() - box.getCenter();
890 (void) direction.normalize();
892 aspectradius + (aspectradius/float(atan(perspcam->heightAngle.getValue())));
893 position.setValue(box.getCenter() + direction * movelength);
898 height = 2 * radius / aspect;
904 SbVec3f direction = position.getValue() - box.getCenter();
905 (void) direction.normalize();
906 position.setValue(box.getCenter() + direction * radius);
912 float distance_to_midpoint = (position.getValue() - box.getCenter()).length();
913 nearDistance = distance_to_midpoint - radius;
914 farDistance = distance_to_midpoint + radius;
921 focalDistance = distance_to_midpoint;
929 const float epsilon = 0.00001f;
932 if (dir.sqrLength()==0.0f||up.sqrLength()==0.0f) {
934 "view and up direction vectors that are not both non-zero");
935 return SbRotation(SbVec3f(0.0f, 0.0f, 1.0f), 0.0f);
943 SbVec3f dir0(0.0f, 0.0f, -1.0f), up0(0.0f, 1.0f, 0.0f);
946 SbRotation rot(dir0,dir);
949 if (fabs(dir.dot(up))>1.0f-epsilon) {
951 "view and up direction vectors that are essentially parallel."
952 " Choosing new arbitrary up direction.");
953 up = dir.cross(SbVec3f(1.0f,1.0f,0.0f));
955 if (fabs(dir.dot(up))>1.0f-epsilon) {
956 up = dir.cross(SbVec3f(1.0f,0.0f,1.0f));
958 if (fabs(dir.dot(up))>1.0f-epsilon) {
973 up = up - dir*(dir.dot(up));
974 if (up.length()<epsilon) {
981 rot.multVec(up0,up0);
982 up0 = up0 - dir*(dir.dot(up0));
983 if (up0.length()<epsilon) {
991 return rot*SbRotation(up0,up);
char data[hepevt_bytes_allocation_ATLAS]
double angle(const GeoTrf::Vector2D &a, const GeoTrf::Vector2D &b)
SbRotation last_cameraorient
SoSFFloat camerastart_focalDistance
SoSearchAction * searchaction
void actual_animatedZoomToBBox(const SbBox3f &box, double duration_in_secs=1.0, double slack=1.0, const SbVec3f &lookat=SbVec3f(999, 999, 999), const SbVec3f &upvec=SbVec3f(999, 999, 999))
bool getCameraParametersForBBox(const SbBox3f &box, SoSFVec3f &position, SoSFFloat &nearDistance, SoSFFloat &farDistance, SoSFFloat &focalDistance, bool &isPerspective, SoSFFloat &height)
double clipVol_startPercentage
void actual_animatedZoomToPath(SoPath *path, double duration_in_secs=1.0, double slack=1.0, const SbVec3f &lookat=SbVec3f(999, 999, 999), const SbVec3f &upvec=SbVec3f(999, 999, 999))
VP1CameraHelper * theclass
static SbRotation cameraOrientation(SbVec3f dir, SbVec3f up)
SoSFFloat cameraend_focalDistance
bool lastParsChanged() const
void actual_animatedZoomToPoint(SbVec3f, double duration_in_secs=1.0)
SoSFFloat cameraend_ortho_height
double clipVol_lastPercentage
SoSFFloat cameraend_nearDistance
SbVec3f cameraendposition
VP1ExaminerViewer * renderArea
SbRotation camerastartorient
SbVec3f last_cameraposition
SoSFFloat cameraend_farDistance
QByteArray targetCamState
SoTimerSensor * seeksensor
void actual_animatedZoomToCameraState(const QByteArray &camstate, double duration_in_secs)
static void seeksensorCB(void *data, SoSensor *)
SbRotation cameraendorient
SoSFFloat camerastart_farDistance
void die(bool abnormal=true)
static std::map< SoCamera *, VP1CameraHelper * > helpers
SoSFFloat camerastart_nearDistance
bool camera_isperspective
void actual_animatedZoomToSubTree(SoNode *subtreeroot, double duration_in_secs=1.0, double slack=1.0, const SbVec3f &lookat=SbVec3f(999, 999, 999), const SbVec3f &upvec=SbVec3f(999, 999, 999))
void getCameraCoordinateSystem(SoCamera *cameraarg, SoNode *root, SbMatrix &matrix, SbMatrix &inverse)
double clipVol_percentage
void startSeekTimer(double duration_in_secs)
SbVec3f camerastartposition
double clipVol_endPercentage
SoSFFloat last_camera_ortho_height
SoSFFloat camerastart_ortho_height
SoGetMatrixAction * matrixaction
static VP1CameraHelper * animatedZoomToPath(SoCamera *camera, SoGroup *sceneroot, SoPath *path, double duration_in_secs=1.0, double clipVolPercent=100.0, double slack=1.0, const SbVec3f &lookat=SbVec3f(999, 999, 999), const SbVec3f &upvec=SbVec3f(999, 999, 999), bool varySpeed=true, bool forceCircular=false)
static VP1CameraHelper * animatedZoomToSubTree(SoCamera *camera, SoGroup *sceneroot, SoNode *subtreeroot, double duration_in_secs=1.0, double clipVolPercent=100.0, double lastClipVolPercent=100.0, double slack=1.0, const SbVec3f &lookat=SbVec3f(999, 999, 999), const SbVec3f &upvec=SbVec3f(999, 999, 999), bool varySpeed=true, bool forceCircular=false)
void setOutputImagesMode(VP1ExaminerViewer *ra, const QString &outputdir, int width=1024, int height=768, double fps=24, const QString &prefix="vp1_frame")
static void getLastAndNextFrameFileNames(const QString &outputdir, const QString &prefix, QString &lastOfExistingFiles, QString &nextAvailableFile)
static VP1CameraHelper * animatedZoomToCameraState(SoCamera *camera, SoGroup *sceneroot, const QByteArray &camstate, double duration_in_secs=1.0, double clipVolPercent=100.0, double lastClipVolPercent=100.0, bool varySpeed=true, bool forceCircular=false)
virtual ~VP1CameraHelper()
static VP1CameraHelper * animatedZoomToBBox(SoCamera *camera, SoGroup *sceneroot, const SbBox3f &box, double duration_in_secs=1.0, double clipVolPercent=100.0, double slack=1.0, const SbVec3f &lookat=SbVec3f(999, 999, 999), const SbVec3f &upvec=SbVec3f(999, 999, 999), bool varySpeed=true, bool forceCircular=false)
static VP1CameraHelper * animatedZoomToPoint(SoCamera *camera, SoGroup *sceneroot, SbVec3f, double duration_in_secs=1.0, double clipVolPercent=100.0, bool varySpeed=true, bool forceCircular=false)
static void abortAnyCurrentZoom(SoCamera *camera)
VP1CameraHelper(SoCamera *, SoGroup *)
static void messageVerbose(const QString &)
static void messageDebug(const QString &)
static QPixmap renderToPixmap(VP1ExaminerViewer *ra, int pixels_x, int pixels_y, bool transparent_background=false, double actualRenderedSizeFact=1.0)
static bool deserializeSoCameraParameters(QByteArray &, SoCamera &)
static QString str(const QString &s)
bool exists(const std::string &filename)
does a file exist