[x3d-public] X3DJSAIL: Exceeding Java String limits on setValue? What do we do?

Don Brutzman brutzman at nps.edu
Wed Mar 29 10:16:49 PDT 2017


OK further progress FYI.

First, have added "simple" methods for setting SFVec SFColor SFRotation fields using individual values on a per-field basis.  This is perhaps a most-common use case, and we don't want to force new X3D Java programmers to have to coerce types right from the start (ugh).  So, methods like setTranslation can accept either float[] 3-tuple, or SFVec3fObject, or simply (float x, float y, float z). Value and bound validation checks remain included throughout the codebase.  Representative method examples (setTranslation, setRotation etc.) at

	http://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/jsail/Grouping/TransformObject.html#method.summary

Second, am working through these same issues you have been diagnosing and debugging.  The setSomething(x, y, z) methods can also make someone's source a bit smaller and simpler, with fewer intermediate object instantiations.  Have also got precise determination of attribute type working in X3dToJava.xslt conversion stylesheet.  Example attached.

Third, now that arrays can be effectively handled as floats rather than strings, this opens the door to re-tackling any remaining "code too large" compilation issues - there are a few examples of that, especially for meshes.  Will next work on how to subdivide exceedingly long arrays (perhaps 100 tuples at a time) and see if the set and append methods support such a divide-and-conquer approach.  Any good techniques you've found will be good to share, TIA.

Have fun with X3DJSAIL!  8)

	http://www.web3d.org/specifications/java/X3DJSAIL.html


