Plugin Cafe Homepage
Forum Home Forum Home > Plugin Cafe > SDK Help
  New Posts New Posts
  FAQ FAQ  Forum Search

UV Mirror H&V

Page  12>
Author
Message
  Topic Search Topic Search
Dynad View Drop Down
Member
Member
Avatar

Joined: 2012 Jul 08
Online Status: Offline
Posts: 8
Direct Link To This Post Topic: UV Mirror H&V
    Posted: 2012 Jul 21 at 2:22pm

User Information:

Cinema 4D Version:   13 
Platform:   Windows  ;   
Language(s):     C++  ;   

---------

User Information:

Cinema 4D Version:    13
Platform:      Win
Language(s):       C++

---------


Hey,

Is there a function available that can mirror the uv map? I tried it with CallCommand, but for some reason i don't get it working with 1 button click.

When i try this:
CallCommand(17039); // uv mode
CallCommand(170023); // flip vertical

The mirror function is never called, do i need to wait (Sleep the thread) or is there a direct function i can use for this method?


Thnx,
~Dynad

Back to Top
ScottA View Drop Down
Member
Member


Joined: 2011 Jan 07
Online Status: Offline
Posts: 2288
Direct Link To This Post Posted: 2012 Jul 25 at 8:25am
Is support going to answer this person's question?

I have some questions about the SDK and UV support too.  And the answer to this question might help me with out my own UV editing questions.

-ScottA
Back to Top
Dynad View Drop Down
Member
Member
Avatar

Joined: 2012 Jul 08
Online Status: Offline
Posts: 8
Direct Link To This Post Posted: 2012 Jul 25 at 7:00pm
Well after some testing and trying, i came with the following conclusion.

When you're in polygon mode or any mode u have in the standard layout and you want a button that switches to polygon uv mode. It doesn't work, but when i change the layout first to bodypaint UV and back.. and then i push my plugin button with the callcommand it works without any problems.

I don't know if it's a bug, but its really annoying that u can't use Bodypaint functions directly after C4D is loaded. So i came up with my own function that does the uv switching.


~Dynad
Back to Top
ScottA View Drop Down
Member
Member


Joined: 2011 Jan 07
Online Status: Offline
Posts: 2288
Direct Link To This Post Posted: 2012 Jul 25 at 7:39pm
When you say you came up with your own function. Do you mean that you are switching layouts, then executing the CallCommands with a function?
Or are you editing the UV's directly inside of the UVW struct?

One of the problems I'm having is figuring out how to execute the "Frontal" projection button.
Frontal (and several other buttons) is not listed in the SDK. And it's not declared in the painter.h file. So AFAIK it can't be called with the CallUVCommand().
I was hoping the support guys would provide you a solution to making the Mirror V button work. Because that too is a button that is not supported in CallUVCommand. Just like the Frontal button.

I'm also having an issue getting changed UVW struct vertices to update after I change them.
But that's a separate issue.

-ScottA


Edited by ScottA - 2012 Jul 25 at 7:40pm
Back to Top
Dynad View Drop Down
Member
Member
Avatar

Joined: 2012 Jul 08
Online Status: Offline
Posts: 8
Direct Link To This Post Posted: 2012 Jul 25 at 9:39pm
Well i rewrote the function myself, cause i couldn't fix the button problem. So i edit the UVW struct instead.

The only way to call the functions is to use the callcommand and use its ID which u can look up in the "Customize commands".

If u want to edit the struct, u need to make sure that your in write mode.
GetDataAddressR(),i,uvw) <-> GetDataAddressW(),i,uvw);


~Dynad
Back to Top
ScottA View Drop Down
Member
Member


Joined: 2011 Jan 07
Online Status: Offline
Posts: 2288
Direct Link To This Post Posted: 2012 Jul 26 at 7:47am
The UV point editing problem I'm having is the UV points don't move. Even when using the W flag.

