Why is ScalarChaser missing from the X3D Specification?
Vrml97ToX3dNist, http://ovrt.nist.gov/v2_x3d.html
X3D-Edit 3.3, https://www.web3d.org/x3d/tools/X3D-Edit
"FollowerPrototypeDeclarations.x3d#ScalarDamper" "https://www.web3d.org/x3d/content/examples/Basic/Followers/FollowerPrototypeDeclarations.x3d#ScalarDamper" "FollowerPrototypeDeclarations.wrl#ScalarDamper" "https://www.web3d.org/x3d/content/examples/Basic/Followers/FollowerPrototypeDeclarations.wrl#ScalarDamper"
ecmascript: function set_Color(Col) { croneDiffuseColor= new SFColor( Col.r * .7 , Col.g * .7 , Col.b * .7 ); croneEmissiveColor= new SFColor( Col.r * .3 , Col.g * .3 , Col.b * .3 ); }
ecmascript: function sin0(x) { return Math.sin(x * 6.28318530717959); // We don't use 2*Math.PI in the hope it will increase performance. } function cos0(x) { return Math.cos(x * 6.28318530717959); // We don't use 2*Math.PI in the hope it will increase performance. } function initialize() { var Heights= new MFFloat; Heights.length= Grid.xDimension * Grid.zDimension; var ZFrom= -Grid.zDimension*Grid.zSpacing/2; var ZTo= Grid.zDimension*Grid.zSpacing/2 - Grid.zSpacing * .1; var ZStep= Grid.zSpacing; var XFrom= -Grid.xDimension*Grid.xSpacing/2; var XTo= Grid.xDimension*Grid.xSpacing/2 - Grid.xSpacing * .1; var XStep= Grid.xSpacing; // ZFrom+= Grid.zSpacing; // ZTo-= Grid.zSpacing; // XFrom+= Grid.xSpacing; // XTo-= Grid.xSpacing; var Idx= 0; // Idx+= 1 + Grid.xDimension * 1; for(var Z= ZFrom; Z<=ZTo; Z+= ZStep) { for(var X= XFrom; X<=XTo; X+= XStep) { var s= 9; var H= .7*( cos0(Z*s / 30) + cos0(X*s / 35 + X*X*s*s / 34) + sin0(X*Z*s / 40)); H+= cos0(Math.sqrt(X*X + Z*Z) / 300) * 15; Heights[Idx++]= H; } // Idx+= 2; } Grid.height= Heights; }
ecmascript: function initialize() { Trees= TreeGroup.children; for(var C= 0; C<Trees.length; C++ ) Trees[C].position= AddGroundHeight(Trees[C].position); } // receives an SFVec3f of a position over ground, evaluates the ground height at that // position and adds it to the y value of the vector. function AddGroundHeight(Vec) { var PosOnGrid= Vec.subtract(GroundTrans.translation); var FloatIdxX= PosOnGrid.x / GroundGrid.xSpacing; var FloatIdxZ= PosOnGrid.z / GroundGrid.zSpacing; var FracX= FloatIdxX - Math.floor(FloatIdxX); var FracZ= FloatIdxZ - Math.floor(FloatIdxZ); // We do linear interpolation in the square we have. var IdxLowerX= Math.floor(FloatIdxX); var IdxLowerZ= Math.floor(FloatIdxZ); var IdxHigherX= IdxLowerX + 1; var IdxHigherZ= IdxLowerZ + 1; if(IdxLowerX < 0) IdxLowerX= 0; if(IdxLowerZ < 0) IdxLowerZ= 0; if(IdxHigherX < 0) IdxHigherX= 0; if(IdxHigherZ < 0) IdxHigherZ= 0; if(IdxLowerX >= GroundGrid.xDimension) IdxLowerX= GroundGrid.xDimension - 1; if(IdxHigherX >= GroundGrid.xDimension) IdxHigherX= GroundGrid.xDimension - 1; if(IdxLowerZ >= GroundGrid.zDimension) IdxLowerZ= GroundGrid.zDimension - 1; if(IdxHigherZ >= GroundGrid.zDimension) IdxHigherZ= GroundGrid.zDimension - 1; var LowerXHeight= GetGroundGridHeightAt(IdxLowerX, IdxLowerZ) * (1 - FracZ) + GetGroundGridHeightAt(IdxLowerX, IdxHigherZ) * FracZ; var HigherXHeight= GetGroundGridHeightAt(IdxHigherX, IdxLowerZ) * (1 - FracZ) + GetGroundGridHeightAt(IdxHigherX, IdxHigherZ) * FracZ; var Height= LowerXHeight * (1 - FracX) + HigherXHeight * FracX; return new SFVec3f(Vec.x, Vec.y + Height, Vec.z); } function GetGroundGridHeightAt(IdxX, IdxZ) { return GroundGrid.height[IdxX + IdxZ * GroundGrid.xDimension]; }
ecmascript: function set_hitCoord(C) { hitCoord= C; if(SensIsActive) { userInput= C.subtract(ActivationCoords).multiply(cScale); } } function set_activated(a) { SensIsActive= a; if(a) ActivationCoords= hitCoord; else userInput= new SFVec2f(0, 0); }
ecmascript: function NonLin(x) { var cAmount= .3; var cBmount= 1 - cAmount; return (x * x * (x>0? 1:-1)) * cAmount + (x) * cBmount; // TBD: Some exponential function would be better. } function userInput(inp) { lastUserInput= inp; if(sensorIsActive) { ProcessMoveInput(inp.y); ProcessRotateInput(inp.x); } } function damperedMoveInput(inp) { if(!sensorIsActive) ProcessMoveInput(inp); } function damperedRotateInput(inp) { if(!sensorIsActive) ProcessRotateInput(inp); } function ProcessMoveInput(inp) { MoveSpeed= NonLin(inp / cInputNominalX) * cNominalMoveSpeed; } function ProcessRotateInput(inp) { OriSpeed= NonLin(inp / cInputNominalY) * cNominalOriSpeed; } function set_sensorIsActive(a) { sensorIsActive= a; if(!a) { DieAwayMoveDamper.set_value= lastUserInput.y; DieAwayMoveDamper.set_destination= 0; DieAwayRotateDamper.set_value= lastUserInput.x; DieAwayRotateDamper.set_destination= 0; // They now creates a transition from lastUserInput.y to 0. } } function Tick(Now) { if(!lastTick) { lastTick= Now; return; } var DeltaT= Now - lastTick; lastTick= Now; if(OriSpeed || MoveSpeed) { ObjectOri= ObjectOri.multiply(new SFRotation(0, 1, 0, -OriSpeed * DeltaT)); ObjectPos= ObjectPos.add(ObjectOri.multVec(new SFVec3f(0, 0, -MoveSpeed * DeltaT))); objectPos_changed= AddGroundHeight(ObjectPos); objectOri_changed= ObjectOri; } } // receives an SFVec3f of a position over ground, evaluates the ground height at that // position and adds it to the y value of the vector. function AddGroundHeight(Vec) { var PosOnGrid= Vec.subtract(GroundTrans.translation); var FloatIdxX= PosOnGrid.x / GroundGrid.xSpacing; var FloatIdxZ= PosOnGrid.z / GroundGrid.zSpacing; var FracX= FloatIdxX - Math.floor(FloatIdxX); var FracZ= FloatIdxZ - Math.floor(FloatIdxZ); // We do linear interpolation in the square we have. var IdxLowerX= Math.floor(FloatIdxX); var IdxLowerZ= Math.floor(FloatIdxZ); var IdxHigherX= IdxLowerX + 1; var IdxHigherZ= IdxLowerZ + 1; if(IdxLowerX < 0) IdxLowerX= 0; if(IdxLowerZ < 0) IdxLowerZ= 0; if(IdxHigherX < 0) IdxHigherX= 0; if(IdxHigherZ < 0) IdxHigherZ= 0; if(IdxLowerX >= GroundGrid.xDimension) IdxLowerX= GroundGrid.xDimension - 1; if(IdxHigherX >= GroundGrid.xDimension) IdxHigherX= GroundGrid.xDimension - 1; if(IdxLowerZ >= GroundGrid.zDimension) IdxLowerZ= GroundGrid.zDimension - 1; if(IdxHigherZ >= GroundGrid.zDimension) IdxHigherZ= GroundGrid.zDimension - 1; var LowerXHeight= GetGroundGridHeightAt(IdxLowerX, IdxLowerZ) * (1 - FracZ) + GetGroundGridHeightAt(IdxLowerX, IdxHigherZ) * FracZ; var HigherXHeight= GetGroundGridHeightAt(IdxHigherX, IdxLowerZ) * (1 - FracZ) + GetGroundGridHeightAt(IdxHigherX, IdxHigherZ) * FracZ; var Height= LowerXHeight * (1 - FracX) + HigherXHeight * FracX; return new SFVec3f(Vec.x, Vec.y + Height, Vec.z); } function GetGroundGridHeightAt(IdxX, IdxZ) { return GroundGrid.height[IdxX + IdxZ * GroundGrid.xDimension]; }
ecmascript: function set_avatarPos(Pos) { avatarPos= Pos; Update(); } function set_avatarOri(Ori) { avatarOri= Ori; Update(); } function Update() { var viewPos= avatarPos.add(avatarOri.multVec(cCameraOffsetPos)); var viewOri= cCameraOffsetOri.multiply(avatarOri); if( viewPos_changed != viewPos) viewPos_changed= viewPos; if( viewOri_changed != viewOri) viewOri_changed= viewOri; }
"MonkeyShadow.png" "https://www.web3d.org/x3d/content/examples/Basic/Followers/MonkeyShadow.png"
ecmascript: function set_MonkeyPos(Pos) { MonkeyPos= Pos; Update(); } function set_MonkeyOri(Ori) { MonkeyOri= Ori; Update(); } function Update() { ShadowPos_changed= AddGroundHeight(new SFVec3f(MonkeyPos.x, .4, MonkeyPos.z)); var ViewDir= MonkeyOri.multVec(new SFVec3f(0, 0, -1)); ViewDir.y= 0; // make it horizontal. var HorzOri= new SFRotation(new SFVec3f(0, 0, -1), ViewDir); // now we have a horizontal orientation only. // figure out the normal vector of the ground. // for this, figure out three points on the ground around the monkey position. var cRadius= 2.3; var EvGridPointA= AddGroundHeight((new SFVec3f(MonkeyPos.x, 0, MonkeyPos.z)).add(HorzOri.multVec((new SFVec3f( 0, 0, -1 )).multiply(cRadius)))); var EvGridPointB= AddGroundHeight((new SFVec3f(MonkeyPos.x, 0, MonkeyPos.z)).add(HorzOri.multVec((new SFVec3f( .866, 0, .5)).multiply(cRadius)))); var EvGridPointC= AddGroundHeight((new SFVec3f(MonkeyPos.x, 0, MonkeyPos.z)).add(HorzOri.multVec((new SFVec3f(-.866, 0, .5)).multiply(cRadius)))); var Normal= EvGridPointC.subtract(EvGridPointA).cross(EvGridPointB.subtract(EvGridPointA)); var NormalOri= new SFRotation(new SFVec3f(0, 1, 0), Normal); ShadowOri_changed= HorzOri.multiply(NormalOri); } // receives an SFVec3f of a position over ground, evaluates the ground height at that // position and adds it to the y value of the vecotr. function AddGroundHeight(Vec) { var PosOnGrid= Vec.subtract(GroundTrans.translation); var FloatIdxX= PosOnGrid.x / GroundGrid.xSpacing; var FloatIdxZ= PosOnGrid.z / GroundGrid.zSpacing; var FracX= FloatIdxX - Math.floor(FloatIdxX); var FracZ= FloatIdxZ - Math.floor(FloatIdxZ); // We do linear interpolation in the square we have. var IdxLowerX= Math.floor(FloatIdxX); var IdxLowerZ= Math.floor(FloatIdxZ); var IdxHigherX= IdxLowerX + 1; var IdxHigherZ= IdxLowerZ + 1; if(IdxLowerX < 0) IdxLowerX= 0; if(IdxLowerZ < 0) IdxLowerZ= 0; if(IdxHigherX < 0) IdxHigherX= 0; if(IdxHigherZ < 0) IdxHigherZ= 0; if(IdxLowerX >= GroundGrid.xDimension) IdxLowerX= GroundGrid.xDimension - 1; if(IdxHigherX >= GroundGrid.xDimension) IdxHigherX= GroundGrid.xDimension - 1; if(IdxLowerZ >= GroundGrid.zDimension) IdxLowerZ= GroundGrid.zDimension - 1; if(IdxHigherZ >= GroundGrid.zDimension) IdxHigherZ= GroundGrid.zDimension - 1; var LowerXHeight= GetGroundGridHeightAt(IdxLowerX, IdxLowerZ) * (1 - FracZ) + GetGroundGridHeightAt(IdxLowerX, IdxHigherZ) * FracZ; var HigherXHeight= GetGroundGridHeightAt(IdxHigherX, IdxLowerZ) * (1 - FracZ) + GetGroundGridHeightAt(IdxHigherX, IdxHigherZ) * FracZ; var Height= LowerXHeight * (1 - FracX) + HigherXHeight * FracX; return new SFVec3f(Vec.x, Vec.y + Height, Vec.z); } function GetGroundGridHeightAt(IdxX, IdxZ) { return GroundGrid.height[IdxX + IdxZ * GroundGrid.xDimension]; }