Jump to content
Sign in to follow this  
8DashP

Stuck trying to render correctly - any suggestions?

Recommended Posts

Hey All,

My old plugin code was drawing properly, my new code isn't. The code has been refactored, but the calculations look the same to me, so I'm not sure what's happening. Did the file format change between the old monster sample, and the new GreyGuy sample, that might have changed the render algorithms? I don;t think pivot points were anything but centered in the original example, which may be an issue, but I can't see where.

Only things I can think of are that my texturepacker atlas has changed layout somehow, or I've just got either a flipping or offset issue. In particular, the Torso and Head seem way out of place, the other parts not so much, but that may be just a scaling thing as the other parts are smaller. Anyway, here's what my current output looks like. I'm hoping maybe someone can look at it and suggest what the issue might be?

BYXoa6t.png

Thanks.

Russell.

*EDIT*

Almost got it. I had to add a second transformation to the offset before painting. Now it's almost correct, there just seems to be some slight offset issues. Looks like everything on the X-axis might be compressed, or offset wrong?

6CYkW3h.png

Share this post


Link to post
Share on other sites

Hmm, this is driving me crazy now. Most of the placements work. It just seems where there is a sub-branch bone coming off the main hierarchy, the top node in that branch is not being placed correctly, but the objects below it are, relatively.

The math is the same on all nodes, so what's unique about where the arms & legs join the pelvis/chest? The parent info on these nodes is common I think, in that their parents info is being derived from the base, instead of other nodes. Ive just set my base character info as x,y,z = 0 and scale x,y = 1, and the pelvis/torso/head hierarchy is rendering correctly. It seems after al the transforms, the X coordinate is not far off the Y axis. Not sure where else to look?

Share this post


Link to post
Share on other sites

Could you please post some pseudo code or the actual code.

I would like to see how the rendering works and how you transform an object relative to the parent?

I have also a problem:







what does such a character map mean? Where are the target folders and files?

- Trixt0r

Share this post


Link to post
Share on other sites

I'll see if there's anything unusual I do in the code, and try and put that up in the morning. I've given up for the night, and am just heading to bed here now. But I've pretty much just used the straight pseudo-code from the documentation here http://www.brashmonkey.com/ScmlDocs/ScmlReference.html with just some local tweaks for my custom environment requirements.

The unmapFromParent function does the grunt work maths of transforming the object location info from the parent bone info, at least from what I can see, so you'd think my problem comes from there, but as I said, it's the same code as the pseudo code. My main difference is manipulating the pivot points before the draw, as Shiva only has a centred pivot point.

You'll also see in that doc, that a character map also has two other fields - target folder and target file. So using the map is just a matter of replacing the original references with the target references to the new images. I haven't usually implemented myself yet, got to get the basics done, but in theory it should be easy. There is another thread here viewtopic.php?f=3&t=15496 where Mike explains the process.

I think the fact it's missing the targets simply means they should be defaulted, i.e. The map is just the standard images.

Russell.

Share this post


Link to post
Share on other sites
My main difference is manipulating the pivot points before the draw, as Shiva only has a centred pivot point.

I see. It looks like you are drawing some parts without taking into account that the origin of the sprites are centered by your engine. Then you should try to recalculate the final sprite position by moving it half of the width to the left and half of the height to the bottom (or the other way around).

Somehting like:


calculate position x, y with pivot points...
move x by -sprite_width/2
move y by -sprite_height/2
render sprite at x,y

Maybe the y value is a different, since I do not know how your engine draws pixels on the y-axis.

I think the fact it's missing the targets simply means they should be defaulted, i.e. The map is just the standard images.

Then a character map with no targets makes no sense to me. Why should Spriter save such a useless character map?

-Trixt0r

Share this post


Link to post
Share on other sites
I see. It looks like you are drawing some parts without taking into account that the origin of the sprites are centered by your engine. Then you should try to recalculate the final sprite position by moving it half of the width to the left and half of the height to the bottom (or the other way around).