Here's the code:
    BaseObject *obj = doc->GetActiveObject();
    if(!obj)return FALSE;
    PointObject *pobj = ToPoint(obj);           //Cast the BaseObject type to a PointObject type and assign it to a variable "pobj"
    Vector *points = pobj->GetPointW();         //Get the array of points in the object(returns their vector positions)
    LONG count = pobj->GetPointCount();

    TempUVHandle *handle = GetActiveUVSet(doc, GETACTIVEUVSET_ALL);  //Create an instance of the TempUVHandle class
    if (!handle) return FALSE;

    UVWTag *uvwtag = (UVWTag*)(pobj->GetTag(Tuvw, 0));         //The UVW tag that's on the object
    UVWHandle dataptr = uvwtag->GetDataAddressW();             //The array of polygons in the UVWtag
    LONG UVpolycount = handle->GetPolyCount();
    GePrint(LongToString(UVpolycount));
    UVWStruct res;                                             //A struct that we will eventually store the UV values in

    for (LONG i=0; i<UVpolycount; i++)
    {
        LONG polyindx = i;                //Assign the polygon's index# to a variable

        UVWTag::Get(dataptr, i, res);     //Store the polygon UVW info into the variable "res"
   
        Real ax = res.a.x;                //These are the x,y UV canvas coords. for each point in each UVpolygon(a,b,c,d)
        Real ay = res.a.y;

        ax = 0.5;                         //Move the vertex res.a.x to 0.5 on the canvas
        uvwtag->Set(dataptr,i,res);       //Update the changes to the UVpolygon in the UVW tag <--------Not working!!

        GePrint("ID#: " + LongToString(polyindx));
        GePrint("AX: " + RealToString(ax) +".... " + "AY: " + RealToString(ay));
    }

    FreeActiveUVSet(handle);              //Free the memory
    pobj->Message(MSG_UPDATE);
    EventAdd();

Everything appears to work correctly. But for some reason the UVW tag won't update to reflect the changes I've made to any of the UV points.
I thought the Set() function was for setting any UV changes. But it's not working for me. And I don't know why.

-ScottA
Back to Top
Matthias Bober View Drop Down
Forum Moderator
Forum Moderator


Joined: 2006 Oct 16
Location: Germany
Online Status: Offline
Posts: 2204
Direct Link To This Post Posted: 2012 Jul 26 at 8:02am
I would recommend to change the UVs directly from the UVWTag with UVWTag::GetDataAddressW and UVWTag::Get and UVWTag::Set. This will give you a pointer to the UV array and the individual UV structures. The UVWStruct contains the UVs for the given polygon. Mirror the UV vectors and set the UVs with UVWTag::Set.

cheers,
Matthias

MAXON
developer support
Back to Top
Matthias Bober View Drop Down
Forum Moderator
Forum Moderator


Joined: 2006 Oct 16
Location: Germany
Online Status: Offline
Posts: 2204
Direct Link To This Post Posted: 2012 Jul 26 at 8:03am
Scott, I think you need to send a MSG_UPDATE message to the UVWTag as well.

cheers,
Matthias

MAXON
developer support
Back to Top
ScottA View Drop Down
Member
Member


Joined: 2011 Jan 07
Online Status: Offline
Posts: 2288
Direct Link To This Post Posted: 2012 Jul 26 at 8:19am
Thanks for the help Matthias,
uvwtag->Message(MSG_UPDATE); didn't seem to help.

I'm not sure how to use UVWTag::GetDataAddressW; like you're suggesting.
How do I use it so it knows which UWV tag I'm referring to?
Do I set the tag active active with: SetBit(BIT_ACTIVE);
Then follow it with:  UVWTag::GetDataAddressW;?

The UVWTag class is a bit confusing to me trying to use it directly like that.

-ScottA


Edited by ScottA - 2012 Jul 26 at 8:21am
Back to Top
Matthias Bober View Drop Down
Forum Moderator
Forum Moderator


Joined: 2006 Oct 16
Location: Germany
Online Status: Offline
Posts: 2204
Direct Link To This Post Posted: 2012 Jul 26 at 8:23am
I'll try to come up with an example.

cheers,
Matthias

MAXON
developer support
Back to Top
ScottA View Drop Down
Member
Member


Joined: 2011 Jan 07
Online Status: Offline
Posts: 2288
Direct Link To This Post Posted: 2012 Jul 26 at 8:28am
That would be very helpful. Thank you.

