• Runtimes
  • How to obtain the bounding box and rendering attachments.

  • 수정됨

Hello, I'm trying to render some spine animations using the runtime of sfml 3.8. I hope to obtain the bounding box with image attachments and render all attachments correctly. The following is my try:

SkeletonDrawable* drawable = new SkeletonDrawable(skeletonData);
drawable->timeScale = 1.0f;
drawable->setUsePremultipliedAlpha(true);

// 初始化骨骼
Skeleton* skeleton = drawable->skeleton;
int size = 768;

AnimationState_setAnimationByName(drawable->state, 0, "Default", false);

drawable->state->tracks[0]->trackTime = 0;
Skeleton_setToSetupPose(skeleton);
AnimationState_apply(drawable->state, skeleton);
Skeleton_updateWorldTransform(skeleton);

SkeletonBounds* bounds = SkeletonBounds_create();
SkeletonBounds_update(bounds, skeleton, 1);

float minX = std::numeric_limits<float>::max();
float minY = std::numeric_limits<float>::max();
float maxX = std::numeric_limits<float>::lowest();
float maxY = std::numeric_limits<float>::lowest();
bool hasAttachment = false;

for (int i = 0; i < skeleton->slotsCount; ++i) {
    spSlot* slot = skeleton->drawOrder[i];
    spAttachment* attachment = slot->attachment;
    if (!attachment) continue;

    if (attachment->type == SP_ATTACHMENT_MESH) {
        spMeshAttachment* mesh = (spMeshAttachment*)attachment;
        if (!mesh->rendererObject) continue;

        hasAttachment = true;
        int vertexCount = mesh->super.worldVerticesLength;
        std::vector<float> worldVertices(vertexCount);
        spVertexAttachment_computeWorldVertices(
            (spVertexAttachment*)mesh, slot, 0, vertexCount, worldVertices.data(), 0, 2
        );
        for (int v = 0; v < vertexCount; v += 2) {
            float x = worldVertices[v];
            float y = worldVertices[v + 1];
            if (x < minX) minX = x;
            if (y < minY) minY = y;
            if (x > maxX) maxX = x;
            if (y > maxY) maxY = y;
        }
    }
}

if (!hasAttachment) {
    printf("No RegionAttachment found!\n");
    return 2;
}
// minX = std::max(minX, -512.0f);
// minY = std::max(minY, -512.0f);
// maxX = std::min(maxX, 512.0f);
// maxY = std::min(maxY, 512.0f);

printf("RegionAttachment Bounding Box: Min(%.2f, %.2f), Max(%.2f, %.2f)\n", minX, minY, maxX, maxY);

float bboxWidth = maxX - minX;
float bboxHeight = maxY - minY;

skeleton->x = size / 2.0f - (minX + bboxWidth / 2.0f);
skeleton->y = size / 2.0f - (minY + bboxHeight / 2.0f);

Skeleton_updateWorldTransform(skeleton);

sf::RenderTexture renderTexture;
renderTexture.create(size, size);
renderTexture.clear(sf::Color::Transparent);
renderTexture.draw(*drawable);
renderTexture.display();

if (!renderTexture.getTexture().copyToImage().saveToFile(path)) {
    printf("Failed to save image\n");
    return 3;
}
else {
    printf("Successfully exported to: %s\n", path);
}


It can be seen that I hoped the image area would actually be centered, but some Meshes failed to do so.


It can be seen here that attachments that work properly through the official skeletonViewer do not work properly in my code.

