Re: [CPP] Storing data in a compileOp

Date : Mon, 12 Dec 2005 19:15:37 +0100
To : XSI(at)Softimage.COM
From : Guy Rabiller <guy(at)alamaison.fr>
Subject : Re: [CPP] Storing data in a compileOp

> ../.. The extra work with finding barycentric co-ordinates seems heavy
> - if I keep a copy a the pointLocatorData finding where it's shifted to seems
> to be very quick - the initial lookup being done only once then stored shouldn't
> have a big impact.../..


But - unless I missunderstand the PointLocatorData Class - the point of having a PointLocatorData Object rather than to keep a simple coordinate is to have these locations 'updated' whenever the mesh is animated/deformed right ? How do you think it is done ? Barycentric coordinates are involved. I'm just suggesting to 'do it yourself', so you compute the 'locations' on the fly, inside your operator without bothering having to save a 'persistent' PointLocatorData object. This shouldnt be heavier than what the PointLocatorData does.

> ../.. Only other thing is I'm not certain of whether the interpolation
> of the CAV map would give the same results as the actual shifted point../..


May be I missunderstood you at first.
You meant the direction is according to:
- the shift between the Base Object vertices and the Cage Object vertices.
- or between the nearest Base Object vertice from the Constrained Object, and the nearest Cage Object vertice from the Constrained Object ?


If it is the last one, then I missunderstood your on this point.

In this case you could add another set of 3 vertices inidices/barycentric coordinates ( no need for distance here ) of the Cage Object closest Triangle in the PPG/Parameters and add a new input for this Cage Object Geometry Primitive to the Operator #3 and you are set ?
--
guy rabiller | 3d technical director (at) LaMaison







Alan Jones a écrit :

Hi Guy,

Thanks very much for the thorough response. There are a few concerns I've got with that approach though I'm not sure whether they're worth being concerned with.

First is that I'd be layering extra objects in there - I'd rather keep the number of objects to a minimum as XSI chugs when you have huge numbers. i.e. 10k feathers will be pushing it without making it 20k or 30k objects.

The extra work with finding barycentric co-ordinates seems heavy - if I keep a copy a the pointLocatorData finding where it's shifted to seems to be very quick - the initial lookup being done only once then stored shouldn't have a big impact.

Only other thing is I'm not certain of whether the interpolation of the CAV map would give the same results as the actual shifted point. Though it may well do - my head is hurting trying to figure that one out though. :-)

Are these things I should be worried about? Thanks again.

Cheers,

Alan.

On 12/12/05, *Guy Rabiller* < guy(at)alamaison.fr <mailto:guy(at)alamaison.fr>> wrote:


Ok Alan, now that I have a clearer view of your problem, here are a few suggestions, hopping that I didnt miss anything. I'm trying here to stick to the XSI DAG 'spirit', avoiding hacks, try to make things as clean as possible.

    The point here, is to not play the 'persistent' approach, but the
    'on the fly computation' approach ( so the 'procedural idea' is
    conserved, when you touch something everything is updated ), then
    have the ability to make things persistent by baking maps or
    plotting datas, if you want, once the animation is validated.

    In practice, it will appear to behave as if there was 'persistent'
    datas:

    What you can do is to split the problem in 3, because you have 3
    problems to solve:
    - one is position constraint, nearby the Base surface
    - the second is the constraint position offset, idealy with
    manual, interactive update of each Constrained object.
    - the third beeing orientation constraint according to the Cage
    object vertices offsets relative to the Base object vertices.

    Perhaps you could adress these issues with those 4 steps:

    1) VertexColorMap Direction Vector Operator
    First you can deal with the Orientation problem in a total
    independent way, by computing all the direction vectors for the
    Base/Cage objects at once ( for each frame ), so that each
    Constrained object Operator will just 'look-up' at this
    information relatively quickly, and have this information
    persisted with the scene ( because in fact it is computed on the
    fly ).
    - Add a VertexColor Map to the Base object.
    - Create an Operator (#1)  that will update this map ( output ),
    according to the direction offset, vertices by vertices from both
    object geometry primitives ( input ).
    - Encode this direction in RGB ( x in R, y in G, .. ) in the
    VertexColorMap.
    The VertexColorMap will then contain direction vector, and will be
    computed on the fly, updated automatically by your Operator
    whenever you deform the Cage object and/or the Base object, so you
    can animate both.
    You could even bake ( or rendermap ) the sequence by creating a
    TextureMap sequence, and connect it ( in fact the UVs, source
    Clip, Cluster ) to the Operator in place of the VertexColorMap (
    use optional input ports here ), this way no computation will take
    place this time, you would have a direction vectors 'cache'
    through picture sequences.

    2) Direction Constraint Operator
    - Create an simple Operator (#2) wich will update the Constrained
    objects Orientation ( output ) according to the VertexColorMap (
    input ) or the TextureMap 'cache' ( input ) from the 'encoded'
    vectors.
    - Its up to you to interpolate the directions nearby a triangle.
    - Once the animation is validated you can 'cache' the Constraint
    by plotting the Orientation of your Feathers, making it persistent
    ( really this time ) so it will be updated very quiickly, and
    remove your Operator.

    3) Position Constraint
    - For each Feather create a Null and position it where the Feather
    should be constrained.
    - Parent the Feather under its Null.
    - Create a new Operator (#3) connected ( input ) to the Base
    Object Geometry, and to the Position ( output ) of the Null.
    - For each Null, retrieve the nearest triangle.
    - From the triangle, get this datas:
    -- The 3 vertices indices ( rather than their positions ).
    -- The Triangle Barycentric coordinates of the Null.
    -- The distance of the Null to the Triangle Plane ( according to
    its Normal )
    So 2 vectors and a scalar. It seems a lot of data, but it will
    allow you to keep track of the deformation of the Base object, and
    recompute the correct Null position on the fly. No need to store
    the positions then.
    - When you Constraint your Feather, you record those datas in a
    PPG under the Feather connected to the Operator, or in the
    Operator Parameters.
    - Inside your Operator, you look for those datas and 'look-up' for
    the 3 triangle vertices from their IDs, then recompute the correct
    position of the Null.
    - Again, you can 'cache' the Null Positions by simply plotting
    them once the animation is validated, then making it persistent (
    really this time ), so they will be updated very quickly. You can
    then remove your Operator.

    As a note, you could combine Operator #2 and #3 if you like, so
    only the Nulls will be constrained both in Position and Orientation.

    4) Position ( and even Orientation ) Offset
    - Parent Each Feather under his associated Null.
    - With each Constrained object parented under their respective
    Null, it is now trivial to move them as regular children, even
    rotate them manually if you have combined Operator #2 and #3.
    - Once you have Moved your Feather, you can update the Null
    Operator PPG/Parameters, by checking the nearest triangle again,
    and update the vertices indices/barycentric coordinates and
    distance. This could be done either by:
    -- Using a Command ( from a menu or script ).
    -- Using an Event ( so that it would be automatically done
    whenever you move the Feather )
    Before you update those, record the Feather Position ( global ),
    Update ( the Feather will move because the Null might move, then
    place back the Feather in the previous Position.
    - Note that once the Null Positions are cached, it wont update
    anything anymore.


Sorry for the long description, I hope its relatively clear, tell me if that is of any help to your problem and if I didnt assumed anything wrong.

    --
    guy rabiller | 3d technical director (at) LaMaison


Alan Jones a écrit :

    Hi Guy,

    Thanks for your help.. That's not what I'm trying to do. I'll put
    it from the ground up so it will hopefully make sense.

    It's for feathers in this case. My plan is to have a mesh and a
    second copy of the mesh - I'll call them base and cage meshes.
    The cage mesh will be approximately a push of the base mesh (
    though it doesn't need be - could be set as you like). The
    important bit here is that they are topologically (is that even a
    real word?) identical. You'll then place your objects to be
    constrained near the surface of the base mesh. The constrained
    object will need to store a pointLocatorData (the XSI format for
    the closestLocations thing) and a vector for it to use in later
    lookup. The line that goes from the closestPoint of the base mesh
    to the equivalent point ( i.e. the center of polygon 3214 or
    whatever) on the cage mesh. Changes to this direction will be
    used to reorient the constrained objects and movement of the
    point on the base mesh will be used to reposition the constrained
    object.

    For this to work I'd need to know the initial relative positions
    of the base and cage mesh. Ideally I'd like to store a copy of
    the Geometry (i.e. the XSI geometry class object) but I've
    resigned myself to being unable to do this and so will just have
    extra copies of the mesh for this. I would store the verticies,
    but then I can't do a lookup using the pointLocatorData which
    defeats the point. ooo actually I could just store the initial
    direction vector in the compiledOp of the constrained object like
    everything else - sweet - ok that's the problem sorted if I can
    get a good permanent storage solution.

    So the other things I need are the pointLocatorData and the
    position vector that's in tangent space for each one. If I did
    use a userdatablob would it create a performance impact by the
    time I had thousands of constrained objects? Though by
    performance impact impact I mean compared with some way of
    storing the data in the custom operator. The performance doesn't
    have to be great as I can just have a group to hide most of the
    feathers during animation - it just has to not be so ridiculous
    that rendering will become impractical. Worst case scenario I can
    use parameters for both of the vectors - though I still really
    need to store a binary pointLocatorData and have it remain
    between saves. Though once that's solved I may as well use a
    struct with the vectors as well.

    Thanks for any ideas.

    Cheers,

    Alan.

    On 12/12/05, *Guy Rabiller* <guy(at)alamaison.fr
    <mailto:guy(at)alamaison.fr> > wrote:


../.. will this data persist between saves? ../..

No. Your class is deleted when the Operator is deleted, so everything 'disappear'.


../.. I've been assuming all this time that init is
called on creation and term on deletion. Is that
the case or is it called everytime I load up the
scene as well? ../..

When your load up the scene, the Operators are created by XSI, so you've been assuming right.


../.. Was hoping to avoid a blob due to the number
of simultaneous copies I'll be using of this and I'd like
to try keep setup as simple as possible ../..

The setup or the coding ? :-)


Just to be sure I understand what you are trying to do:

        You have 2 mesh objects, and you want to Constraint one
        object to the second object, so that one vertice of the
        Constrained object is at a certain distance and in the normal
        direction of one vertice of the Constraining object ? Or do I
        have all wrong ?

        Still it's unclear why you would want to call your
        class/operator methods/functions from outside the operator.

        --
        guy rabiller | 3d technical director (at) LaMaison


Alan Jones a écrit :

        Hi Guy,

        Thanks for that - just to check I've followed - I have my
        operator class and it stays as is - then I just use it to
        create an pass data through to my other class which has any
        additional functionality I want?

        Seeing this position is the offset I thought I may want to
        change it to whatever the current difference is. hmmm
        actually I just realised something - I've been assuming all
        this time that init is called on creation and term on
        deletion. Is that the case or is it called everytime I load
        up the scene as well? i.e. will this data persist between saves?

        Cheers,

        Alan.

        On 12/12/05, *Guy Rabiller* <guy(at)alamaison.fr
        <mailto:guy(at)alamaison.fr>> wrote:



../.. The data should persist until I
delete the compiledOperator. ../..

This should be automatic, as long as you use a class for your compiled operator rather than directly using the callbacks.

            First create a Class wich has the 3 members
            Init/Update/Term with similar arguments as of the callbacks.
            Then when in the operator Init callback, create a new
            instance of your class then

            CYourClass* pYourInstancePointer = new CYourClass();
            inCtx.PutUserData(
            (CValue::siPtrType)pYourInstancePointer );
            pYourInstancePointer->Init(inCtx);

            In the Update and Term, retrieve your pointer:

            CValue::siPtrType pUserData = in_ctx.GetUserData();
            CYourClass* pYourInstancePointer = (CYourClass*)pUserData;

            and either
            pYourInstancePointer->Term(inCtx)
            or
            pYourInstancePointer->Update(inCtx, outPort)

            Now your Class can contain any public or private
            members/properties, and it will be persistent until you
            delete the operator.

../..I'm making a customOperator that will be working ../..

I meant why would you want to call the function from outside of your Class/Operator ?


-- guy rabiller | 3d technical director (at) LaMaison

            Alan Jones a écrit :

            Hi Guy,

            The data should persist until I delete the
            compiledOperator.

            I'm making a customOperator that will be working as a
            constraint and I want to store the initial position of
            the point being constrained relative to another point
            (using pointLocatorData and a vector in tangent space)
            so I want to store both of those pieces during the init
            function. Then later I was to grab those - check the
            changed position of the point it's relative to and
            figure out the new location.

            Cheers,

            Alan.

            On 12/12/05, *Guy Rabiller* <guy(at)alamaison.fr
            <mailto:guy(at)alamaison.fr>> wrote:


../.. I'd like to store some data (a vector)
in my compiled op for it to reference later ../..

Define 'later' ?

                How 'far' the data(s) should be persistent ?

../.. is there a way to call my own functions on
                the class ../..

                Why would you do that ?
                --
                guy rabiller | 3d technical director (at) LaMaison


Alan Jones a écrit :

Hi All,

I'd like to store some data (a vector) in my
compiled op for it to
reference later - though I don't want the user to
see it.

I've looked at the init function - which seems
like a good enough
place to start, but can't seem to find a nice
place to keep it. Is
adding my own variables to the class going to
break anything? or is
that how I should be doing it?

It might be nice to be able to change it from a
command too - is there
a way to call my own functions on the class if I
add them or is
update, init and term or I can really work within.

Thanks for any help.

Cheers,

Alan.



---
Unsubscribe? Mail Majordomo(at)Softimage.COM with the following text in body:
unsubscribe xsi


Search the XSI List archives here or use the advanced search form to search across mailing lists. Searching help is available.
This site supposedly brought to you by Benjamin Grosser and the Imaging Technology Group.