Hello Carlo,

Carlo Orru wrote:
> During the last days I've been working on my framework, thus it has
> undergone some changes since I wrote my last e-mail...
> Now I have added the possibility for the user to separately specify the 
> field value (or the vector of values in case of a multi-field) to be 
> modified, instead of specifying the whole FieldContainer.
> In order for this to work, the user has to input the value (for example 
> a Color3f, or a Quaternion) or the collection of values, the mask and 
> the field name(s). So we can have both control points holding a field 
> container and control points holding field value(s).
> 
>>   
>>> The Animate() method works as follows:
>>> after calculating the current time, a new ControlPoint object with a
>>> field container inside is created. Such field container is then assigned
>>> the correct value which has just ben retrieved from the interpolation
>>> between two control points, and then the update of the field container
>>> returned by "someNode->getCore()" can take place:
>>>     
>> I guess I'm missing something here, but why do you have to create a new 
>> container here? I would have expected (and your example actually seems 
>> to support this) that there is one container in the graph and a number 
>> of them (of the same type) as control points associated with points in 
>> time. The update computes the interpolation between values of the 
>> control points and stores these into the container in the graph.
>>
>>   
> Now I don't create a new container anymore: the field container whose 
> fields are to be updated is handed down directly to the newly created 
> control point (inside the Animate() method).

ok.

>>> using the field mask
>>> provided to the ControlPointList object to identify the fields to be
>>> updated and checking the string returned by the 
>>> FieldContainer::getTypeName() in order to know what tipe of core we are
>>> dealing with, the appropriate fields are updated via CPEdit(fcPtr,
>>> field_mask).
>>>     
>> why do you need to know what type of core is being used, or what do you 
>> do with this information, how does it influence the "the appropriate 
>> fields are updated" step ?
>>   
> The step you mentioned is no more influenced by the knowledge about the 
> type of core which is being dealt with: the update process now only 
> relies on the field(s) name(s) (requested to the user when creating the 
> control point list) and, of course, on the mask, which is also requested 
> to the user. In fact I use the getField(Char8* field_name) method to 
> gain acces to the field specified by 'field_name', and then I use 
> methods like setAbstrValue(), pushValueByStr() and getValueByStr() to 
> access/update the field.

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.

>>> This method has been tested and seems to work fine, but I also would
>>> like to try a different approach such as, for example, passing a plain
>>> Vec3f to the ControlPoint class constructor and making the appropriate
>>> field do the update by itself (perhaps using some kind of Vec3f wrapper
>>> class with an update() method inside).
>>>     
>> hm, I'm not sure if I understand this alternative approach, what does a 
>> Vec3f have to do with animating a MFColor4f for example?
>> In general I'm not too big a fan of wrapping something as basic as a 
>> Vec3f, especially as this class gives you full access to it's members. 
>> Therefore a non-intrusive approach should be possible, i.e. having a 
>> function that can interpolate between two Vec3f need not be a member 
>> function.
>>
>>   
> Such approach, which is currently being worked on, consists in wrapping
> field types like Quaternion, Vec3f, Color3f and so on, using a template
> class. For example, if we were dealing with a Quaternion, things would
> look like this:
> 
> template <>
> class FieldWrapper<Quaternion> : public Quaternion
> {
>     public:
>         FieldWrapper(void);
>         FieldWrapper(Quaternion q);
>         void Interpolate(Real32, FieldWrapper<Quaternion>,
>                                  FieldWrapper<Quaternion>);
>         void UpdateFC(FieldContainerPtr, BitVector, const Char8*);
> };
> 
> In this way, I can make the wrapper class itself hold the result of the
> interpolation which is to be used to update the chosen field container.
> Obviously, if we were dealing with a MFColor4f we had to use a
> FieldWrapper<Color4f> class, for the difference between single fields 
> and multi fields is handled by the control point and the animation 
> controller: the ControlPoint object stores the field(s) passed by the 
> user inside a MFVector<> object, which, in case of a single fielded 
> control point, has only one element inside.

ok. What is the reason for FieldWrapper<T>::Interpolate taking two 
FieldWrapper<T> arguments and not two T arguments ?
Also, in what sense IS FieldWrapper<Quaternion> A Quaternion, i.e. why 
does it publicly derive from it?
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 ;) ).

[Reformatted so that answer directly follows question]
>> Some more general question on your framework:
>> - What part is responsible for performing the actual interpolation 
>> between values?
 >
 > - The actual interpolation is performed by the FieldWrapper<> class.
 >
>> - How does it handle MFields of different sizes?
 >
 > - MFields of different sizes are handled by the AnimationController
 >    object, which repeatedly calls the FieldWrapper<>::Interpolate()
 >    and FieldWrapper<>::UpdateFC() methods in order to update every
 >    field element.
 >         *** I don't know if this answers your question... if not,
 >         *** could you please be more specific? What do you mean by
 >         *** "different sizes" ? Maybe an example would make things
 >         *** clearer... Thanks.

This is admittedly a vague question and I'm not sure what a good answer 
is either nor did I think that much about it before asking, sorry; 
simply not allowing the situation might be the only reasonable thing to do.
Anyway, the question was, whether there is some way one can define the 
interpolation between a e.g. MFColor3f with 1 value and one with 3 
values. As an example, think of a GradientBackground that starts with a 
single color and is blended to an actual gradient with three colors (of 
course this can also be achieved by using the same color for all 3 
values for the starting control point).
Hm, the more I think about this, the more I get the impression that this 
can not be reasonably defined in general...

>> - Is there a way to customize the interpolation process for different 
>> types or even instances of containers/fields (for example it is likely 
>> that one would handle quaternions in a special way instead of just 
>> interpolating linearly)?
 >
 > - The customization of the interpolation process is planned, but is
 >    currently yet to be implemented. At the moment, only linear
 >    interpolation is supported.

That's fine, I just wanted to know if it is being considered in the design.

>> - How is behavior for time values outside the range covered by control 
>> points handled (e.g. are there ideas on how to do looped or chained 
>> animations)?
> 
> - As long as the current time value remains below the one assigned to
>    the first control point in the list, then the first control point's
>    values are used to update the specified field container. If the
>    current time value is above the one assigned to the last control
>    point in the list, then the last control point's values are used to
>    update the specified field container.
>    There's currently no support for looped or chained animations: again,
>    those features are planned but not being worked on at the moment.

Ok, same as above.

> Actually, the multi-field support has just been implemented, but is yet 
> to be tested, so I'm still not sure whether it works properly or not.
> Could you please make some examples of field containers with 
> multi-fields I could test my code on ?

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.

> And also, how can the whole animation process be stored inside an OpenSG 
> binary file?

For the fields of a fieldcontainer this capability comes for free (as 
long as the field holds values of a type that is already used somewhere 
in the system. Adding new fields is possible, but not something that I 
can describe in one sentence ;) ).
I guess the key here is to separate data that describes an animation 
from the logic that performs it. With this separation, the data can be 
stored in FieldContainers and binary conversion comes for free. The 
tricky part of course is finding the right data to fully describe a 
large set of possible animation schemes in a simple, intuitive and 
compact way :)

        Thanks,
                Carsten


-------------------------------------------------------------------------
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