Hello Carlo,

Carlo Orru wrote:
For a general solution it is probably acceptable to go through the string accessors, it would be nice if it was possible to allow the user to replace this with something that requires knowledge of the type of the field being changed but can use e.g. the vector interface to modify values.
Could you please explain it better? How could such thing be accomplished ?

sorry, rereading this I realize now that it is rather hard to understand
without knowing what I was thinking at that time ;)
The functions that return/take strings to modify the field content
basically provide a very generic interface to fields, as you can use
them with minimal static type information (i.e. you only need a Field *
and the virtual functions Do The Right Thing).
However, if it is known that the Field * actually is a MFUInt32 * one
can call a specialized function for that case or instantiate a template
and inside use operator[] to modify the field contents, without having
to go through the virtual string interface.
So for the general (or fallback) case the string interface can be used,
but when the user is willing to provide more information (i.e. the type
of the field at compile time), a more efficient accessors could be used.

ok. What is the reason for FieldWrapper<T>::Interpolate taking two FieldWrapper<T> arguments and not two T arguments ?
Well, actually, there is no reason... Thanks for pointing it out...

Also, in what sense IS FieldWrapper<Quaternion> A Quaternion, i.e. why does it publicly derive from it?
Because in the beginning I wanted every field to be able to update itself
via the "Interpolate" method, i.e. I wanted to do something like this:

TransformPtr tr = Transform::create();
FieldWrapper<Quaternion> fw_q(Quaternion(Vec3f(1,0,0), deg2rad(60)));
tr->setRotation(fw_q);

this is basically a case of slicing; the field only stores a Quaternion
so everything else is sliced off fw_q and tr->getRotation only gives you
a Quaternion back.

In this way I thought I'd be able to directly update the field just by
calling FieldWrapper<Quaternion>::Interpolate. Well, I was wrong.
I'm trying to understand why this is necessary or a good thing to do; so what could something like the following not do?

// base template
template <class FieldT>
struct FieldValueInterpolator;


// partial specialization for SF
template <class ValueTypeT, Int32 NamespaceI>
struct FieldValueInterpolator<SField<ValueTypeT, NamespaceI> >
{
   typedef SField<ValueTypeT, NamespaceI> SFieldType;
   typedef typename SFieldType::ArgumentType ArgumentType;

   void updateField(Real32 fract, ArgumentType val0, ArgumentType val1,
                    FieldContainerPtr pCont, UInt32 fieldId)
   {
     SFieldType *pCastSF = static_cast<SFieldType *>(
        pCont->getField(fieldId));

     // interpolate between val0 and val1 depending on fract,
     // which is in [0,1]

     // write value to pCastSF using pCastSF->setValue()
   }
};

// partial specialization for MF
template <class ValueTypeT, Int32 NamespaceI>
struct FieldValueInterpolator<MField<ValueTypeT, NamespaceI> >
{
   typedef MField<ValueTypeT, NamespaceI> MFieldType;
   typedef typename MFieldType::ArgumentType ArgumentType;

   void updateField(Real32 fract, ArgumentType val0, ArgumentType val1,
                    FieldContainerPtr pCont, UInt32 fieldId)
   {
     MFieldType *pCastMF = static_cast<MFieldType *>(
        pCont->getField(fieldId));

     // interpolate between val0 and val1 depending on fract,
     // which is in [0,1]

     // write value to pCastMF using pCastMF->push_back(),
     // (*pCastMF)[i] etc.
   }
};

Admittedly, I have not fully thought through this idea and I'm not convinced that all the static typing is necessary/helpful at this level, but something similar might be used at a very low level to avoid the string accessors (sorry, for being pedantic about this, I don't like string based interfaces much ;) ).

This seems to be a very good way to interpolate the two values, but:

- How do I get the "fieldId" parameter ?

there are two ways, one to get it at compile time and one to get it at
runtime.
Node::ChildrenFieldId gives you the id of the children field of Node at
compile time, while
NodePtr n;
n->getType().getFieldDescription("children")->getId() gives you the same
thing at runtime.

- Is there any way to know what kind of value we are dealing with other
  than looking at the name string ? (I need to know the type in order to
  be able to perform the interpolation!)

that is a fundamental challenge when writing (object oriented) software
and in general C++ offers two solutions:
- by designing a class hierarchy with a common interface, you do not
need to know the (exact) type anymore, as the virtual function call
mechanism determines the right function to call, depending on the actual
type of object you are dealing with.
This approach becomes problematic when you need to pass values of
different types to a function that essentially performs the same task
for these types (i.e. interpolation between two values), because it is
not clear what the necessary common interface should be.
- templates allow you to preserve the static type of objects, without
manually writing code for every possible type.
Templates have their own problems of course, as excessive use is known
to cause code bloat and one quickly starts to carry around a large
number of type arguments, that are only required at some lower levels,
but now show up in high level interfaces.

To answer your question: Most things in OpenSG (all FieldContainers for
example) have a type object, that you can query for the name of the type
and also an id.

hm, GeoProperties are the ones that come to mind that already exist in the system and are quite likely to be animated. Let me know if these do not help and you need some containers for experimentation.
Sorry but no, they don't help... I need a FieldContainer  with some
MFields inside...

hm, they do have that, it just is a bit less obvious with the geo
properties, given all the template stuff around it ;)
Anyways, I've attached a .zip (slightly renamed to get SF to accept the attachment) file with a container that has some S and
MFields, place the files in Source/WindowSystem/GLUT and recompile
OpenSG (let me know if that causes a major problem for you, I can try to
move them to their own lib or so).

        Hope it helps,
                Carsten

Attachment: OSGAnimTestContainer.zip.TrickSF
Description: Binary data

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Opensg-core mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensg-core

Reply via email to