#X3D V3.0 utf8 PROFILE Immersive # [X3D] version=3.0 # [X3D] noNamespaceSchemaLocation=https://www.web3d.org/specifications/x3d-3.0.xsd # X3D-to-ClassicVRML XSL translation autogenerated by X3dToClassicVrmlEncoding.xslt and X3dToVrml97.xslt # https://www.web3d.org/x3d/content/X3dToClassicVrmlEncoding.xslt # https://www.web3d.org/x3d/content/X3dToVrml97.xslt # Transformation using XSLT processor: Saxonica # head META "title" "MaterialChoicePrototype.x3d" META "description" "Prototype definition for toggle-able Material node that can choose among an array of material nodes, and is switchable at run time. This prototype also demonstrates why it is important that only the first node in a ProtoBody can render: so that it can serve as a special node type (such as Material)." META "creator" "Don Brutzman and MV4205 class" META "created" "29 April 2004" META "modified" "28 November 2019" META "reference" "MaterialChoiceExample.x3d" META "identifier" "https://savage.nps.edu/Savage/Tools/Animation/MaterialChoicePrototype.x3d" META "generator" "X3D-Edit 3.2, https://savage.nps.edu/X3D-Edit" META "license" "../../license.html" # [Scene] ========== ========== ========== WorldInfo { title "MaterialChoicePrototype.x3d" } PROTO MaterialChoice [ # [appinfo] MaterialChoice selects one of several different Material values inputOnly SFInt32 set_index initializeOnly SFInt32 index 0 # [appinfo] which Material node is chosen, with array index starting at 0 outputOnly SFInt32 index_changed inputOnly SFFloat set_fraction initializeOnly SFFloat fraction 0 # [appinfo] fraction to interpolate between current and next Material node (if any) across all field values. inputOnly SFBool next # [appinfo] Trigger next Material node inputOnly SFBool previous # [appinfo] Trigger previous Material node initializeOnly MFNode materials [ ] # [appinfo] array of available Material nodes defaults to zeroth Material # no default initialization node since it crashes Xj3D inputOnly SFNode appendMaterial # [appinfo] append another Material node to materials array inputOnly SFInt32 deleteMaterial # [appinfo] delete Material node indicated by input index value inputOnly SFBool deleteAllMaterials # [appinfo] deletes all Material nodes resets scene to default Material values defined in X3D Specification ] { DEF ViewedMaterialNode Material { } DEF MaterialAnimationScript Script { initializeOnly SFBool traceEnabled FALSE inputOnly SFInt32 set_index IS set_index initializeOnly SFInt32 index IS index outputOnly SFInt32 index_changed IS index_changed inputOnly SFFloat set_fraction IS set_fraction initializeOnly SFFloat fraction IS fraction inputOnly SFBool next IS next inputOnly SFBool previous IS previous initializeOnly SFNode viewedMaterial USE ViewedMaterialNode initializeOnly SFNode defaultMaterial Material { } initializeOnly MFNode materials IS materials inputOnly SFNode appendMaterial IS appendMaterial # [appinfo] append another Material node to materials array inputOnly SFInt32 deleteMaterial IS deleteMaterial # [appinfo] delete Material node indicated by input index value inputOnly SFBool deleteAllMaterials IS deleteAllMaterials # [appinfo] deletes all Material nodes resets scene to default Material values defined in X3D Specification initializeOnly SFInt32 priorBadIndex -1 directOutput TRUE url [ "ecmascript: // ### X3D Browser.print() not supported by all VRML97 viewers, instead simply using print() function initialize () { tracePrint ('initialize() begin...'); if (materials[index] != null) { viewedMaterial.diffuseColor = materials[index].diffuseColor; viewedMaterial.emissiveColor = materials[index].emissiveColor; viewedMaterial.specularColor = materials[index].specularColor; viewedMaterial.shininess = materials[index].shininess; viewedMaterial.ambientIntensity = materials[index].ambientIntensity; viewedMaterial.transparency = materials[index].transparency; interpolateMaterialValues(); } else alwaysPrint ('warning: no initialization Material node provided for materials[' + index + ']' + ', materials.length=' + materials.length); tracePrint ('initialize() complete'); } function set_index (value, timestamp) { if (value == index) return; else if ((value >= 0) && (value < materials.length)) { index = value; viewedMaterial.diffuseColor = materials[index].diffuseColor; viewedMaterial.emissiveColor = materials[index].emissiveColor; viewedMaterial.specularColor = materials[index].specularColor; viewedMaterial.shininess = materials[index].shininess; viewedMaterial.ambientIntensity = materials[index].ambientIntensity; viewedMaterial.transparency = materials[index].transparency; interpolateMaterialValues(); index_changed = value; // chain input event to output event tracePrint ('set_index(' + value + ') complete'); } else if (value == -1) { tracePrint ('set_index(' + value + ') out of range, use default Material values'); index = value; viewedMaterial.diffuseColor = defaultMaterial.diffuseColor; viewedMaterial.emissiveColor = defaultMaterial.emissiveColor; viewedMaterial.specularColor = defaultMaterial.specularColor; viewedMaterial.shininess = defaultMaterial.shininess; viewedMaterial.ambientIntensity = defaultMaterial.ambientIntensity; viewedMaterial.transparency = defaultMaterial.transparency; index_changed = value; // chain input event to output event } else if (priorBadIndex != value) { alwaysPrint ('set_index(' + value + ') out of range (only ' + materials.length + ' Material nodes)'); priorBadIndex = value; } } function set_fraction(value, timestamp) { tracePrint ('set_fraction(' + value + ')'); if (fraction != value) // only update if value is changed { fraction = value; interpolateMaterialValues(); } } function interpolateMaterialValues() { f = fraction % 1; // nonzero remainder (modulo 1) within range [0..1] tracePrint ('interpolateMaterialValues(index=' + index + ', fraction=' + fraction + ', f=' + f + ')'); // reset Material index if fraction is above 1 if (Math.floor(fraction) >= 1) { index = Math.floor(fraction); tracePrint ('index=' + index + ' (reset from fraction)'); } fraction = f; // no need to retain integral part of fraction once index is set correspondingly // check OK to proceed if (index < 0) return; // avoid index underflow if (index >= materials.length - 1) return; // avoid index overflow if (f == 0.0) return; // avoid zero interpolation viewedMaterial.diffuseColor.r = materials[index].diffuseColor.r + f * (materials[index+1].diffuseColor.r - materials[index].diffuseColor.r); viewedMaterial.diffuseColor.g = materials[index].diffuseColor.g + f * (materials[index+1].diffuseColor.g - materials[index].diffuseColor.g); viewedMaterial.diffuseColor.b = materials[index].diffuseColor.r + f * (materials[index+1].diffuseColor.b - materials[index].diffuseColor.b); tracePrint ('viewedMaterial.diffuseColor=' + viewedMaterial.diffuseColor); viewedMaterial.emissiveColor.r = materials[index].emissiveColor.r + f * (materials[index+1].emissiveColor.r - materials[index].emissiveColor.r); viewedMaterial.emissiveColor.g = materials[index].emissiveColor.r + f * (materials[index+1].emissiveColor.g - materials[index].emissiveColor.g); viewedMaterial.emissiveColor.b = materials[index].emissiveColor.b + f * (materials[index+1].emissiveColor.b - materials[index].emissiveColor.b); viewedMaterial.specularColor.r = materials[index].specularColor.r + f * (materials[index+1].specularColor.r - materials[index].specularColor.r); viewedMaterial.specularColor.g = materials[index].specularColor.g + f * (materials[index+1].specularColor.g - materials[index].specularColor.g); viewedMaterial.specularColor.b = materials[index].specularColor.b + f * (materials[index+1].specularColor.b - materials[index].specularColor.b); viewedMaterial.shininess = materials[index].shininess + f * (materials[index+1].shininess - materials[index].shininess); viewedMaterial.ambientIntensity = materials[index].ambientIntensity + f * (materials[index+1].ambientIntensity - materials[index].ambientIntensity); viewedMaterial.transparency = materials[index].transparency + f * (materials[index+1].transparency - materials[index].transparency); } function next(trigger) { tracePrint ('next(' + trigger + ')'); if ((trigger == true) && (materials.length > 0)) { value = index + 1; if (value >= materials.length) value = 0; set_index (value); // update Material, test, etc. } } function previous(trigger) { tracePrint ('previous(' + trigger + ')'); if ((trigger == true) && (materials.length > 0)) { value = index - 1; if (value < 0) value = materials.length - 1; set_index (value); // update Material, test, etc. } } function appendMaterial(newMaterial) { tracePrint ('appendMaterial(' + newMaterial + ')'); newMaterialCopy = new SFNode ('Material {}'); tracePrint ('newMaterial.diffuseColor=' + newMaterial.diffuseColor); newMaterialCopy.diffuseColor = newMaterial.diffuseColor; newMaterialCopy.emissiveColor = newMaterial.emissiveColor; newMaterialCopy.specularColor = newMaterial.specularColor; newMaterialCopy.shininess = newMaterial.shininess; newMaterialCopy.ambientIntensity = newMaterial.ambientIntensity; newMaterialCopy.transparency = newMaterial.transparency; materials[materials.length] = newMaterialCopy; set_index (materials.length-1); // update Material, test, etc. } function deleteAllMaterials(trigger) { if ((trigger == true) && (materials.length > 0)) { materials.length = 0; // deletes all objects in materials MFNode array index = 0; // must be different to trigger node reset by set_index() set_index (-1); tracePrint ('deleteAllMaterials() materials.length=' + materials.length); } } function deleteMaterial(materialIndex) { if ((materialIndex >= materials.length) || materialIndex < 0) alwaysPrint ('deleteMaterial(materialIndex=' + materialIndex + ') out of range, materials.length=' + materials.length); else { for (i = materialIndex; i <= materials.length - 2; i++) { materials[i] = materials[i+1]; } materials.length = materials.length - 1; if ((index == 0) && (materialIndex == 0) && (materials.length > 0)) { index = -1; // allow reset back to 0 set_index (0); } else if (index >= materialIndex) set_index (index-1); // decrement to remain same tracePrint ('deleteMaterial(materialIndex=' + materialIndex + ') complete, materials.length=' + materials.length); } } function tracePrint(outputString) { if (traceEnabled) Browser.println ('[MaterialChoice] ' + outputString); } function alwaysPrint(outputString) { Browser.println ('[MaterialChoice] ' + outputString); } " ] } } # ==================== Anchor { description "MaterialChoiceExample" url [ "MaterialChoiceExample.x3d" "https://savage.nps.edu/Savage/Tools/Animation/MaterialChoiceExample.x3d" "MaterialChoiceExample.wrl" "https://savage.nps.edu/Savage/Tools/Animation/MaterialChoiceExample.wrl" ] children [ Shape { geometry Text { string [ "MaterialChoicePrototype" "defines a prototype" "" "Click text to see example scene" "MaterialChoiceExample" ] fontStyle FontStyle { justify [ "MIDDLE" "MIDDLE" ] size 0.9 } } appearance Appearance { material Material { diffuseColor 1 1 0.2 } } } ] }