Also.
Is there any way at all that we can execute the UV projection buttons (Sphere, Cylinder, Frontal, etc..)?


Thanks,
-ScottA
Back to Top
Matthias Bober View Drop Down
Forum Moderator
Forum Moderator


Joined: 2006 Oct 16
Location: Germany
Online Status: Offline
Posts: 2204
Direct Link To This Post Posted: 2012 Jul 26 at 8:33am
Many of the UV commands are avaible through the CallUVCommand function. This would be an alternative for mirroring as well. It's the way BodyPaint works. I'll try to show this in the example rather than through the UVWTag.

So there are several ways to manipulate UVs. In the end it always depends on what you are exactly trying to do.

cheers,
Matthias

MAXON
developer support
Back to Top
ScottA View Drop Down
Member
Member


Joined: 2011 Jan 07
Online Status: Offline
Posts: 2288
Direct Link To This Post Posted: 2012 Jul 26 at 9:06am
You actually already posted an example how to use CallUVCommand() a while back. And that's where I learned how to use it.
But there's a lot of buttons that are not included in it. Like the "Frontal" and "Mirror V"buttons for example. That's why I switched to editing the UV points individually.
I'm looking in the C4D_painter.h file. And I don't see these buttons defined in there.
And in the C4D_painter.cpp file. The function seems to call to a private class:
return 
C4DOS.Pa->CallUVCommand(padr,PointCount,polys,lPolyCount,uvw,polyselection,pointselection,op,mode,cmdid,settings);

Even if the users were smart enough to add new definitions to CallUVCommand(). It seems that we can't access the class that does all the work. But maybe I'm missing something?

That's why I was thinking there might be an undocumented way to execute the actual buttons themselves. Something similar to this:
     LONG tool_id = doc->GetAction();

     BasePlugin *tool = NULL;
     tool = FindPlugin(tool_id, PLUGINTYPE_TOOL);

     if(!tool) return FALSE;

     DescriptionCommand dc;
     dc.id = DescID(MDATA_CREATEPOLYGON_BUTTON);
     tool->Message(MSG_DESCRIPTION_COMMAND, &dc);

     EventAdd();



-ScottA
Back to Top
Giblet View Drop Down
Member
Member


Joined: 2003 May 21
Online Status: Offline
Posts: 465
Direct Link To This Post Posted: 2012 Jul 26 at 10:54am
In case it's useful, here is some code that I cobbled together from some older SDK example code...


//------------------------------------------------------------------------------------------------------
//******************************************************************************************************
// FrontalMapUVs() - perform a simple 'frontal' uv-mapping
//******************************************************************************************************
//------------------------------------------------------------------------------------------------------
#define SIGDIG    5.0
static Real sign(Real n)
{
    if( n > 0.0 )    return 1.0;
    if( n < 0.0 )    return -1.0;
    return 0.0;
}
static Real TrimDecimal(Real num, Real digits)
{
    Real n;

    n = num * Pow((Real)10.0, digits);
    n = sign(n) * Abs(Floor(n + 0.5));
    return n / Pow((Real)10.0, digits);
}