What should I do?

  • Nate님이 이에 답장했습니다.
    Related Discussions
    ...

    To obtain the bounding box and render attachments correctly using the Spine runtime with SFML, you need to ensure that you are correctly handling the world vertices for each attachment type. In your code, you are already computing the world vertices for MeshAttachment types, but you should also handle RegionAttachment types similarly. For RegionAttachment, you can use spRegionAttachment_computeWorldVertices to get the world vertices.

    Additionally, ensure that you are updating the world transform of the skeleton after setting the position to center the skeleton correctly. This involves calling Skeleton_updateWorldTransform after setting the skeleton's x and y properties.

    Here's a brief outline of what you should do:

    1. Check for both RegionAttachment and MeshAttachment types in your loop.
    2. Use the appropriate function to compute world vertices for each attachment type.
    3. Update the skeleton's world transform after setting its position.

    By following these steps, you should be able to correctly calculate the bounding box and render the attachments as expected.

    • ETO님이 이에 답장했습니다.

      Spinebot In fact, making modifications according to what you said won't lead to a better performance. On the contrary, I only calculated SP_ATTACHMENT_MESH at the beginning for my consideration, because this could enable the vast majority of my files to be processed correctly. If SP_ATTACHMENT_REGION is considered, the effect would be even worse.

      skeleton->x = size / 2.0f - (minX + bboxWidth / 2.0f);
      skeleton->y = size / 2.0f - (minY + bboxHeight / 2.0f);
      Skeleton_updateWorldTransform(skeleton);

      This point has been considered in my initial code.

      Spinebot Update the skeleton's world transform after setting its position.

      And no suggestions were received regarding the issue of missing attachments.

      In conclusion, there is no sign at all that the entire problem will be solved.

      ETO I hope to obtain the bounding box with image attachments and render all attachments correctly.

      This terminology is a bit odd, maybe by "image attachments" you mean both region and mesh attachments?

      ETO SkeletonBounds* bounds = SkeletonBounds_create();

      SkeletonBounds does this:

      Collects each visible BoundingBoxAttachment and computes the world vertices for its polygon. The polygon vertices are provided along with convenience methods for doing hit detection.

      It only uses bounding box attachments, not region, mesh, or other types of attachments. If you want to compute the AABB for all attachments, you don't need SkeletonBounds.

      Otherwise your approach is good: compute the world vertices for each attachment and compute the maximal bounds. Note that is almost identical to rendering, so you can copy/paste the SFML rendering code for the spine-sfml runtime, remove the rendering, and put in computing the maximal bounds.

      if (!mesh->rendererObject) continue;

      Since you aren't rendering, you aren't using the rendererObject and you don't need this line.

      printf("No RegionAttachment found!\n");

      Your code checks for mesh attachments, not region attachments, so this message is confusing. You can add this code:

      if (attachment->type == SP_ATTACHMENT_REGION) {
          spRegionAttachment* region = (spRegionAttachment*)attachment;
          hasAttachment = true;
          
          float vertices[8];
          spRegionAttachment_computeWorldVertices(region, slot->bone, vertices, 0, 2);
          
          for (int v = 0; v < 8; v += 2) {
              float x = vertices[v];
              float y = vertices[v + 1];
              if (x < minX) minX = x;
              if (y < minY) minY = y;
              if (x > maxX) maxX = x;
              if (y > maxY) maxY = y;
          }
      }

      However, it may be better to copy/paste from the spine-sfml renderer.

      drawable->state->tracks[0]->trackTime = 0;

      This is right to choose a frame to pose, but if you have physics your skeleton will see the setup pose, then suddenly the animation pose, causing physics to jump. If you care about physics, you need to pose your skeleton repeatedly from 0 to a particular trackTime using a time step like 16ms.

      if (!attachment) continue;

      This is OK, but you may want to check if the attachment is invisible:

      if (!attachment || slot->color.a == 0) continue;

      It can be seen that I hoped the image area would actually be centered, but some Meshes failed to do so.

      Sorry, I don't understand what you mean here.

      It can be seen here that attachments that work properly through the official skeletonViewer do not work properly in my code.

      I see the difference, but it's not clear why. Are you able to render it correctly in a similar way but to the screen? Is it only regions or only meshes that don't render?

      • ETO님이 이에 답장했습니다.

        Nate Sorry for the confusion. I'm not familiar with these proper terms. Now I will describe in detail what I tried and encountered.




        These four pictures should be able to correspond to the problems corresponding to the bounding box. In most cases, SP_ATTACHMENT_MESH can always obtain relatively accurate four extremities, while SP_ATTACHMENT_REGION does not show reference value in practice.

        Nate "image attachments"

        It means that I hope to calculate the not completely transparent parts as bounding boxes, but actually I have no clue because neither SP_ATTACHMENT_MESH nor SP_ATTACHMENT_REGION is difficult to statistically analyze.
        Because as shown in the figure, even the box containing the content of the picture is not necessarily attached to the image.
        If the runtime of spine cannot achieve this, I might consider first obtaining the maximum boundaries obtained from SP_ATTACHMENT_REGION and SP_ATTACHMENT_MESH to obtain the PNG, and then processing the PNG in other ways to make it finally centered.

        Also, regarding the animation, you can see that the animation I hope to use is "Default". It is worth noting that this animation actually has only one frame and is theoretically an animation for preview. So my setting like this is of no use.

        Nate using a time step like 16ms

        drawable->state->tracks[0]->trackTime = 16;

        As mentioned earlier, SP_ATTACHMENT_MESH is more meaningful for my border statistics. In fact, it is only reflected in SP_ATTACHMENT_MESH.
        It's only partially missing, so that I can't accurately identify the cause.It has only one frame, so I feel at a loss here.

        Nate causing physics

        The invisible check is most likely ineffective. It's just a final struggle.

        I had a problem importing the file into spine (it was probably my own problem), so I only configured skeletonViewer and runtime.

        I hope this is enough information and thank you for your help.

        • NateETO님이 이에 답장했습니다.

          ETO These four pictures should be able to correspond to the problems corresponding to the bounding box.

          OK but... what am I looking at? What are the red boxes? What are the problems?

          In most cases, SP_ATTACHMENT_MESH can always obtain relatively accurate four extremities, while SP_ATTACHMENT_REGION does not show reference value in practice.

          Maybe the skeleton has no region attachments? The 4 vertices for a region attachment will work for computing the AABB just like the vertices of a mesh.

          It means that I hope to calculate the not completely transparent parts as bounding boxes

          The vertices will give you an AABB based on the images drawn. It doesn't account for the parts of the images that are blank. Is that the problem you are having? That the AABB from vertices still has blank space? The only way to know that would be to look at the pixel values. For example, render to a buffer as you have done, then look at pixel values. This is often called "whitespace stripping".

          drawable->state->tracks[0]->trackTime = 16;

          Note this is in seconds. 16ms is 0.016.

          As mentioned earlier, SP_ATTACHMENT_MESH is more meaningful for my border statistics.

          Both regions and meshes are important. A skeleton could be entirely regions.

          It's only partially missing, so that I can't accurately identify the cause.It has only one frame, so I feel at a loss here.

          Sorry, your posts don't really explain your problems. I am not familiar with your skeletons. I don't know what the red boxes are trying to tell me. I don't know what your end goal is. I don't know what problems you are having trying to get there. Please concisely but thoroughly explain these key concepts:
          1) what you want to do and why,
          2) what you tried,
          3) what you expected, and
          4) what happened instead.

          • ETO님이 이에 답장했습니다.

            Nate The area in the red box is the four-point range I obtained, which is determined by the SP_ATTACHMENT_REGION or SP_ATTACHMENT_MESH in the upper left corner.

            Nate Maybe the skeleton has no region attachments?

            In my opinion, this understanding is correct. This is indeed the reason for the fourth picture. I think I should count both SP_ATTACHMENT_REGION and SP_ATTACHMENT_MESH simultaneously. Theoretically, this is correct, but the final effect is not as good as only counting SP_ATTACHMENT_MESH (most models are similar to the comparison of Figure 1 and Figure 2, and Figure 3 and Figure 4).

            Nate Both regions and meshes are important. A skeleton could be entirely regions.

            I quite agree with this. It's just that using only SP_ATTACHMENT_MESH currently performs better. Of course, if the problem is eventually solved, it must be SP_ATTACHMENT_REGION and SP_ATTACHMENT_MESH.

            Nate Is that the problem you are having?

            This is almost the problem I have encountered. This is the difference in location when I use the runtime and skeletonViewer.

            Nate "whitespace stripping".

            I will consider using this method, but because of this problem here (the fifth picture).

            ETO Because as shown in the figure, even the box containing the content of the picture is not necessarily attached to the image.

            I think even if it is achieved, it is not necessarily possible to be "strictly centered".

            ETO If the runtime of spine cannot achieve this, I might consider first obtaining the maximum boundaries obtained from SP_ATTACHMENT_REGION and SP_ATTACHMENT_MESH to obtain the PNG, and then processing the PNG in other ways to make it finally centered.

            So I will try this method first, because in any case, it should be necessary for the above situation.

            Nate Note this is in seconds. 16ms is .

            This is my mistake. Thank you for your correction. But does 16ms correspond to 60 frames? You suggested I take one frame, but in fact, my animation only has the zeroth frame. There might be no difference between going through one frame and going through 16*60. I once tried to calculate the duration of the animation to reach the last frame, but there was no improvement either.

            Nate what you want to do and why,

            I hope to preview the image in the center.
            I hope to render the image correctly.

            Nate what you tried,
            Nate what happened instead.

            I attempted to obtain bounding boxes using SP_ATTACHMENT_REGION and SP_ATTACHMENT_MESH, but the effect was not good.
            The rendering code above me caused some images to be missing.

            This is the problem I encountered. I'm sorry again for my ambiguous expression. ≦(._.)≧

            But does 16ms correspond to 60 frames?

            By default Spine uses 30 FPS in the editor. At runtime it is always in seconds. One frame is 1 / 30 = 0.033 seconds (33ms).

            You suggested I take one frame, but in fact, my animation only has the zeroth frame.

            Then trackTime = 0 is fine. You may want to calculate the maximal bounds for a specific frame later in the animation, or for an entire animation. spine-player does an entire animation:
            EsotericSoftware/spine-runtimesblob/4.2/spine-ts/spine-player/src/Player.ts#L793-L819
            There's no Skeleton getBounds in spine-sfml/spine-c, but you're doing the similar. You can see it in TypeScript:
            EsotericSoftware/spine-runtimesblob/4.2/spine-ts/spine-core/src/Skeleton.ts#L628
            This does more than your code, eg properly applying clipping.

            I hope to preview the image in the center.

            There's technically many solutions to this. Using bounds from the vertices centers it based on what is drawn, but visually blank parts of the region and mesh attachments may make it look off center. The only way to fix that is draw, then inspect the pixels.

            I hope to render the image correctly.
            The rendering code above me caused some images to be missing.

            If you can draw to the screen correctly, it should draw to your texture correctly. Get rendering to the screen working first.

            I attempted to obtain bounding boxes using SP_ATTACHMENT_REGION and SP_ATTACHMENT_MESH, but the effect was not good.

            Done correctly, it should give you the AABB of what is drawn. That you are drawing images with lots of blank space is a separate problem.

            If you don't want to use what is drawn for centering, then what is "centered" can be subjective. For example, if a character has a long spear, it may extend far to one side. Even after you remove whitespace, the character will be off to one side. Maybe that is good enough.

            You might consider a marker in each skeleton to define the center of the character. Or you could use 0 worldX.

            What is this being done for? If you are going to pack the images into an atlas, you don't need to worry about whitespace at all, you can let texture packing do it. If you just want to get it done and aren't doing it at runtime, you could pack the images and the atlas data can tell you how many whitespace pixels were cut off.

            • ETO님이 이에 답장했습니다.
              • 수정됨

              Nate My job is very clear. I take a screenshot of the "Default" animation of the existing animation file to make the image strictly centered (having considered "long spear" and such, only centering is required). In fact, I shouldn't or can't make any modifications to the animation file. This is beyond my authority.

              Nate There's no Skeleton in spine-sfml/spine-c

              I hope to pack a very, very small tool to handle this job, so I hope to carry as few operating environments as possible. spine-sfml/spine-c can't do it,so, what > 3.8/spine-c/spine-c/src/spine/Skeleton.c. Then I will try: spine-sfml/spine-cpp

              Nate The only way to fix that is draw, then inspect the pixels.

              So this job is necessary, but I still hope to know more about to what extent spine-runtime can achieve.

              Nate That you are drawing images with lots of blank space is a separate problem.

              So I raised two questions. The first one already has a basic direction for solution, which is the one discussed above.

              The second problem is the most important one at present. I have chosen a more extreme example again.

              I don't know what happened. The code above me couldn't draw many things, nor could I tell the connection between these missing objects. I don't know how to obtain more information about this problem.

              Nate I examined the specific implementation of Skeleton and realized that there was no essential difference from my traversal of SP_ATTACHMENT_REGION and SP_ATTACHMENT_MESH. Therefore, I realized that this work might have gone beyond the scope of spine-runtime. So I adopted the simple Andrew's Monotone Chain algorithm to fulfill my requirements, and it did. (Perhaps I should have done this long ago. ( 。ớ ₃ờ)ھ)

              So the first problem has been solved at a certain stage, while there is no idea about the second one.

              The monotone chain algorithm (aka Andrew's algorithm) is for computing a convex hull. You can reference an efficient, non-allocating version of it that I wrote here. How do you use this algorithm? Do you apply it to the pixels in each mesh? This seems quite complicated. The easiest approach is to render to an in-memory buffer then read the pixels from each edge. Reduce the size of the image for each row or column that is fully transparent. When you encounter a pixel that is not fully transparent, stop. Code for that for texture packing can be seen here. Of course you will need to adapt to your game toolkit API. Since this involves rendering, you are dependent on the game toolkit API. It's not functionality the Spine Runtimes provide, so changing runtimes won't help much. Changing game toolkits may help. Doing it with libgdx would be easy, but you may not want your tool to require or package Java.

              For your rendering problem, as I mentioned before: get it working by rendering to the screen first. Once that works, then render to a texture. The rendering code path should be the same, but it's easier to work on getting the screen rendering correct. It's not possible to give more help from only screenshots of incorrect rendering. I can only guess at what is wrong, but it seems as if some batched geometry was not flushed at the end of your rendering.

              • ETO님이 이에 답장했습니다.

                Nate Andrew's Monotone Chain. Here I have used the following more common writing method. I analyzed your writing method and used the quick sort algorithm, while I used std::sort, which combines quick sort and heap sort. The time complexity of both is the same O(n log n). Compared with your maintenance of the index, I don't have the corresponding requirements, so my constant factor is smaller. Therefore, I think it is efficient enough.
                //(Andrew's Monotone Chain)
                static int cross(const sf::Vector2i& O, const sf::Vector2i& A, const sf::Vector2i& B) {
                return (A.x - O.x) * (B.y - O.y) - (A.y - O.y) * (B.x - O.x);
                }
                static std::vector<sf::Vector2i> convexHull(std::vector<sf::Vector2i> P) {
                int n = P.size(), k = 0;
                if (n <= 1) return P;
                std::sort(P.begin(), P.end(), [](auto& a, auto& b) {
                return a.x < b.x || (a.x == b.x && a.y < b.y);
                });
                std::vector<sf::Vector2i> H(2 * n);
                for (int i = 0; i < n; ++i) {
                while (k >= 2 && cross(H[k - 2], H[k - 1], P[i]) <= 0) k--;
                H[k++] = P[i];
                }
                for (int i = n - 2, t = k + 1; i >= 0; --i) {
                while (k >= t && cross(H[k - 2], H[k - 1], P[i]) <= 0) k--;
                H[k++] = P[i];
                }
                H.resize(k - 1);
                return H;
                }

                Regarding the acquisition of the point set, as you said, I don't have a very good method. I traversed all the pixels. This is indeed a bottleneck. But as you said, I don't want to introduce more things, and the time consumption is actually within the acceptable range. Overall, this has met my needs. Thank you for your suggestion.

                Regarding the rendering issue, I have made more attempts below and should be able to provide more details.

                This is the complete process I attempted. Meanwhile, I tried to output the duration of the animation, and unsurprisingly, the result was 0.000000.

                Next, I will talk about the differences under different conditions.

                The difference between the upper left corner and the lower left corner lies in whether this is enabled or not. I found that if the attachment is not explicitly set, even if I do not set an exit condition when counting the bounding box, the unrendered attachments will not be recorded.

                for (int i = 0; i < skeleton->slotsCount; ++i) {
                spSlot* slot = skeleton->drawOrder[i];
                if (!slot->attachment && slot->data->attachmentName) {
                spAttachment* att = Skeleton_getAttachmentForSlotName(skeleton, slot->data->name, slot->data->attachmentName);
                if (att) slot->attachment = att;

                From the difference between the upper left and the right, I learned that not all attachments need to be forcibly opened. There might be a judgment condition here, and I don't know how to handle it.

                Then let's look at another example. The layout is consistent with the previous one, but we can see that after enabling all attachments, there is no difference. At the same time, just like above, it is not included in the statistics of the bounding box.

                As you said, I have rendered it on the screen. In fact, there is no difference between it and when I output it to PNG (always as an example in the upper left corner).


                Is there any extra processing in the skeletonViewer rendering process, the latter example still has no idea for me.

                Nate I can only guess at what is wrong, but it seems as if some batched geometry was not flushed at the end of your rendering.

                For this issue, I only performed such rendering once throughout the full text and there was no cross-thread operation. I don't think it matters much here. According to the previous examples, the location where the error occurred should be at or before the earlier traversal.

                Nate

                I ran through all my model libraries and found that there was still model return 4 but no return 3. This indicates that the model calculated the bounding box, but all of them were set to transparent. Then I made an attempt based on this.

                However, what emerged were the elements that should have been properly hidden, while the elements that should have been drawn still did not appear. This might provide some clues.

                Your convexHull function looks good!

                I traversed all the pixels.

                I still contend the fastest and simplest solution is:

                1. Compute the AABB using mesh and region vertices.
                2. Create a buffer using that AABB size and render the skeleton to it.
                3. Discard fully transparent rows/columns at the 4 edges. You now have the tightly fitting AABB.

                If you know the maximum size of your skeletons, you can skip step 1 and in step 2 just create a large buffer, eg 4096 x 4096.

                You can see an example here. That code poses a skeleton with an animation on frame 0 (using the timeline API, effectively the same as your use of AnimationState), then renders it to a buffer -- very similar to what you want (but in Java with libgdx). Next you'd read the pixels to discard fully transparent rows/columns at the edges (like I showed in the texture packer in my earlier post). Game toolkits like libgdx are so much nicer than those that force you to use a scene graph. 🙁

                Your code that iterates slots should be based on the spine-sfml rendering code, here:
                EsotericSoftware/spine-runtimesblob/4db43da67888eb71ed706046cb13735d96286048/spine-sfml/c/src/spine/spine-sfml.cpp#L159-L317

                Copy paste that, then remove the parts that do rendering. In the for (int j = 0; j < indicesCount; ++j) { loop use the vertices to find the AABB. The reason to do this is because you must do exactly what the spine-sfml rendering code does, except you calculate AABB instead of rendering. If you do something else, then your AABB may not match rendering. For example, it appears your code doesn't apply clipping correctly.

                That code does not use Skeleton_getAttachmentForSlotName and you should not need it. By default the skeleton has the setup pose attachments visible. You don't need to set attachment visibility. The spine-sfml renderer does not. The FboTest linked above does not. You should not change the slot color either.

                I tried to output the duration of the animation, and unsurprisingly, the result was 0.000000.

                0 is correct if the animation has only keys on frame 0.

                As you said, I have rendered it on the screen. In fact, there is no difference between it and when I output it to PNG

                OK, good -- it will be easier to debug when rendering to the screen. Are you rendering directly to the screen though? The code you've show seems to be rendering to the texture. Don't render to your texture and then render the texture to the screen. Render directly to the screen to ensure your rendering code is correct, only then make it more complex by rendering to a texture.

                Render directly to the screen, like the example:

                sf::RenderWindow window(...);
                SkeletonDrawable *drawable = ...;
                ...
                window.clear();
                window.draw(*drawable);
                window.display();

                Is there any extra processing in the skeletonViewer rendering process

                No extra processing should be needed. The SkeletonViewer code is available. The FboTest above is simpler. You just load the skeleton and render it.

                I ran through all my model libraries and found that there was still model return 4 but no return 3. This indicates that the model calculated the bounding box, but all of them were set to transparent.

                This could be correct. A skeleton could have all attachments hidden in the setup pose, eg maybe they are only shown in animations. Or, when a skeleton uses skins it is common to not have any attachments at all in the default skin. When shown in Skeleton Viewer, you won't see anything until you choose a skin.

                At this point you should probably start with the spine-sfml example code. Run it and see spineboy renders. Change the skeleton to one of yours, see it renders correctly. Modify the example to render to a texture, then render the texture to the screen to see rendering was correct. If you need an AABB to render to a texture, base it on the spine-sfml rendering code. Finally, convert the texture to an image and remove fully transparent rows/columns from the 4 edges.

                Give that a try (don't skip any steps!) and if you still have trouble, post or email your full code. contact@esotericsoftware.com

                • ETO님이 이에 답장했습니다.

                  Nate

                  Nate start with the spine-sfml example code. Run it and see spineboy renders. Change the skeleton to one of yours, see it renders correctly.

                  I did do so (Based on this), but the result I got was that spineboy was completely normal, while this part of my model did not display properly.

                  Nate Render directly to the screen, like the example:

                  The window in the upper left corner above me is done this way. I explained it later, but it might not be conspicuous enough.

                  Nate Or, when a skeleton uses skins it is common to not have any attachments at all in the default skin.

                  I have considered this aspect, but the fact is that my model only has the default skin.

                  Nate Discard fully transparent rows/columns at the 4 edges

                  This is indeed a good method. Through some algorithmic techniques, a fitting bounding box can be found efficiently. But in my practice, just like the spear you mentioned above, there is a cigarette placed a bit far away in my model library (the graphic designer is really bad QWQ). So later on, I hope to achieve the "center of gravity" effect. I will design a function to display the more important parts at a slightly central position, so I hope to obtain more information through traversal.

                  Nate For example, it appears your code doesn't apply clipping correctly

                  I made the modifications according to the code you provided above. The reason why clipping was not applied earlier is that I didn't find the usage requirements in the model. Since it was mentioned, I'll add it as well.

                  I don't know if my understanding is correct. I made such a modification, but there was no improvement shown in the end.

                  I just sent my code, which includes example.cpp and main.cpp. The former is a simplified test based on the sample code, and the latter is the code I am currently using. It also includes three groups of problematic models. These three should almost cover all the situations I have encountered.

                  We got your email, thanks! We'll take a look soon. It should render using the 3.8.99 spine-sfml, as it does in the 3.8.99 Skeleton Viewer.

                  Note your skeleton data is 3.8.99, so it's important you use and base your code on the 3.8.99 spine-sfml.

                  • ETO님이 이에 답장했습니다.

                    Nate I'm very sorry. I didn't notice such details before. I don't know how to obtain the spine-sfml of 3.8.99. What I got here is "download zip" under the 3.8 branch because I noticed that releases are no longer there. I did download it before, but it should be 3.8.95 (releases), and it probably won't work very well either.

                    The latest in the 3.8 branch is compatible with exports from 3.8.xx editor versions, so it sounds like you have the right runtime code.

                    • ETO님이 이에 답장했습니다.

                      Nate I noticed that you are somewhat interested in my implementation of the bounding box. This is my final implementation. Although the annotations are all in Chinese, in implementation, it is simply to obtain the center of gravity by dividing the total torque by the total mass, and then move the closely surrounding side to center the center of gravity. This does indeed require traversal. (If it is no longer necessary, we can stop discussing the issue in this direction. This has fully met my needs.)


                      Meanwhile, when I was checking just now, I found that I hadn't implemented your suggestions well before.

                      Nate Are you rendering directly to the screen though? The code you've show seems to be rendering to the texture.

                      I just corrected the code.
                      make window.draw(finalSprite); to window.draw(*drawable);
                      But in the end, it still failed.

                      Cool, that is a neat solution!

                      Hopefully on Monday we'll solve your rendering.

                      • ETO님이 이에 답장했습니다.