arm
Web3D/VR
#@extern @vr-extern-proto-object-box.wrl
PROTO SwingingArm [
exposedField SFVec3f translation 0 0 0
exposedField SFRotation orientation 0 0 1 0
exposedField MFNode children []
eventIn MFNode addChildren
eventIn MFNode removeChildren
exposedField SFFloat transparency 0.9
field SFFloat armLength 0.5
]{
DEF MOVEPOINT Transform {
translation IS translation
rotation IS orientation
children [
Transform {
translation -0.1 0 0
children [
Group {
children [
Shape {
appearance DEF GRAY Appearance {
material Material {
transparency IS transparency
diffuseColor 0.4 0.4 0.8
emissiveColor 0.4 0.4 0.8
}
}
geometry box { size 0.2 0.025 0.025 }
}
DEF DRAGSENSOR PlaneSensor {
minPosition 0 0
maxPosition 1 1
}
]
}
Transform {
translation -0.1 0 0
children [
Group {
children [
Transform {
translation 0 0.05 0
children [
DEF MINIMIZE TouchSensor {}
Shape {
appearance Appearance {
material Material {
transparency 0.2
diffuseColor 0.4 0.0 0.8
emissiveColor 0.4 0.0 0.8
}
}
geometry Sphere {
radius 0.025
}
}
]
}
Shape {
appearance Appearance {
material Material {
transparency 0.2
diffuseColor 0.8 0.8 0.8
emissiveColor 0.8 0.8 0.8
}
}
geometry Sphere {
radius 0.025
}
}
DEF ROTATESENSOR PlaneSensor {
minPosition -0.314 -0.157
maxPosition 0 0.157
}
]
}
DEF ROTATEPOINT Transform {
children [
DEF END_ARM_TRANS Transform {
translation -.25 0 0
children [
Shape {
appearance USE GRAY
geometry DEF END_ARM_BOX box {
size 0.5 0.025 0.025
}
}
DEF CONNECTPOINT Transform {
translation -0.3 0 0.03
children IS children
addChildren IS addChildren
removeChildren IS removeChildren
}
]
}
]
}
]
}
]
}
]
}
DEF SCRIPT Script {
directOutput TRUE
eventIn SFFloat aspectRatio
eventIn SFVec3f setRotateTrans
eventOut SFRotation rotation_changed
eventIn SFBool doDrag
eventIn SFVec3f setDragTrans
eventOut SFVec3f newPos
eventOut SFRotation armRotation
eventOut SFRotation correctionRotation
field SFVec3f orgPos IS translation
field SFVec3f pos 0 0 0
field SFRotation orgRot 0 0 1 0
field SFRotation correctionRot 0 0 1 0
field SFFloat xCenter 0
field SFFloat yCenter 0
field SFFloat left -2
field SFFloat right 2
field SFFloat top 0.95
field SFFloat bottom -0.95
eventIn SFTime minimize
field SFBool minimized FALSE
field SFRotation oldRotation 0 0 1 0
field SFNode rotPtTrans USE ROTATEPOINT
field SFFloat armLength IS armLength
field SFNode endArmBox USE END_ARM_BOX
field SFNode endArmTrans USE END_ARM_TRANS
field SFNode connPtTrans USE CONNECTPOINT
url "vrmlscript:
function initialize() {
//setWindowRect(Browser.windowAspect);
aspect = Browser.windowAspect;
pos = orgPos;
setWindowRect(aspect);
correctPosition();
setArmLength();
}
function minimize(value,time) {
if(minimized) {
minimized = false;
rotPtTrans.rotation = oldRotation;
} else {
minimized = true;
oldRotation = rotPtTrans.rotation;
rotPtTrans.rotation = new SFRotation(0,1,0,3.14);
}
}
function setArmLength() {
endArmBox.size = new SFVec3f(armLength ,0.025 ,0.025);
endArmTrans.translation = new SFVec3f(-armLength/2 ,0 ,0);
connPtTrans.translation = new SFVec3f(-armLength/2 - 0.05 ,0 ,0.03);
}
function aspectRatio(value,time) {
setWindowRect(value);
correctPosition();
}
function setWindowRect(aspect) {
if(aspect>1) {
// if aspect>1, Y is constant, so X is relative to AspectRatio
yfov = Browser.boundViewpoint.fieldOfView;
if(yfov==0) { yfov = 0.785398; }
//xfov = Math.atan(aspect*(Math.tan(yfov/2)))*2;
yfov = 0.785398;
right = (aspect*(Math.tan(yfov/2))) * 2.0; // + 0.1;
top = 0.95;
} else {
// if aspect<1, X is constant, so Y is relative to AspectRatio
xfov = Browser.boundViewpoint.fieldOfView;
if(xfov==0) { xfov = 0.785398; }
//yfov = Math.atan((Math.tan(yfov/2))/aspect)*2;
right = 0.95;
top = ((Math.tan(xfov/2))/aspect) * 2.0 + 0.1;
}
// print ('ratio == ' + aspect);
// print ('yfov == ' + yfov);
// print ('xfov == ' + xfov);
// print ('angleRatio == ' + angleRatio);
left = -right;
bottom = -top;
}
function setRotateTrans (value,time) {
rotA = new SFRotation(0,1,0, value.x*10);
rotB = new SFRotation(1,0,0,-value.y*10);
rotation_changed = rotA.multiply(rotB);
}
function doDrag(value,time) {
if(!value) {
orgPos = pos;
} else {
pos = orgPos;
correctionRot = orgRot;
}
}
function correctPosition() {
// Snap position to edge of screen
dx = 0;
dy = 0;
if(pos.x > xCenter) { dx = right-pos.x; }
else { dx = pos.x-left; }
if(pos.y < yCenter) { dy = pos.y-bottom; }
else { dy = top-pos.y; }
if(dx<dy) {
if(pos.x > xCenter) {
armRotation = new SFRotation(0,0,1,0);
correctionRotation = new SFRotation(0,0,1,0);
orgRot = new SFRotation(0,0,1,0);
pos.x = right;
} else {
armRotation = new SFRotation(0,0,1, 3.14);
correctionRotation = new SFRotation(0,0,1,-3.14);
orgRot = new SFRotation(0,0,1, 3.14);
pos.x = left;
}
} else /* dy<dx */ {
if(pos.y < yCenter) {
armRotation = new SFRotation(0,0,1,-1.57);
correctionRotation = new SFRotation(0,0,1, 1.57);
orgRot = new SFRotation(0,0,1,-1.57);
pos.y = bottom;
} else {
armRotation = new SFRotation(0,0,1, 1.57);
correctionRotation = new SFRotation(0,0,1,-1.57);
orgRot = new SFRotation(0,0,1, 1.57);
pos.y = top;
}
}
// Limit position to screen
if(pos.y < bottom) { pos.y = bottom; }
if(pos.y > top) { pos.y = top; }
if(pos.x < left) { pos.x = left; }
if(pos.x > right) { pos.x = right; }
newPos = pos;
}
function setDragTrans (value,time) {
rotVal = correctionRot.multVec(value);
pos = new SFVec3f();
pos.x = orgPos.x + rotVal.x;
pos.y = orgPos.y + rotVal.y;
pos.z = orgPos.z;
correctPosition();
}
"
}
Script { ## To setup some ROUTES that cannot be defined statically
field SFNode script USE SCRIPT
url "vrmlscript:
function initialize()
{
Browser.addRoute(Browser,'windowAspect',script,'aspectRatio');
}
function shutdown()
{
Browser.removeRoute(Browser,'windowAspect',script,'aspectRatio');
}
"
}
ROUTE MINIMIZE.touchTime TO SCRIPT.minimize
ROUTE ROTATESENSOR.translation_changed TO SCRIPT.setRotateTrans
ROUTE SCRIPT.rotation_changed TO ROTATEPOINT.rotation
ROUTE DRAGSENSOR.isActive TO SCRIPT.doDrag
ROUTE DRAGSENSOR.trackPoint_changed TO SCRIPT.setDragTrans
ROUTE SCRIPT.newPos TO MOVEPOINT.translation
ROUTE SCRIPT.armRotation TO MOVEPOINT.rotation
ROUTE SCRIPT.correctionRotation TO CONNECTPOINT.rotation
}