#VRML_SIM R2022b utf8 # license: Copyright Cyberbotics Ltd. Licensed for use only with Webots. # license url: https://cyberbotics.com/webots_assets_license # A cardboard box. # template language: javascript EXTERNPROTO "webots://projects/appearances/protos/Cardboard.proto" PROTO CardboardBox [ field SFVec3f translation 0 0 0.3 field SFRotation rotation 0 0 1 0 field SFString name "cardboard box" field SFVec3f size 0.6 0.6 0.6 # Defines the size of the cardboard box. field SFFloat mass 0 # Defines the mass of the cardboard box in kg. A value smaller or equal to 0 remove the physics of the cardboard box. field SFBool locked FALSE # Is `Solid.locked`. field SFFloat lidAngle 0 # Defines the opening of the cardboard box in radians. A value equal to 0 closes the box and uses a simple box for the bounding object, preventing it from containing objects. ] { %< let size = fields.size.value; let volume = size.x * size.y * size.z; let mass = fields.mass.value; if (volume < 0.000001 || volume > 1) { size = fields.size.defaultValue; console.error('Box volume outside of range [ 1 cm3 ; 1 m3 ]. \'size\' value reset to (' + size.x + ', ' + size.y + ', ' + size.z + ').'); } const max_size = 2.5; const min_size = 0.01; if (size.x > max_size) { console.error('\'size.x\' greater than maximal size (' + max_size + '). Value clamped.'); size.x = max_size; } else if (size.x < min_size) { console.error('\'size.x\' less than minimal size (' + min_size + '). Value clamped.'); size.x = min_size; } if (size.y > max_size) { console.error('\'size.y\' greater than maximal size (' + max_size + '). Value clamped.'); size.y = max_size; } else if (size.y < min_size) { console.error('\'size.y\' less than minimal size (' + min_size + '). Value clamped.'); size.y = min_size; } if (size.z > max_size) { console.error('\'size.z\' greater than maximal size (' + max_size + '). Value clamped.'); size.z = max_size; } else if (size.z < min_size) { console.error('\'size.z\' less than minimal size (' + min_size + '). Value clamped.'); size.z = min_size; } // we want the mass for a 1cm3 box be comprised between 0.1 and 10 g inclusive // and the mass for a 1m3 box be comprised between 1 and 100 kg, hence the // following min_mass and max_mass values: let min_mass = Math.pow(volume, 2/3); let max_mass = min_mass * 100; if (mass > 0 && mass < min_mass) { console.error('\'mass\' less than minimal value (' + min_mass + '). Value clamped.'); mass = min_mass; } else if (mass > max_mass) { console.error('\'mass\' greater than maximal value (' + max_mass + '). Value clamped.'); mass = max_mass; } >% Solid { translation IS translation rotation IS rotation children [ DEF BACK Transform { translation %<= -(size.x / 2 - 0.00025) >% 0 0 children [ Shape { appearance Cardboard { type "back" } geometry Box { size 0.0005 %<= size.y - 0.0001 >% %<= size.z - 0.0001 >% } } ] } DEF FRONT Transform { translation %<= size.x / 2 - 0.00025 >% 0 0 children [ Shape { appearance Cardboard { type "front" } geometry Box { size 0.0005 %<= size.y - 0.0001 >% %<= size.z - 0.0001 >% } } ] } DEF RIGHT Transform { translation 0 %<= -(size.y / 2 - 0.00025) >% 0 children [ Shape { appearance Cardboard { type "right" } geometry Box { size %<= size.x - 0.0001 >% 0.0005 %<= size.z - 0.0001 >% } } ] } DEF LEFT Transform { translation 0 %<= size.y / 2 - 0.00025 >% 0 children [ Shape { appearance Cardboard { type "left" } geometry Box { size %<= size.x - 0.0001 >% 0.0005 %<= size.z - 0.0001 >% } } ] } DEF BOTTOM Transform { translation 0 0 %<= -size.z / 2 + 0.00025 >% children [ Shape { appearance Cardboard { type "bottom" } geometry Box { size %<= size.x - 0.0001 >% %<= size.y - 0.0001 >% 0.0005 } } ] } DEF TOP Transform { %< let position = {x:0, y:0, z:0} let angle = fields.lidAngle.value; position.x = -((size.x / 2) - Math.cos(angle) * (size.x / 2)); position.z = (size.z / 2) - 0.00025 + Math.sin(angle) * (size.x / 2); >% translation %<= position.x >% %<= position.y >% %<= position.z >% rotation 0 1 0 %<= -fields.lidAngle.value >% children [ Shape { appearance Cardboard { type "top" } geometry Box { size %<= size.x - 0.0001 >% %<= size.y - 0.0001 >% 0.0005 } } ] } ] name IS name model "cardboard box" %< if (fields.lidAngle.value === 0) { >% boundingObject Box { size %<= size.x >% %<= size.y >% %<= size.z >% } %< } else { >% boundingObject Group { children [ DEF BACK Transform { translation %<= -(size.x / 2 - 0.0005) >% 0 0 children [ Shape { appearance Cardboard { type "back" } geometry Box { size 0.003 %<= size.y - 0.0001 >% %<= size.z - 0.0001 >% } } ] } DEF FRONT Transform { translation %<= size.x / 2 - 0.0005 >% 0 0 children [ Shape { appearance Cardboard { type "front" } geometry Box { size 0.003 %<= size.y - 0.0001 >% %<= size.z - 0.0001 >% } } ] } DEF RIGHT Transform { translation 0 %<= -(size.y / 2 - 0.0005) >% 0 children [ Shape { appearance Cardboard { type "right" } geometry Box { size %<= size.x - 0.0001 >% 0.003 %<= size.z - 0.0001 >% } } ] } DEF LEFT Transform { translation 0 %<= size.y / 2 - 0.0005 >% 0 children [ Shape { appearance Cardboard { type "left" } geometry Box { size %<= size.x - 0.0001 >% 0.003 %<= size.z - 0.0001 >% } } ] translationStep 0 } DEF BOTTOM Transform { translation 0 0 %<= -size.z / 2 + 0.0005 >% children [ Shape { appearance Cardboard { type "bottom" } geometry Box { size %<= size.x - 0.0001 >% %<= size.y - 0.0001 >% 0.003 } } ] } DEF TOP Transform { translation %<= position.x >% %<= position.y >% %<= position.z >% rotation 0 1 0 %<= -fields.lidAngle.value >% children [ Shape { appearance Cardboard { type "bottom" } geometry Box { size %<= size.x - 0.0001 >% %<= size.y - 0.0001 >% 0.003 } } ] } ] } %< } if (mass > 0) { >% physics Physics { density -1 mass %<= mass >% } %< } >% locked IS locked } }