// Update ===================================================== XSIPLUGINCALLBACK CStatus sn_squashstretch_op_Update( CRef& in_ctxt ) { OperatorContext ctxt( in_ctxt ); KinematicState parentKine = (CRef)ctxt.GetInputValue(0); CTransformation parentXF = parentKine.GetTransform(); CVector3 parentScl = parentXF.GetScaling(); double blend = ctxt.GetParameterValue(L"blend"); double driver = ctxt.GetParameterValue(L"driver"); double sq_min = ctxt.GetParameterValue(L"sq_min"); double sq_max = ctxt.GetParameterValue(L"sq_max"); double st_min = ctxt.GetParameterValue(L"st_min"); double st_max = ctxt.GetParameterValue(L"st_max"); double sq_y = ctxt.GetParameterValue(L"sq_y"); double sq_z = ctxt.GetParameterValue(L"sq_z"); double st_y = ctxt.GetParameterValue(L"st_y"); double st_z = ctxt.GetParameterValue(L"st_z"); double sq_ratio = smoothstep(clamp(max(sq_max - driver,0) / max(sq_max - sq_min,0.0001),0,1)); double st_ratio = smoothstep(1.0 - clamp(max(st_max - driver,0) / max(st_max - st_min,0.0001),0,1)); sq_y *= sq_ratio; sq_z *= sq_ratio; st_y *= st_ratio; st_z *= st_ratio; parentScl.PutY(parentScl.GetY() * max( 0, 1.0 + sq_y + st_y )); parentScl.PutZ(parentScl.GetZ() * max( 0, 1.0 + sq_z + st_z )); parentScl.LinearlyInterpolate(parentXF.GetScaling(),parentScl,blend); parentXF.SetScaling(parentScl); KinematicState outKine(ctxt.GetOutputTarget()); outKine.PutTransform(parentXF); return CStatus::OK; }
// Update ===================================================== XSIPLUGINCALLBACK CStatus sn_squashstretch2_op_Update( CRef& in_ctxt ) { // Inputs ------------------------- OperatorContext ctxt( in_ctxt ); KinematicState k = (CRef)ctxt.GetInputValue(0); CTransformation t = k.GetTransform(); KinematicState parent_kine = (CRef)ctxt.GetInputValue(1); CTransformation parent_trans = parent_kine.GetTransform(); CVector3 parent_scl = parent_trans.GetScaling(); double blend = ctxt.GetParameterValue(L"blend"); double driver = ctxt.GetParameterValue(L"driver"); double driver_min = ctxt.GetParameterValue(L"driver_min"); double driver_ctr = ctxt.GetParameterValue(L"driver_ctr"); double driver_max = ctxt.GetParameterValue(L"driver_max"); double axis = ctxt.GetParameterValue(L"axis"); double stretch = ctxt.GetParameterValue(L"stretch"); double squash = ctxt.GetParameterValue(L"squash"); // Ratio --------------------------- double st_ratio = clamp(max(driver - driver_ctr, 0) / max(driver_max - driver_ctr, 0.0001), 0,1); double sq_ratio = clamp(max(driver_ctr - driver, 0) / max(driver_ctr - driver_min, 0.0001), 0,1); squash *= sq_ratio; stretch *= st_ratio; CVector3 scl; scl.Set(parent_scl.GetX(), parent_scl.GetY(), parent_scl.GetZ()); if (axis != 0) scl.PutX(parent_scl.GetX() * max( 0, 1.0 + squash + stretch )); if (axis != 1) scl.PutY(parent_scl.GetY() * max( 0, 1.0 + squash + stretch )); if (axis != 2) scl.PutZ(parent_scl.GetZ() * max( 0, 1.0 + squash + stretch )); scl.LinearlyInterpolate(parent_scl, scl, blend); t.SetScaling(scl); KinematicState outKine(ctxt.GetOutputTarget()); outKine.PutTransform(t); return CStatus::OK; }
XSIPLUGINCALLBACK CStatus apply_MomentumConsBallSocket_Execute( CRef& in_ctxt ) { Context ctxt( in_ctxt ); Selection l_pSelection = Application().GetSelection(); // you need to select TWO objects if(l_pSelection.GetCount() != 2) { Application().LogMessage(L"[MOMENTUM] You need to select TWO rigid bodies.",siErrorMsg); return CStatus::Abort; } X3DObject obj1(l_pSelection.GetItem(0)); X3DObject obj2(l_pSelection.GetItem(1)); CRef opRef1,opRef2; opRef1.Set(obj1.GetFullName()+L".kine.global.MomentumKinematics"); if(!opRef1.IsValid()) opRef1.Set(obj1.GetFullName()+L".polymsh.MomentumDeform"); opRef2.Set(obj2.GetFullName()+L".kine.global.MomentumKinematics"); if(!opRef2.IsValid()) opRef2.Set(obj2.GetFullName()+L".polymsh.MomentumDeform"); if(!opRef1.IsValid()) { Application().LogMessage(L"[MOMENTUM] Object "+obj1.GetFullName()+L" is not a bullet rigid body.",siErrorMsg); return CStatus::Abort; } if(!opRef2.IsValid()) { Application().LogMessage(L"[MOMENTUM] Object "+obj1.GetFullName()+L" is not a bullet rigid body.",siErrorMsg); return CStatus::Abort; } // get the transform for the cons CTransformation xfA = obj1.GetKinematics().GetGlobal().GetTransform(); CTransformation xfB = obj2.GetKinematics().GetGlobal().GetTransform(); CVector3 trans; trans.LinearlyInterpolate(xfA.GetTranslation(),xfB.GetTranslation(),0.5); xfA.SetTranslation(trans); // create the constraint object Null consNull1; obj1.AddNull(L"BallSocket_pivot",consNull1); consNull1.GetKinematics().GetGlobal().PutTransform(xfA); consNull1.GetActivePrimitive().PutParameterValue(L"primary_icon", (LONG)2); // create the operator CustomOperator newOp = Application().GetFactory().CreateObject(L"MomentumConsBallSocket"); newOp.AddOutputPort(consNull1.GetKinematics().GetGlobal().GetRef()); newOp.AddInputPort(consNull1.GetKinematics().GetGlobal().GetRef()); newOp.AddInputPort(obj1.GetKinematics().GetGlobal().GetRef()); newOp.AddInputPort(obj2.GetKinematics().GetGlobal().GetRef()); newOp.AddInputPort(opRef1); newOp.AddInputPort(opRef2); newOp.Connect(); // set the expression for the frame! CValueArray args(2); CValue returnVal; args[0] = newOp.GetFullName()+L".frame"; args[1] = L"fc"; Application().ExecuteCommand(L"SetExpr",args,returnVal); return CStatus::OK; }
/////////////////////////////////////////////////////////////// // METHOD /////////////////////////////////////////////////////////////// CStatus splinekine_op_Update( CRef& in_ctxt, int mode = 0 ) { OperatorContext ctxt( in_ctxt ); long count = (LONG)ctxt.GetParameterValue(L"count"); CVector3Array pos(count); CVector3Array tangent(count); CVector3Array rot(count); CDoubleArray roll(count); CVector3Array rotParent(count); CVector3Array scl(count); CTransformation singleXF,singleParentXF; CMatrix3 singleMat; CTransformation modelXF; if(mode == 0) // simple 180 flipping interpolation { for(long i=0;i<count;i++) { singleXF = KinematicState(ctxt.GetInputValue(i)).GetTransform(); singleMat = singleXF.GetRotationMatrix3(); pos[i] = singleXF.GetTranslation(); tangent[i].MulByMatrix3(CVector3(singleXF.GetSclX()*2.5,0,0),singleMat); rot[i] = singleXF.GetRotationXYZAngles(); scl[i] = singleXF.GetScaling(); } modelXF = KinematicState(ctxt.GetInputValue(count)).GetTransform(); } else if(mode == 1) // local rotation X based roll { for(long i=0;i<count;i++) { singleParentXF = KinematicState(ctxt.GetInputValue(i*2+0)).GetTransform(); singleXF = KinematicState(ctxt.GetInputValue(i*2+1)).GetTransform(); roll[i] = singleXF.GetRotX(); singleXF = MapObjectPoseToWorldSpace(singleParentXF,singleXF); singleMat = singleXF.GetRotationMatrix3(); pos[i] = singleXF.GetTranslation(); tangent[i].MulByMatrix3(CVector3(singleXF.GetSclX()*2.5,0,0),singleMat); rot[i] = singleParentXF.GetRotationXYZAngles(); scl[i] = singleXF.GetScaling(); } modelXF = KinematicState(ctxt.GetInputValue(count*2)).GetTransform(); } double u = ctxt.GetParameterValue(L"u"); bool resample = ctxt.GetParameterValue(L"resample"); long subdiv = (LONG)ctxt.GetParameterValue(L"subdiv"); bool absolute = ctxt.GetParameterValue(L"absolute"); double step = 1.0 / max(1,count-1); int index1 = (int)min(count-2,u / step); int index2 = index1+1; int index1temp = index1; int index2temp = index2; double v = (u - step * double(index1)) / step; double vtemp = v; // calculate the bezier CVector3 bezierPos; CVector3 xAxis,yAxis,zAxis; if(!resample) { // straight bezier solve CVector3Array results = bezier4point(pos[index1],tangent[index1],pos[index2],tangent[index2],v); bezierPos = results[0]; xAxis = results[1]; } else if(!absolute) { CVector3Array presample(subdiv); CVector3Array presampletan(subdiv); CDoubleArray samplelen(subdiv); double samplestep = 1.0 / double(subdiv-1); double sampleu = samplestep; presample[0] = pos[index1]; presampletan[0] = tangent[index1]; CVector3 prevsample(presample[0]); CVector3 diff; samplelen[0] = 0; double overalllen = 0; CVector3Array results(2); for(long i=1;i<subdiv;i++,sampleu+=samplestep) { results = bezier4point(pos[index1],tangent[index1],pos[index2],tangent[index2],sampleu); presample[i] = results[0]; presampletan[i] = results[1]; diff.Sub(presample[i],prevsample); overalllen += diff.GetLength(); samplelen[i] = overalllen; prevsample = presample[i]; } // now as we have the sampleu = 0; for(long i=0;i<subdiv-1;i++,sampleu+=samplestep) { samplelen[i+1] = samplelen[i+1] / overalllen; if(v>=samplelen[i] && v <= samplelen[i+1]) { v = (v - samplelen[i]) / (samplelen[i+1] - samplelen[i]); bezierPos.LinearlyInterpolate(presample[i],presample[i+1],v); xAxis.LinearlyInterpolate(presampletan[i],presampletan[i+1],v); break; } } } else { CVector3Array presample(subdiv); CVector3Array presampletan(subdiv); CDoubleArray samplelen(subdiv); double samplestep = 1.0 / double(subdiv-1); double sampleu = samplestep; presample[0] = pos[0]; presampletan[0] = tangent[0]; CVector3 prevsample(presample[0]); CVector3 diff; samplelen[0] = 0; double overalllen = 0; CVector3Array results; for(long i=1;i<subdiv;i++,sampleu+=samplestep) { index1 = (int)min(count-2,sampleu / step); index2 = index1+1; v = (sampleu - step * double(index1)) / step; results = bezier4point(pos[index1],tangent[index1],pos[index2],tangent[index2],v); presample[i] = results[0]; presampletan[i] = results[1]; diff.Sub(presample[i],prevsample); overalllen += diff.GetLength(); samplelen[i] = overalllen; prevsample = presample[i]; } // now as we have the sampleu = 0; for(long i=0;i<subdiv-1;i++,sampleu+=samplestep) { samplelen[i+1] = samplelen[i+1] / overalllen; if(u>=samplelen[i] && u <= samplelen[i+1]) { u = (u - samplelen[i]) / (samplelen[i+1] - samplelen[i]); bezierPos.LinearlyInterpolate(presample[i],presample[i+1],u); xAxis.LinearlyInterpolate(presampletan[i],presampletan[i+1],u); break; } } } // compute the scaling (straight interpolation!) CVector3 scl1; scl1.LinearlyInterpolate(scl[index1temp], scl[index2temp],vtemp); scl1.PutX(1); // scl1.PutX(modelXF.GetSclX()); // We need to find another way to manage global scaling // compute the rotation! CRotation rot1,rot2; rot1.SetFromXYZAngles(rot[index1temp]); rot2.SetFromXYZAngles(rot[index2temp]); CQuaternion quat; quat.Slerp(rot1.GetQuaternion(),rot2.GetQuaternion(),vtemp); rot1.SetFromQuaternion(quat); yAxis.Set(0,1,0); yAxis.MulByMatrix3InPlace(rot1.GetMatrix()); // use directly or project the roll values! if (mode == 1) { double thisRoll = roll[index1temp] * (1.0 - vtemp) + roll[index2temp] * vtemp; rot1.SetFromAxisAngle(xAxis,DegreesToRadians(thisRoll)); yAxis.MulByMatrix3InPlace(rot1.GetMatrix()); } zAxis.Cross(xAxis,yAxis); yAxis.Cross(zAxis,xAxis); xAxis.NormalizeInPlace(); yAxis.NormalizeInPlace(); zAxis.NormalizeInPlace(); CTransformation result; result.SetScaling(scl1); result.SetRotationFromXYZAxes(xAxis,yAxis,zAxis); result.SetTranslation(bezierPos); KinematicState outKine(ctxt.GetOutputTarget()); outKine.PutTransform(result); return CStatus::OK; }