Somehting like:


calculate position x, y with pivot points...
move x by -sprite_width/2
move y by -sprite_height/2
render sprite at x,y

Maybe the y value is a different, since I do not know how your engine draws pixels on the y-axis.

Yes, I already had that in, even in my original image. What got me to the second image was that I then had to apply a transform to the pivot, the same as the pseudo-code transformation, to get it into the same space as the image coordinates, but still something is amiss with those few joint connections. Here's my pivot transformation C++ code, where k is the current objectkey you are processing to paint, and the values used are those after the pseudocode transforms to the scml data.


float pivotX = k.spriteKey.pivot_x;
float pivotY = k.spriteKey.pivot_y;

if (k.spriteKey.useDefaultPivot)
{
// get default pivot data from folder/file data
pivotX = data_objects[0].folders[k.spriteKey.folder].files[k.spriteKey.file].pivotX;
pivotY = data_objects[0].folders[k.spriteKey.folder].files[k.spriteKey.file].pivotY;
}

float offsetX = (pivotX - 0.5f) * img_dims.first; // image x dimension
float offsetY = (pivotY - 0.5f) * img_dims.second; // image y dimension
float sprite_x = -offsetX*k.info.scaleX;
float sprite_y = -offsetY*k.info.scaleY;

bool flipped = ((k.info.scaleX < 0) != (k.info.scaleY < 0));

float angle = k.info.angle;

if (flipped)
angle = -angle;

float s = (float)sin (angle * SCM::DEG_TO_RAD);
float c = (float)cos (angle * SCM::DEG_TO_RAD);
float xnew = (sprite_x * c) - (sprite_y * s);
float ynew = (sprite_x * s) + (sprite_y * c);
xnew += k.info.x;
ynew += k.info.y;

sprite_x = xnew;
sprite_y = ynew;

Then a character map with no targets makes no sense to me. Why should Spriter save such a useless character map?

Well I could be wrong on the original intent, so don't take my word as the true intent. My guess would be because it means you can use common code, and just process the current character map regardless of whether it is the original image, or a new map, instead of having one code path when no map is applied vs another path when a map is applied.

Russell.

Share this post


Link to post
Share on other sites

Is k.info.angle the parent angle? The angle of the current object has to be affected by the inherited angle with currentObject->angle += parentObject->angle (same for the scaling with multiplication). I think you are rotating the wrong x and y values. You do not have to rotate pivot points. Those are just added to the final position.

And I would do the unmapping before calculating the pivot part. Something like this:


float x = //initialize this with the value from the scml file saved in the timeline key...
float y = //initialize this with the value from the scml file saved in the timeline key...
bool flipped = ((k.info.scaleX < 0) != (k.info.scaleY < 0));

float angle = k.info.angle; //I hope this is the angle of the parent bone...

if (flipped)
angle = -angle;

float s = (float)sin (angle * SCM::DEG_TO_RAD);
float c = (float)cos (angle * SCM::DEG_TO_RAD);
float xnew = (x * c) - (y * s);
float ynew = (x * s) + (y * c);
xnew += k.info.x;
ynew += k.info.y;

float sprite_x = xnew;
float sprite_y = ynew;

float pivotX = k.spriteKey.pivot_x;
float pivotY = k.spriteKey.pivot_y;

if (k.spriteKey.useDefaultPivot)
{
// get default pivot data from folder/file data
pivotX = data_objects[0].folders[k.spriteKey.folder].files[k.spriteKey.file].pivotX;
pivotY = data_objects[0].folders[k.spriteKey.folder].files[k.spriteKey.file].pivotY;
}
float offsetX = (pivotX - 0.5f) * img_dims.first; // image x dimension
float offsetY = (pivotY - 0.5f) * img_dims.second; // image y dimension
sprite_x -= offsetX*k.info.scaleX;
sprite_y -= offsetY*k.info.scaleY;