Bool FrontalMapUVs(PolygonObject *op, Matrix mg)
{
    if( !op ) return false;

    LONG numFaces = op->GetPolygonCount();
    LONG numVerts = op->GetPointCount();
    Vector *pVerts = op->GetPointW();
    CPolygon *pPolys = op->GetPolygonW();

    UVWTag *pUVTag = (UVWTag *)op->MakeVariableTag(Tuvw, numFaces);
    if( !pUVTag )
        return false;

#ifdef _R12_SDK_
    UVWHandle    pUVHndl = pUVTag->GetDataAddressW();
    if( !pUVHndl )
        return false;
#elif _R11p5_SDK_
    void *pUVHndl = pUVTag->GetDataAddressW();
    if( !pUVHndl )
        return false;
#else
    void *pUVHndl = NULL;
#endif

    LONG ndx;
    Real lenxinv, lenyinv, lenzinv;
    Vector mapCenter, mapSize, vMin, vMax;

    vMin.x = 100000.0;
    vMin.y = 100000.0;
    vMin.z = 100000.0;
    vMax.x = -100000.0;
    vMax.y = -100000.0;
    vMax.z = -100000.0;

    for(ndx=0; ndx<numVerts; ndx++)
    {
        Vector pt = pVerts[ndx] * mg;

        if( pt.x < vMin.x ) vMin.x = pt.x;
        if( pt.x > vMax.x ) vMax.x = pt.x;
        if( pt.y < vMin.y ) vMin.y = pt.y;
        if( pt.y > vMax.y ) vMax.y = pt.y;
        if( pt.z < vMin.z ) vMin.z = pt.z;
        if( pt.z > vMax.z ) vMax.z = pt.z;
    }

    mapSize.x = Abs(vMax.x - vMin.x);
    mapSize.y = Abs(vMax.y - vMin.y);
    mapSize.z = Abs(vMax.z - vMin.z);

    mapCenter.x = vMin.x+(mapSize.x*0.5);
    mapCenter.y = vMin.y+(mapSize.y*0.5);
    mapCenter.z = vMin.z+(mapSize.z*0.5);

    if (mapSize.x!=0.0) lenxinv = 1.0/mapSize.x;    else lenxinv = 0.0;
    if (mapSize.y!=0.0) lenyinv = 1.0/mapSize.y;    else lenyinv = 0.0;
    if (mapSize.z!=0.0) lenzinv = 1.0/mapSize.z;    else lenzinv = 0.0;

    // Walk the list of polygons and map the UVs
    for(ndx=0; ndx<numFaces; ndx++)
    {
        UVWStruct uvw;

        cmpUVGet(pUVTag, pUVHndl, ndx, uvw);

        Vector pt_a = (pVerts[pPolys[ndx].a] - mapCenter) + mg.off;
        Vector pt_b = (pVerts[pPolys[ndx].b] - mapCenter) + mg.off;
        Vector pt_c = (pVerts[pPolys[ndx].c] - mapCenter) + mg.off;
        Vector pt_d = (pVerts[pPolys[ndx].d] - mapCenter) + mg.off;

        uvw.a.x = TrimDecimal((pt_a.x*lenxinv)+0.5, SIGDIG);
        uvw.a.y = TrimDecimal((-pt_a.y*lenyinv)+0.5, SIGDIG);

        uvw.b.x = TrimDecimal((pt_b.x*lenxinv)+0.5, SIGDIG);
        uvw.b.y = TrimDecimal((-pt_b.y*lenyinv)+0.5, SIGDIG);

        uvw.c.x = TrimDecimal((pt_c.x*lenxinv)+0.5, SIGDIG);
        uvw.c.y = TrimDecimal((-pt_c.y*lenyinv)+0.5, SIGDIG);

        uvw.d.x = TrimDecimal((pt_d.x*lenxinv)+0.5, SIGDIG);
        uvw.d.y = TrimDecimal((-pt_d.y*lenyinv)+0.5, SIGDIG);

        cmpUVSet(pUVTag, pUVHndl, ndx, uvw);
    }
    return true;
}


