428 lines (358 with data), 15.0 kB
#ifndef _ANYMOCAP_CREATE_MARKER_DRIVER_CLASS_ANY_
#define _ANYMOCAP_CREATE_MARKER_DRIVER_CLASS_ANY_
/*
---
group: MoCap
topic: Markers
descr: Creates MoCap markers and links them to the C3D file data.
---
See below for more details
*/
// This template is used by all the MoCap models to link the model to the C3D file data.
// It creates a marker driver on the specified segment on the model and creates the
// necessary drivers to link the marker position to the C3D file data.
//
// The class template has special options to add optimizations of the marker positions
// and to add filters to the marker positions.
//
// :::{rubric} For example
// :::
//
// :::{code-block} AnyScript
// CreateMarkerDriver RPSI (
// MarkerPlacement=Trunk.Segments.PelvisSeg,
// PlaceMarkerAt=Right.PSIS,
// OptX=OFF, OptY=OFF, OptZ=ON,
// UseC3DWeightResiduals=ON
// ) = {
// sRelOpt = {-0.025,0,0.0};
// };
// :::
//
#class_template CreateMarkerDriver (
MarkerName=_NOT_DEFINED_,
MarkerPlacement,
WeightX=1, WeightY=1, WeightZ=1,
OptX=0, OptY=0, OptZ=0,
ScaleMarkerPosOnOff = 1,
FilterCutOffFrequency = 0,
FilterOrder = 2,
UseC3DWeightResiduals = 0,
PARAMETER_OPT_STUDY = Main.Studies.ParameterIdentification,
C3D_OBJECT = Main.ModelSetup.C3DFileData,
BODY_MODEL_FOLDER = Main.HumanModel.BodyModel,
PlaceMarkerAt = MoCapMarkerFrameAMMR24,
USE_BVH_INPUT = 0,
BVH_OBJECT = Main.ModelSetup.BVHFileData,
MarkerPlacementBVH = REQUIRED_FOR_BVH_INPUT,
DRAW_SCALE = 1,
SKIP_MARKER_EXIST_CHECK = 0,
)
{
//Class template arguments:
//---------------------------
// CreateMarkerDriver#MarkerPlacement
// (Required) The segment on which the marker is place, relative to the Body model.
// CreateMarkerDriver#PlaceMarkerAt
// Specifies which coordinate system on the segment the marker is place.
// This is used when placing markers relative to bony landmarks. (Defaults to `AnatomicalFrame`)
// CreateMarkerDriver#WeightX
// The weight of soft driver for the marker in X direction
// CreateMarkerDriver#WeightY
// The weight of soft driver for the marker in Y direction
// CreateMarkerDriver#WeightZ
// The weight of soft driver for the marker in Z direction
// CreateMarkerDriver#OptX
// Switch to determine if the markers positions can be optimized in the X direction
// CreateMarkerDriver#OptY
// Switch to determine if the markers positions can be optimized in the Y direction
// CreateMarkerDriver#OptZ
// Switch to determine if the markers positions can be optimized in the Z direction
// CreateMarkerDriver#ScaleMarkerPosOnOff
// Switch to indicate if the marker position should be scaled with the segment
// which it is attached. If the marker is located relative the segments original
// this should be ON. If the marker is located relative to a bony landmark it
// may make sense to turn this off.
// CreateMarkerDriver#FilterCutOffFrequency
// If set to something different that zero, it will use a special low pass filter
// on this marker, instead of using the default filter applied by the AnyInputC3D
// object.
// CreateMarkerDriver#FilterOrder
// Filter order to use if FilterCutOffFrequency > 0
// CreateMarkerDriver#MarkerName
// The name of marker in the C3D file. It defaults to the name of the class template.
// CreateMarkerDriver#UseC3DWeightResiduals
// Switch to specify if the Marker residual value in the C3D file should be
// used when creating weights for the marker. This is can be used to automatically
// set the weight of the marker to zero when the marker drops out.
// CreateMarkerDriver#PARAMETER_OPT_STUDY
// Can be used to specify which optimization study marker design values should be
// added. It is useful in advanced cases where multiple marker optimization studies
// are used.
// CreateMarkerDriver#C3D_OBJECT
// Specifies from which C3D object to link the markers. This only for advanced cases
// using multiple C3D files for input.
// CreateMarkerDriver#BODY_MODEL_FOLDER
// Specifies the folder where the body model is located. This is only for advanced
// cases where the body model is not located in the default location.
// CreateMarkerDriver#USE_BVH_INPUT
// Switch to specify if the marker should be linked to a BVH file instead of a C3D file.
// CreateMarkerDriver#BVH_OBJECT
// Specifies from which BVH object to link the markers. This only for advanced cases
// using multiple BVH files for input.
// CreateMarkerDriver#MarkerPlacementBVH
// Specifies the segment on which the marker is place, relative to the Body model.
// This is only used when using BVH input.
// CreateMarkerDriver#DRAW_SCALE
// Specifies the scale of the marker in the model view. This is only used for
// visualization purposes.
// CreateMarkerDriver#SKIP_MARKER_EXIST_CHECK
// Disable the check if the marker exists in the C3D file. This switch must be
// enabled if you model is structured so markers are created
// before the AnyInputC3D file have been defined. (Defaults to 0)
// #if MarkerName != _NOT_DEFINED_
// AnyInt Deprecated_MarkerName_argument = warn(0, strformat("\n"+
// "------------------------------------------------------------------------------------------------------\n"+
// " The "MarkerName" argument to CreateDriver is deprecated. Just give the class template the same \n"+
// " name as the marker. \n"+
// "-------------------------------------------------------------------------------------------------------\n")
// );
//
// #endif
#if USE_BVH_INPUT
#if MarkerName != _NOT_DEFINED_
#if MarkerName != __NAME__
AnyMessage NotSupported_MarkerName_argument = {
TriggerPreProcess = On;
Type = MSG_ErrorFatal;
Message = strformat("\n"+
"------------------------------------------------------------------------------------------------------\n"+
" The "MarkerName" can't be specified for the BVH based models. \n"+
" Just remove the MarkerName argument to the class template. \n"+
"-------------------------------------------------------------------------------------------------------\n");
};
#endif
#endif
#endif
#if USE_BVH_INPUT == 0
#if SKIP_MARKER_EXIST_CHECK == 0
AnyMessage TestMarkerExist ={
#if MarkerName == _NOT_DEFINED_
AnyString MarkerLabel = #__NAME__;
#else
AnyString MarkerLabel = #MarkerName;
#endif
// Note: if you get a ERROR: " 'PointLabels' : Identifier cannot be resolved "
// This is because you create a marker earlier than the C3D file objects
// is created. For example by creating the marker directly in the "TrialSpecificData.any" file
// In that case set the class-template argument 'SKIP_MARKER_EXIST_CHECK=1', as a workaround.
TriggerPreProcess = not(sum(eqfun(Main.ModelSetup.C3DFileData.PointLabels, MarkerLabel)));
Type=MSG_Error;
Message = "Marker: " + strquote(MarkerLabel) + " does not exist in the c3d file";
};
#endif
#endif
#var AnyVar ConstMarkerWeightX = WeightX;
#var AnyVar ConstMarkerWeightY = WeightY;
#var AnyVar ConstMarkerWeightZ = WeightZ;
#if (UseC3DWeightResiduals == 1) & (USE_BVH_INPUT == 0)
AnyFunSquareWaveThreshold MarkerWeightsFun =
{
#var dT = {C3D_OBJECT.WeightTransitionTime};
#if MarkerName == _NOT_DEFINED_
T = C3D_OBJECT.Points.Markers.__NAME__.PosInterpol.T;
#var Data = C3D_OBJECT.Points.Markers.__NAME__.Residual;
#else
T = C3D_OBJECT.Points.Markers.MarkerName.PosInterpol.T;
#var Data = C3D_OBJECT.Points.Markers.MarkerName.Residual;
#endif
OutputValues =
{{0, .ConstMarkerWeightX },
{0, .ConstMarkerWeightY },
{0, .ConstMarkerWeightZ}};
#var Threshold = 0.0;
#var TType = {TransitionStart, TransitionEnd};
};
#else
AnyFunConst MarkerWeightsFun =
{
Value = {.ConstMarkerWeightX , .ConstMarkerWeightY , .ConstMarkerWeightZ };
};
#endif
#var AnyObjectPtrVar MarkerWeightsPtr = &MarkerWeightsFun;
// CreateMarkerDriver
/// Position of the marker within its local reference frame
#var AnyVec3 sRelOpt;
#if USE_BVH_INPUT
// CreateMarkerDriver
/// Position of the marker on the BVH stick figure model. This is only
/// used when using BVH input.
#var AnyVec3 sRelOnBVH = {0,0,0};
#endif
#var AnyVec3 sRelOptDelta = {0, 0, 0};
#if OptX ==0 & OptY == 0 & OptZ == 0
AnyVec3 sRelOptEdit = DesignVar(sRelOptDelta); //make it a design var ! because it will not be otherwise
#else
AnyVec3 sRelOptEdit = sRelOptDelta;
#endif
Main.ModelSetup.Macros={
AnyStringVar Set##__NAME__ = ("classoperation "+ CompleteNameOf(...sRelOptEdit) + " " + strquote("Set Value") + strformat ("\n")+ "classoperation Main " + strquote("Update Values") + strformat ("\n"));
};
Main.ModelSetup.ParameterIdentification = {
AnyDesVar __NAME__##_X = { Val = ....sRelOptEdit[0];
#var Min=-100;
#var Max=100;
};
AnyDesVar __NAME__##_Y = {
Val = ....sRelOptEdit[1];
#var Min=-100;
#var Max=100;
};
AnyDesVar __NAME__##_Z = {
Val = ....sRelOptEdit[2];
#var Min=-100;
#var Max=100;
};
};
AnyFolder &MarkerPlacementSegment = BODY_MODEL_FOLDER.MarkerPlacement;
MarkerPlacementSegment = {
AnyRefNode __NAME__##_Marker ={
#if ScaleMarkerPosOnOff == 1
AnyVec3 MarkerOffset = (.GeomScale(..sRelOpt) + ..sRelOptEdit )*.ScalingNode.ARel' ;
sRel = .PlaceMarkerAt.sRel + MarkerOffset;
ARel= .ScalingNode.ARel;
#else
sRel = .PlaceMarkerAt.sRel + (..sRelOpt + ..sRelOptEdit )*.PlaceMarkerAt.ARel';
ARel= .PlaceMarkerAt.ARel;
#endif
// This was an attempt to allow PlaceMarkerAt to be anywhere and not only
// a RefNode on the segments.
// AnyFunTransform3DLinRef Transform2SegmentFrame = {
// AnyVec3 test1 = ..PlaceMarkerAt.sRel;
// AnyMat33 test2 = ..PlaceMarkerAt.ARel;
// Ref = &..PlaceMarkerAt;
// };
// sRel = Transform2SegmentFrame({0.0,0,0}) + MarkerOffset;
AnyFolder Arrows = {
// This folder is left for backwards compotability
#var AnyVar size = DRAW_SCALE*0.05;
};
AnyDrawVector Arrow_X = {
AnyInt is_optimized = eqfun(OptX,1);
Vec = {size,0, 0};
#include "DrawVector.any"
#var Text="X";
};
AnyDrawVector Arrow_Y = {
AnyInt is_optimized = eqfun(OptY,1);
Vec = {0,size, 0};
#include "DrawVector.any"
#var Text="Y";
};
AnyDrawVector Arrow_Z = {
AnyInt is_optimized = eqfun(OptZ,1);
Vec = {0,0,size};
#include "DrawVector.any"
#var Text="Z";
};
}; //MarkerName
};// InsertionNode
AnyKinDriverMarker Driver = {
AnyDrawKinMeasure Draw = {
#if UseC3DWeightResiduals
#var Visible = On;// iffun(bool(sum(.WeightPos)), On, Off);
#else
#var Visible = On;
#endif
#var Opacity = iffun(bool(sum(.WeightPos)), 1.0, 0.2) * bool(sum(.WeightPos));
#var Label = Off;
#var Size = DRAW_SCALE*0.01;
#if USE_BVH_INPUT
#var Line = DesignVar(Off);
#else
#var Line = On;
#endif
};
#if UseC3DWeightResiduals
AnyDrawKinMeasure DrawDroppedOutMarker = {
#var Visible = On; //iffun(bool(sum(.WeightPos)), Off, On);
#var Label = Off;
#var Size = DRAW_SCALE*0.01;
#var Opacity = 0.5 * not(bool(sum(.WeightPos)));
RGB1 = {0.4, 0.4, 0.4};
RGB3 = {0.4, 0.4, 0.4};
};
#endif
Linear.Ref=0;
AnyRefFrame &MarkerRef = BODY_MODEL_FOLDER.MarkerPlacement.__NAME__##_Marker;
#if USE_BVH_INPUT
AnyFolder &MarkerDataRef = BVH_OBJECT.Markers.__NAME__;
#else
#if MarkerName == _NOT_DEFINED_
AnyFolder &MarkerDataRef = C3D_OBJECT.Points.Markers.__NAME__;
#else
AnyFolder &MarkerDataRef = C3D_OBJECT.Points.Markers.MarkerName;
#endif
#endif
#if FilterCutOffFrequency > 0
/// A lowpass butterworth filter
AnyFunButterworthFilter LowPassFilter =
{
#var FilterForwardBackwardOnOff = On;
#var AutomaticInitialConditionOnOff = On;
N = FilterOrder;
W = {1/(C3D_OBJECT.Header.VideoFrameRate*0.5)*FilterCutOffFrequency };
Type = LowPass;
};
/// Interpolation function of the lowpass filtered data
AnyFunInterpol FilteredPosInterpol =
{
#var Type = Bspline;
BsplineOrder =4;
T = .MarkerDataRef.PosInterpol.T;
Data = .LowPassFilter(.MarkerDataRef.Pos');
};
#else
AnyParamFun &InterpolRef = MarkerDataRef.PosInterpol;
#endif
WeightFun={.MarkerWeightsPtr};
};
PARAMETER_OPT_STUDY ={
#if OptX ==1
AnyDesVar &__NAME__##_X = Main.ModelSetup.ParameterIdentification.__NAME__##_X;
#endif
#if OptY ==1
AnyDesVar &__NAME__##_Y = Main.ModelSetup.ParameterIdentification.__NAME__##_Y;
#endif
#if OptZ ==1
AnyDesVar &__NAME__##_Z = Main.ModelSetup.ParameterIdentification.__NAME__##_Z;
#endif
};
#if USE_BVH_INPUT
BVH_OBJECT.Markers = {
AnyVirtualMarkerBVH __NAME__ = {
RefFramePtr = &MarkerPlacementBVH.__NAME__;
};
};
//AnyFolder &MarkerInsertionNodeBVH = MarkerPlacementBVH;
MarkerPlacementBVH =
{
AnyRefNode __NAME__ = {
//sRel = ..sRelOnBVH;
#if MarkerName == _NOT_DEFINED_
sRel = Main.ModelSetup.MocapDrivers.__NAME__.sRelOnBVH ;
#else
sRel = Main.ModelSetup.MocapDrivers.MarkerName.sRelOnBVH ;
#endif
AnyDrawNode drw_node =
{
#var RGB = {0, 1, 0};
#var ScaleXYZ = 0.015*{1, 1, 1};
Visible = BVH_OBJECT.ModelDrawOnOff;
};
};
};//
//Main.ModelSetup.BVHFileData.Markers.MarkerName.
#endif
}; // End of InsertSegmentClass
#endif