Mathematically these are two different things. What you are doing is a translation and then a rotation which is not equal to a rotation followed by a translation, i.e. T*R != R*T.

This is what I am doing in my API.

I hope this helps somehow.

-Trixt0r

Share this post


Link to post
Share on other sites
Is k.info.angle the parent angle? The angle of the current object has to be affected by the inherited angle with currentObject->angle += parentObject->angle (same for the scaling with multiplication). I think you are rotating the wrong x and y values. You do not have to rotate pivot points. Those are just added to the final position.

And I would do the unmapping before calculating the pivot part.

First off, I appreciate you taking the time to look. Thanks very much.

k.info.angle is the unmapped angle already. Here's my code that processes the keys prior to trying to adjust the pivot, which si really just a c++ version of the reference pseudocode

		std::vector objectKeys;
for (const auto &o : mainKey.objectRefs)
{
SCM::SpatialInfo parentInfo;
if (o.parent >= 0)
{
parentInfo = boneKeys[o.parent].info;
}
else
{
parentInfo = sprites[parentSprite].characterInfo;
}

SCM::TimelineKey currentKey = keyFromRef (o , newTime);
currentKey.info = currentKey.info.unmapFromParent (parentInfo);
objectKeys.push_back (currentKey);
}

After that is when my other code gets run.

Unfortunately, just substituting your code in place of my previous code makes a big mess of the placement. But my X, Y values at that time are already unmapped, so maybe that wasn't what you intended. Maybe I need to move the pivot adjustment into the unmap function?

I had an original implementation working with the generic C++ code provided here on the forum. But I found it rather difficult to read, and overly complicated for my use. That's why I'm trying to refactor based on the reference documentation. So the reason I was doing my pivot rotation like I currently have was because that's close to how the code in the C++ implementation worked, but obviously I've messed something up in translation :(

I also read another article only talking about 2D rotation with an offset pivot, and it mentioned about subtracting the picot first, then transforming, then adding back on, but I'm not sure if that's right, and my attempts so far have not resolved anything. Odd part is, when doing that, all of my locations are displaced EXCEPT the ones that are currently in the wrong position (shoulders & hips joints), they seem to stay fixed in the one place, like they're being scaled to almost 0 or something? It almost seems like a data error int eh SCMl file, but given no one else has this issue, it must be something I'm doing.

I'll try moving my pivot code into the unmap, instead of being post-unmap, and see if that matters.

*EDIT*

Eh, well after trying several variations, they either all make it worse, or best I can get is my original first image posted above. And once again, even in all the bad results, the should & hip joints seem to stay exactly where they are, while everything else moves all over the place. Must be number issues somewhere, not formula. Maybe something is going to 0? Precision problem? The end co-ordinates for those sprite locations aren't 0 thought, just small numbers. Back to the drawing board.

Thanks. Russell.;

Share this post


Link to post
Share on other sites

Right well, I'm embarrassed to say that I've found the solution to my problem. I was on the right track about the issue, just looking in the wrong place. Seems when I imported the pivot_y from the scml data, I'd cut & pasted the pivot_x import line, and forgot to change the check from "pivot_x" to "pivot_y" :oops:

I did have to go back to my original code of also rotating the offset separately, after transforming the sprite position. I've tried several pays to incorporate it at the same time as the sprite transform, without success. I'll review the math a bit more, as while I have the correct result currently, it's a double calculation, which I'd like to remove.

I'm happy to say though, at least I have a working version now, and once again, thanks Trixt0r for at least holding my hand while I worked through the issues, as it encouraged me to keep trying, instead of just giving up.

Russell.

Share this post


Link to post
Share on other sites
I think the fact it's missing the targets simply means they should be defaulted, i.e. The map is just the standard images.

Then a character map with no targets makes no sense to me. Why should Spriter save such a useless character map?

According to this post, an image with no target means "hide it" (i.e. "replace it with nothing"). When you want the default image, just leave that image out of the map entirely.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...