...note that I call that routine IF the mesh is not already uv-mapped...


    // start by grabbing the current UVWTag
    UVWTag *pSrcUVs = (UVWTag*)(op->GetTag(Tuvw, 0));
    if( !pSrcUVs )
    {
        // if not already mapped, do a simple frontal mapping
        if( !FrontalMapUVs(op, op->GetMgn()) )
            return NULL;
....


...also note that I'm just passing the mesh's global matrix, so you could remove that argument and just grab it inside that routine.

The only other note is the "cmpUVGet()/cmpUVSet()" calls... those are calls to my version-compatibility routines...


//-------------------------------------------------------------
// cmpUVGet()
//-------------------------------------------------------------
void cmpUVGet(UVWTag *pUVWTag, UVWHandle pUVHndl, LONG ndx, UVWStruct& uvw)
{
#ifdef _R11p5_SDK_
    if( pUVWTag && pUVHndl )    pUVWTag->Get(pUVHndl, ndx, uvw);
#else
    if( pUVWTag )                uvw = pUVWTag->Get(ndx);
#endif
}

//-------------------------------------------------------------
// cmpUVSet()
//-------------------------------------------------------------
void cmpUVSet(UVWTag *pUVWTag, UVWHandle pUVHndl, LONG ndx, const UVWStruct& uvw)
{
#ifdef _R11p5_SDK_
    if( pUVWTag && pUVHndl )    pUVWTag->Set(pUVHndl, ndx, uvw);
#else
    if( pUVWTag )                pUVWTag->Set(ndx, uvw);
#endif
}


...where my _Rxx_SDK_ defines are cumulative (ie. R11.5 is also defined in my R12 (and later) builds and R11.5 and R12 defines are also defined in my R13 (and later) builds, along with the R13 define, etc.).  This is a carry-over from long, long ago... I'm in the process of changing over to a "#if API_VERSION < 13000" type system.





Edited by Giblet - 2012 Jul 26 at 10:58am
Back to Top
ScottA View Drop Down
Member
Member


Joined: 2011 Jan 07
Online Status: Offline
Posts: 2288
Direct Link To This Post Posted: 2012 Jul 26 at 11:23am
Thanks Giblet.
That might come in handy later on. But right now I can't even manage to make simple UV point move where I want it to go.
I can give them new positions. And those new positions show up as being changed in the console.
But they won't budge on the UV canvas. And I don't know why.

-ScottA




Back to Top
Giblet View Drop Down
Member
Member


Joined: 2003 May 21
Online Status: Offline
Posts: 465
Direct Link To This Post Posted: 2012 Jul 26 at 11:25am
Just do...


    pPolyObj->Message(MSG_UPDATE);
    EventAdd();


...after changing anything on pPolyObj (including any UVWTag modifications).  EDIT: that is... after doing all your changes (you only need to do it once, before returning from your plugin code).


Edited by Giblet - 2012 Jul 26 at 11:29am
Back to Top
ScottA View Drop Down
Member
Member


Joined: 2011 Jan 07
Online Status: Offline
Posts: 2288
Direct Link To This Post Posted: 2012 Jul 26 at 11:35am
Yeah. I tried that (see the code example I posted earlier).
It's not working.

-ScottA
Back to Top
Matthias Bober View Drop Down
Forum Moderator
Forum Moderator


Joined: 2006 Oct 16
Location: Germany
Online Status: Offline
Posts: 2204
Direct Link To This Post Posted: 2012 Jul 26 at 11:57am
Scott, from where do you call your UV code, e.g. what kind of plugin (tag, command etc.)?

cheers,
Matthias

MAXON
developer support
Back to Top
ScottA View Drop Down
Member
Member


Joined: 2011 Jan 07
Online Status: Offline
Posts: 2288
Direct Link To This Post Posted: 2012 Jul 26 at 12:09pm
I'm doing it from a GeDialog plugin. Inside of the Command() method.

We are allowed to edit the existing UV's in existing uvwtags right?
I see lots of MakeTag type UV code in the forums. But not much that deals with editing existing uvwtags.

-ScottA
Back to Top
Giblet View Drop Down
Member
Member


Joined: 2003 May 21
Online Status: Offline
Posts: 465
Direct Link To This Post Posted: 2012 Jul 26 at 1:01pm
The problem is that you are NOT modifying the uvw struct before you Set() it back - you are only modifying (and printing) a local variable. :)

EDIT: In other words...


        ax = 0.5;                         //Move the vertex res.a.x to 0.5 on the canvas
        uvwtag->Set(dataptr,i,res);       //Update the changes to the UVpolygon in the UVW tag <--------Not working!!


Your comments above are incorrect... modifying the local 'ax' variable is not the same as modifying res.a.x
To fix it, you'd need to...


        res.a.x = 0.5;                    //Move the vertex res.a.x to 0.5 on the canvas
        uvwtag->Set(dataptr,i,res);       //Update the changes to the UVpolygon in the UVW tag <--------It works!!


Cheers.


Edited by Giblet - 2012 Jul 26 at 1:15pm
Back to Top
Page  12>

Forum Jump Forum Permissions View Drop Down

Bulletin Board Software by Web Wiz Forums® version 9.61 [Free Express Edition]
Copyright ©2001-2009 Web Wiz

This page was generated in 0.328 seconds.