On 3/28/2017 12:43 AM, Don Brutzman wrote:
> On 3/27/2017 6:49 AM, John Carlson wrote:
>> I’m hoping with append, we can start knocking out more code too large issues.  i will have to create a good pattern for breaking them up into methods.
>
> Yes that can work, though it makes source and bytecode bigger.
>
> Also need to break up exceedingly long comments (which do exist in a few places, mostly for archival purposes).
>
> Tonight I added and uploaded a few more utility constructors and setValue() methods for SFVec2fObject, SFVec3fObject, SFVec4fObject that use double parameters in addition to the original float parameters.
>
> Double and float flexibility is good because then you can write data into these methods without putting an "f" after each number, using Java doubles instead of Java floats.  Source excerpts:
>
> ==========================
> .setGeometry(new IndexedFaceSetObject().setSolid(false).setCoordIndex(new int[] {0,1,2,-1,1,3,2,-1,2,3,4,-1,1,5,3,-1,3,5,6,-1,5,1,0,-1, [... skip ...] -1,1561,1558,1560,-1})
>
>   .setCoord(new CoordinateObject().setPoint(new MFVec3fObject(-44.6674,-1.12054,0,-44.7852,-0.376604,0,  [... skip ...] ))))))))))));
> ==========================
>
> Nevertheless that led to a new problem: some (like the "0," above) are whole values without decimal point or fractions, and these get treated as an integer by Java, thwarting type matching by not matching the double-array signature of the MFVec3fObject constructor above.  Ouch.
>
> ... so I'll probably put in a pattern-matching test in the X3dToJava.xslt converter with avoids this problem, converting 0 to 0d etc.
>
> Maybe also add a conversion switch to prefer floats (less memory use in compiled byte code) versus doubles (less string space in source).
>
> This is a tricky implementation space but it seems like we are making things more streamlined with each success... onward we go.  8)
>
>
> On 3/26/2017 8:57 PM, Don Brutzman wrote:
>> It should be possible to avoid String size limits by using typed values instead.
>>
>> Latest build has built-in type support for fieldObject and fieldValueObject, allowing a programmer to set and get numeric array values of fields without using String datatypes.  There are tons of typed getValue"Type" and setValue methods provided.
>>
>>     http://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/jsail/Core/fieldObject.html#method.summary
>>
>>     http://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/jsail/Core/fieldValueObject.html#method.summary
>>
>> Here are some examples from HelloWorldProgram.java
>>
>> new ProtoInterfaceObject()
>>     .addField(new fieldObject()
>>         .setName("enabled")
>>         .setType(fieldObject.TYPE_SFBOOL)
>>         .setAccessType( fieldObject.ACCESSTYPE_INPUTOUTPUT)
>>         .setValue(true)              // equivalent, strongly typed
>>         .setValue(new MFBoolObject(true)) // equivalent
>>         .setValue(SFBoolObject.TRUE))     // equivalent
>>     .addField(new fieldObject()
>>         .setName("diffuseColor")
>>         .setType(fieldObject.TYPE_SFCOLOR)
>>         .setAccessType( fieldObject.ACCESSTYPE_INPUTOUTPUT)
>>         .setValue(new SFColorObject().setValueByString("0.8 0.8 0.8"))      // equivalent, strongly typed
>>         .setValue((SFColorObject.toString(SFColorObject.DEFAULT_VALUE)))) // equivalent
>>
>> Similarly the SF/MF field objects have more methods allowing you to use numeric types more conveniently instead of strings.  Furthermore, support for both float and double arrays exists in most places.  Look at the variety of getValue"Type" and setValue methods provided, for example SFVec3fObject.
>>
>>     http://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/jsail/fields/SFVec3fObject.html
>>
>> There are also typed append() methods for the MF array objects, for example MFVec3f.append(SFVec3fObject newValue) and MFVec3f.append(float[] newValue)
>>
>>     http://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/jsail/fields/MFVec3fObject.html
>>
>>     http://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/jsail/fields/MFVec3fObject.html#append-float:A-
>>
>>     http://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/jsail/fields/MFVec3fObject.html#append-org.web3d.x3d.jsail.fields.SFVec3fObject-
>>
>> Array-length counting tests are included throughout the source code and documentation, for example:
>>
>>     "WARNING: newValue array length must correspond to tuple size for base type MFVec3f tuple size of 3."
>>
>> So hopefully this provides alternative, higher-performance patterns.  Please advise if some of the conversions are still not yielding.
>>
>> v/r Don
>>
>>
>> On 3/25/2017 10:52 AM, Don Brutzman wrote:
>>> ... so, in other words, an alternative is changing something like this
>>>
>>>     new CoordinateObject()
>>>         .setPoint(new float[] {-8f,-9f,4f, [...]
>>>
>>> to
>>>     new CoordinateObject()
>>>         .setPoint(new MFVec3fObject().setValue(-8f,-9f,4f, [...]
>>>
>>> or even
>>>     new CoordinateObject()
>>>         .setPoint(new MFVec3fObject().setValue(-8f,-9f,4f, [...]
>>>
>>> Continuing on that path, I add a variety of other constructor and setValue methods to the field objects to facilitate use of either floats or doubles as needed.
>>>
>>> Example invocations, tested in HelloWorldProgram.java
>>> ======================================================
>>>         // test alternate type forms
>>>         boxCoordinateNode.setPoint(new MFVec3fObject(new float[] {-8f,-9f,4f,-7f,-7f,5f,-3f,0f,5f}));                //  floats to  float array to MFVec3f
>>>         boxCoordinateNode.setPoint(new MFVec3fObject(new double[] {-8f,-9f,4f,-7f,-7f,5f,-3f,0f,5f}));                //  floats to double array to MFVec3f
>>>         boxCoordinateNode.setPoint(new MFVec3fObject(new double[] {-8,-9,4,-7,-7,5,-3,0,5}));                        //    ints to double array to MFVec3f
>>>         boxCoordinateNode.setPoint(new MFVec3fObject(new double[] {-8.0,-9.0,4.0,-7.0,-7.0,5.0,-3.0,0.0,5.0}));        // doubles to double array to MFVec3f
>>> //        original SAI interface returns void, cannot be pipelined, candidate specification change
>>> //        boxCoordinateNode.setPoint(new MFVec3fObject().setValue(new float[] {-8f,-9f,4f,-7f,-7f,5f,-3f,0f,5f}));    //  floats to float array to MFVec3f
>>>         boxCoordinateNode.setPoint(new MFVec3fObject().setValue(new double[] {-8f,-9f,4f,-7f,-7f,5f,-3f,0f,5f}));    //  floats to double array to MFVec3f
>>>         boxCoordinateNode.setPoint(new MFVec3fObject().setValue(new double[] {-8,-9,4,-7,-7,5,-3,0,5}));            // doubles to double array to MFVec3f
>>>         boxCoordinateNode.setPoint(new MFVec3fObject().setValue(new double[] {-8.0,-9.0,4.0,-7.0,-7.0,5.0,-3.0,0.0,5.0}));// doubles to double array to MFVec3f
>>>         boxCoordinateNode.setPoint(boxPathPointArray); // restore
>>> ======================================================
>>>
>>> Deployment update complete.
>>>
>>> On 3/25/2017 1:08 AM, Don Brutzman wrote:
>>>> OK as hypothesized below, added a whole pile of paired float[] and double[] setValue() methods are now provided in the jsail.fields SF/MF field objects for flexible initialization there.
>>>>
>>>>     Package org.web3d.x3d.jsail.fields
>>>>     The fields subpackage is provided for creating typed X3D field values and also includes various utility capabilities.
>>>>     http://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/jsail/fields/package-summary.html
>>>>
>>>> Meanwhile fieldObject and fieldValueObject remain string based (as in XML), that design will take further consideration.
>>>>
>>>>
>>>> On 3/24/2017 8:36 PM, Don Brutzman wrote:
>>>>> [...]
>>>>>
>>>>> b. for floating point arrays, perhaps overloaded methods for double arrays when a float array is expected, avoiding the need for "f" after each value.
>>>>>
>>>>> however this could bloat the API quite a lot, also be more confusing.
>>>>>
>>>>> so, type conversion of individual complex-type values like that might be best accomplished in a deliberate fashion, so it might be better to concentrate such type-conversion methods in the SF/MF field object classes.
>>>>>
>>>>> For example, MFDouble.  existing methods can be found at
>>>>>
>>>>>     http://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/jsail/fields/MFDoubleObject.html#method.summary
>>>>>
>>>>>     void     setValue(double newValue)
>>>>>         Assign a single double as new array value.
>>>>>     void     setValue(double[] newValue)
>>>>>         Assign a new double[] value to this field.
>>>>>
>>>>> perhaps some additional set methods like
>>>>>
>>>>>     void     setValue(int newValue)
>>>>>         Assign a single int as new array value.
>>>>>     void     setValue(int[] newValue)
>>>>>         Assign a new int[] value to this field.
>>>>>
>>>>>     void     setValue(float newValue)
>>>>>         Assign a single float as new array value.
>>>>>     void     setValue(float[] newValue)
>>>>>         Assign a new float[] value to this field.
>>>>>
>>>>> The Java compiler must worry about the general case and thus can be pretty picky about type coercion, often requiring the programmer to coerce types explicitly so that no unintended loss of numerical fidelity occurs.  In terms of X3D scene graph, however, the typed precision of each value is strictly defined in the abstract specification, so there is no ambiguity about what the end-state is.  So there might be legitimate room for additions here while avoiding the creation of trapdoors for programmers to fall into.
>>>>>
>>>>> comments welcome.  i'll start by looking at setValue utility methods on objects like MFDoubleObject etc.
>>>>>
>>>>>
>>>>> On 3/24/2017 8:25 AM, yottzumm at gmail.com wrote:
>>>>>> There’s one with floating point numbers which is even bigger.  At least the previous message one is scrollable.
>>>>>>
>>>>>> John
>>>>>>
>>>>>> *From: *Don Brutzman <mailto:brutzman at nps.edu>
>>>>>> *Sent: *Friday, March 24, 2017 11:17 AM
>>>>>> *To: *yottzumm at gmail.com <mailto:yottzumm at gmail.com>
>>>>>> *Cc: *X3D Graphics public mailing list <mailto:x3d-public at web3d.org>
>>>>>> *Subject: *Re: X3DJSAIL: Exceeding Java String limits on setValue? What do we do?
>>>>>>
>>>>>> On 3/24/2017 5:33 AM, yottzumm at gmail.com wrote:
>>>>>>
>>>>>>> There are a couple of files where setValue exceeds Java string limits.  What should we do?  Would passing an array help?
>>>>>>
>>>>>> - please share example
>>>>>>
>>>>>> - ("splitting strings" + " is easy enough" + " for passed parameters")
>>>>>>
>>>>>> - arrays are definitely more efficient and more compact for compilation and storage
>>>>>>
>>>>>> - better understanding will likely lead to even further options
>>
>> all the best, Don
>
>
> all the best, Don


all the best, Don
-- 
Don Brutzman  Naval Postgraduate School, Code USW/Br       brutzman at nps.edu
Watkins 270,  MOVES Institute, Monterey CA 93943-5000 USA   +1.831.656.2149
X3D graphics, virtual worlds, navy robotics http://faculty.nps.edu/brutzman
-------------- next part --------------
package X3dForAdvancedModeling.Animation;

/*
Copyright (c) 1995-2017 held by the author(s).  All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer
      in the documentation and/or other materials provided with the
      distribution.
    * Neither the name of the Web3D Consortium (http://www.web3D.org)
      nor the names of its contributors may be used to endorse or
      promote products derived from this software without specific
      prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
import org.web3d.x3d.jsail.Core.*;
import org.web3d.x3d.jsail.EnvironmentalEffects.*;
import org.web3d.x3d.jsail.EventUtilities.*;
import org.web3d.x3d.jsail.fields.*;
import org.web3d.x3d.jsail.Geometry3D.*;
import org.web3d.x3d.jsail.Grouping.*;
import org.web3d.x3d.jsail.Interpolation.*;
import org.web3d.x3d.jsail.Navigation.*;
import org.web3d.x3d.jsail.Shape.*;
import org.web3d.x3d.jsail.Texturing.*;
import org.web3d.x3d.jsail.Time.*;

/*
   <meta name="generator" content="X3dToJava.xslt stylesheet to create X3DJSAIL Java program from X3D source." />
   <meta name="url"       content="http://www.web3d.org/x3d/stylesheets/X3dToJava.xslt" />
   <meta name="reference" content="X3DJSAIL, http://www.web3d.org/specifications/java/X3DJSAIL.html" />
*/
 
public class BoxSwitch
{
  X3DObject x3dModelObjectTree = new X3DObject().setProfile("Immersive").setVersion("3.3")
    .setHead(new headObject()
      .setMeta(new metaObject().setName("title").setContent("BoxSwitch.x3d"))
      .setMeta(new metaObject().setName("creator").setContent("Don Brutzman"))
      .setMeta(new metaObject().setName("created").setContent("30 December 2015"))
      .setMeta(new metaObject().setName("modified").setContent("4 March 2017"))
      .setMeta(new metaObject().setName("description").setContent("Show animation by switching Box nodes that are each covered by a different ImageTexture."))
      .setMeta(new metaObject().setName("reference").setContent("../GeometricShapes/CubeWithLabeledSides.x3d"))
      .setMeta(new metaObject().setName("drawing").setContent("../GeometricShapes/images/CubeSideImages.vsd"))
      .setMeta(new metaObject().setName("identifier").setContent("http://x3dGraphics.com/examples/X3dForAdvancedModeling/Animation/BoxSwitch.x3d"))
      .setMeta(new metaObject().setName("generator").setContent("X3D-Edit 3.3, https://savage.nps.edu/X3D-Edit"))
      .setMeta(new metaObject().setName("license").setContent("../license.html")))
    .setScene(new SceneObject()
      .addChild(new BackgroundObject().setSkyColor(new MFColorObject(new float[] {0.8f,0.8f,0.9f})))
      .addChild(new NavigationInfoObject())
      .addChild(new SwitchObject("BoxSwitcher").setWhichChoice(-1)
        .addChild(new ShapeObject()
          .setGeometry(new BoxObject("UnitBox"))
          .setAppearance(new AppearanceObject()
            .setTexture(new ImageTextureObject().setUrl(new MFStringObject("\"../GeometricShapes/images/RedImage.png\" \"http://x3dGraphics.com/examples/X3dForAdvancedModeling/GeometricShapes/images/RedImage.png\"")))))
        .addChild(new ShapeObject()
          .setGeometry(new BoxObject().setUSE("UnitBox"))
          .setAppearance(new AppearanceObject()
            .setTexture(new ImageTextureObject().setUrl(new MFStringObject("\"../GeometricShapes/images/GreenImage.png\" \"http://x3dGraphics.com/examples/X3dForAdvancedModeling/GeometricShapes/images/GreenImage.png\"")))))
        .addChild(new ShapeObject()
          .setGeometry(new BoxObject().setUSE("UnitBox"))
          .setAppearance(new AppearanceObject()
            .setTexture(new ImageTextureObject().setUrl(new MFStringObject("\"../GeometricShapes/images/TurquoiseImage.png\" \"http://x3dGraphics.com/examples/X3dForAdvancedModeling/GeometricShapes/images/TurquoiseImage.png\"")))))
        .addChild(new ShapeObject()
          .setGeometry(new BoxObject().setUSE("UnitBox"))
          .setAppearance(new AppearanceObject()
            .setTexture(new ImageTextureObject().setUrl(new MFStringObject("\"../GeometricShapes/images/YellowImage.png\" \"http://x3dGraphics.com/examples/X3dForAdvancedModeling/GeometricShapes/images/YellowImage.png\"")))))
        .addChild(new ShapeObject()
          .setGeometry(new BoxObject().setUSE("UnitBox"))
          .setAppearance(new AppearanceObject()
            .setTexture(new ImageTextureObject().setUrl(new MFStringObject("\"../GeometricShapes/images/WhiteImage.png\" \"http://x3dGraphics.com/examples/X3dForAdvancedModeling/GeometricShapes/images/WhiteImage.png\"")))))
        .addChild(new ShapeObject()
          .setGeometry(new BoxObject().setUSE("UnitBox"))
          .setAppearance(new AppearanceObject()
            .setTexture(new ImageTextureObject().setUrl(new MFStringObject("\"../GeometricShapes/images/GreyImage.png\" \"http://x3dGraphics.com/examples/X3dForAdvancedModeling/GeometricShapes/images/GreyImage.png\""))))))
      .addComments("Animated Box")
      .addChild(new TimeSensorObject("Clock").setCycleInterval(12).setLoop(true))
      .addChild(new IntegerSequencerObject("Sequencer").setKey(new float[] {0.0f,0.1667f,0.3333f,0.5f,0.6667f,0.8333f,1.0f}).setKeyValue(new int[] {0,1,2,3,4,5,0}))
      .addChild(new ROUTEObject().setFromField("fraction_changed").setFromNode("Clock").setToField("set_fraction").setToNode("Sequencer"))
      .addChild(new ROUTEObject().setFromField("value_changed").setFromNode("Sequencer").setToField("whichChoice").setToNode("BoxSwitcher"))
      .addChild(new ViewpointObject("OrbitingView").setPosition(-8.0f,0.0f,0.0f).setOrientation(new SFRotationObject(new float[] {0.0f,1.0f,0.0f,-1.57f})).setDescription("Orbiting view"))
      .addComments("Animated Viewpoint, orbiting about the origin")
      .addChild(new PositionInterpolatorObject("CircularPathPositionInterpolator").setKeyValue(new MFVec3fObject(new float[] {0.0f,0.0f,8.0f,1.389f,0.0f,7.878f,2.736f,0.0f,7.518f,4.0f,0.0f,6.928f,5.142f,0.0f,6.128f,6.128f,0.0f,5.142f,6.928f,0.0f,4.0f,7.518f,0.0f,2.736f,7.878f,0.0f,1.389f,8.0f,0.0f,0.0f,7.878f,0.0f,-1.389f,7.518f,0.0f,-2.736f,6.928f,0.0f,-4.0f,6.128f,0.0f,-5.142f,5.142f,0.0f,-6.128f,4.0f,0.0f,-6.928f,2.736f,0.0f,-7.518f,1.389f,0.0f,-7.878f,0.0f,0.0f,-8.0f,-1.389f,0.0f,-7.878f,-2.736f,0.0f,-7.518f,-4.0f,0.0f,-6.928f,-5.142f,0.0f,-6.128f,-6.128f,0.0f,-5.142f,-6.928f,0.0f,-4.0f,-7.518f,0.0f,-2.736f,-7.878f,0.0f,-1.389f,-8.0f,0.0f,-0.0f,-7.878f,0.0f,1.389f,-7.518f,0.0f,2.736f,-6.928f,0.0f,4.0f,-6.128f,0.0f,5.142f,-5.142f,0.0f,6.128f,-4.0f,0.0f,6.928f,-2.736f,0.0f,7.518f,-1.389f,0.0f,7.878f,0.0f,0.0f,8.0f})).setKey(new float[] {0.0f,0.02778f,0.05556f,0.08333f,0.11111f,0.13889f,0.16667f,0.19444f,0.22222f,0.25f,0.27778f,0.30556f,0.33333f,0.36111f,0.38889f,0.41667f,0.44444f,0.47222f,0.5f,0.52778f,0.55556f,0.58333f,0.61111f,0.63889f,0.66667f,0.69444f,0.72222f,0.75f,0.77778f,0.80556f,0.83333f,0.86111f,0.88889f,0.91667f,0.94444f,0.97222f,1.0f}))
      .addChild(new ROUTEObject().setFromField("fraction_changed").setFromNode("Clock").setToField("set_fraction").setToNode("CircularPathPositionInterpolator"))
      .addChild(new ROUTEObject().setFromField("value_changed").setFromNode("CircularPathPositionInterpolator").setToField("position").setToNode("OrbitingView"))
      .addChild(new OrientationInterpolatorObject("CenterFacingOrientationInterpolator").setKey(new float[] {0.0f,0.3333f,0.6667f,1.0f}).setKeyValue(new MFRotationObject(new float[] {0.0f,1.0f,0.0f,0.0f,0.0f,1.0f,0.0f,2.094395f,0.0f,1.0f,0.0f,4.18879f,0.0f,1.0f,0.0f,0.0f})))
      .addChild(new ROUTEObject().setFromField("fraction_changed").setFromNode("Clock").setToField("set_fraction").setToNode("CenterFacingOrientationInterpolator"))
      .addChild(new ROUTEObject().setFromField("value_changed").setFromNode("CenterFacingOrientationInterpolator").setToField("orientation").setToNode("OrbitingView"))
      .addComments("Additional Viewpoints")
      .addChild(new ViewpointObject().setOrientation(new SFRotationObject(new float[] {0.0f,1.0f,0.0f,1.57f})).setPosition(8.0f,0.0f,0.0f).setDescription("Front view"))
      .addChild(new ViewpointObject().setPosition(-8.0f,0.0f,0.0f).setOrientation(new SFRotationObject(new float[] {0.0f,1.0f,0.0f,-1.57f})).setDescription("Back view"))
      .addChild(new ViewpointObject().setPosition(0.0f,0.0f,8.0f).setDescription("Left view"))
      .addChild(new ViewpointObject().setPosition(0.0f,0.0f,-8.0f).setOrientation(new SFRotationObject(new float[] {0.0f,1.0f,0.0f,3.1416f})).setDescription("Right view"))
      .addChild(new ViewpointObject().setPosition(0.0f,8.0f,0.0f).setOrientation(new SFRotationObject(new float[] {1.0f,0.0f,0.0f,-1.57f})).setDescription("Top view"))
      .addChild(new ViewpointObject().setPosition(0.0f,-8.0f,0.0f).setOrientation(new SFRotationObject(new float[] {1.0f,0.0f,0.0f,1.57f})).setDescription("Bottom view")));
}


More information about the x3d-public mailing list