Development and Release Thread
This Library will be for a CE C,
It will be an optional inclusion in your project. Meaning it is not come with "gfx" but it does use it.




*Left: By commandblockguy | Right: By EverydayCode

So I was inspired by many users on Cemetech and YouTube to create a Sprite stacking
Library along with a Sprite stacking engine and on calculator tool.

"The reason I would make an on calculator tool is because most tools out there either cost too much, or they're just unreasonable."


BTW Tool may look like:

"very good content creator (but does not listen to viewers) here is his channel "


The goal of this project is to make a sprite stacking library that is efficient and optimized for developers to use.


Examples of sprite stacking:


The examples above will be what will be what the library will try to replicate and of course try to implement different types of optimization methods. Razz


I'll be posting more information down below ... such as the function and more info about the engine and on calculator tool. Also, I will be posting Demo prototypes!!
The project is split up into 3 different pieces.
*I will add images and prototype GIF's later*

Gfx3 Library / Gfx3 Engine
The library allows users to create and display objects.
"Of course with the use of the 'gfx' library"

Development status: 30% Done


Functions:
Code:
// Setting up layers
void gfx3_SetIndexMaxLayers(uint8_t MaxLayers, uint8_t index_num);
bool gfx3_ActiveIndex(uint8_t index_num);
bool gfx3_SetIndexSprites(gfx_sprite_t *sprite_buffer, int layer_num, uint8_t index_num);

// Layer Options
bool gfx3_SetX_Offset(int X_offset, uint8_t index);
bool gfx3_SetY_Offset(int Y_offset,  uint8_t index);
void gfx3_SetObject_Scale(int xs, int ys, uint8_t index);

// Object rotation
void gfx3_RotateObjectCC(uint8_t index);
void gfx3_RotateObjectC(uint8_t index);
void gfx3_RotateObject_Layer(uint8_t angle, uint8_t layer_num, uint8_t index);
void gfx3_RotateObject(uint8_t angle, uint8_t index);

// displaying "objects"
void gfx3_Object_NoClip(uint24_t x, uint8_t y, uint8_t index);
void gfx3_TransparentObject_NoClip(uint24_t x, uint8_t y, uint8_t index);


LIBRARY TO-DO LIST
  • (100%) Displaying object.
  • (50%) Rotating objects.
  • (0%) Optimize.
  • (0%) Debug.


Sprite/object editor:
In this part of the project I'll be creating a Sprite editor called "stackedX". It would allow users to export angled Sprites and object appvars to use on in the C library Razz.
"Like I said in a previous post most tools out there for sprite stacking is way too expensive, so I'm making it easier for users to create objects for the library."

Development status: Concept Art

fight is the editor | left is the preview

EDITOR TO-DO LIST
  • (100%) Concept Art.
  • (0%) Prototype.
  • (0%) Previewing drawn data.
  • (0%) Exporting data.
  • (0%) Auto Saving.
  • (0%) Final Debug!!



What do you think about this project? Would you ever use "gfx3" in a CE project?
So much yes!
G freaking G!!
This is awesome.
Assuming we don't go for a pre-rendered frame for Project TI-Trek, this could actually be very useful for Trek's 3D interface.
Quick Update:
gfx3 Library and engine:

"I know it may look like regular Sprites lol, but it's being layered in the buffer"

The Sprites are being layered in the buffer and their blit onto the screen. One issue I encountered was malloc"ing" the sprites in rotate function. This somehow allocates too much which leads to a crash.



Questions/Statements:

ACagliano wrote:
So much yes!
G freaking G!!
This is awesome.
Assuming we don't go for a pre-rendered frame for Project TI-Trek, this could actually be very useful for Trek's 3D interface.


Lol yes that is a lot of g's Razz
I hope it would be very useful to you!!
If you're worried about frame rates I'll be introducing two methods later on.
"an okay api is no more than 8 functions, a good api is 4 or less"
Quick update:



Just finished the concept art for the sprite editor!
(undo and redo) mistakes (such as deleting layers and much more)
(saving / auto saving) simply saves before you leave can be changed in the settings' autosave to deliberately saving it.
(pallet and colors) you just may be able to upload the own pallet, or you could choose from a variety of x lib colors.



this is the preview area where you view your objects.
You can export your objects as an app var to use in the C programming language, or you can export it as many angled Sprites.


MateoConLechuga wrote:
"An okay API is no more than 8 functions, A good API is 4 or less"


Lol I just understood it. Thank you for the support Razz
"it is an okay library"

This is the first version of the project and is still in development stages ... There is bound to be some type of mess (hints *development*). Anyway any advice towards the structure of the functions and much more will be useful and not regarded.
The sprite editor concept art looks very professional and the test screenies look to be running quite smoothly, nice job!
I recently updated the amount of functions from 12 to 7 Razz

Old functions
Code:
// Setting up layers
void gfx3_SetIndexMaxLayers(uint8_t MaxLayers, uint8_t index_num);
bool gfx3_ActiveIndex(uint8_t index_num);
bool gfx3_SetIndexSprites(gfx_sprite_t *sprite_buffer, int layer_num, uint8_t index_num);

// Layer Options
bool gfx3_SetX_Offset(int X_offset, uint8_t index);
bool gfx3_SetY_Offset(int Y_offset,  uint8_t index);
void gfx3_SetObject_Scale(int xs, int ys, uint8_t index);

// Object rotation
void gfx3_RotateObjectCC(uint8_t index);
void gfx3_RotateObjectC(uint8_t index);
void gfx3_RotateObject_Layer(uint8_t angle, uint8_t layer_num, uint8_t index);
void gfx3_RotateObject(uint8_t angle, uint8_t index);

// displaying "objects"
void gfx3_Object_NoClip(uint24_t x, uint8_t y, uint8_t index);
void gfx3_TransparentObject_NoClip(uint24_t x, uint8_t y, uint8_t index);


New functions

Code:
struct gfx3_object_t{
   gfx_sprite_t *layers; // z_index
   uint8_t max_index;
   
   int x_offset;
   int y_offset;
   
   uint8_t x_scale;
   uint8_t y_scale;
   
   uint8_t angle;
};

// Active Objects
void gfx3_SetObjectSprites(gfx3_object_t *gfx3_object, gfx_sprite_t *sprite_buffer, int sizeofarray);

// other setting
void gfx3_SetObjectScale(gfx3_object_t *gfx3_object, uint8_t x_scale, uint8_t y_scale);
void gfx3_SetObjectOffset(gfx3_object_t *gfx3_object, uint8_t x_offset, uint8_t y_offset);

// Rotating Index
void gfx3_RotateObjectLayer(gfx3_object_t *gfx3_object, uint8_t angle, uint8_t z_index);
void gfx3_RotateObject(gfx3_object_t *gfx3_object, uint8_t angle, uint8_t z_index)

// Displaying Objects
void gfx3_Object_NoClip(gfx3_object_t *gfx3_object, uint24_t x, uint8_t y);
void gfx3_TransparentObject_NoClip(gfx3_object_t *gfx3_object, uint24_t x, uint8_t y);
Please don't do "typedef struct". Just use "struct" everywhere Very Happy
Mateo: I am still new to C and I have noticed that you really hate typedef structs! Why is that and should I always avoid them when coding C on computers as well as on the TI 84 Plus CE?
Yes you should always avoid them for many reasons; unless you desire to make the structure opaque to users:

* Hiding the fact that it's a struct causes bad things if people don't realize it: allocating structs on the stack is something you should be aware of (and careful with), and passing them as parameters is is much better done explicitly as a "pointer to struct".
* It tends to be easier to read. For example "gfx3_object_t" doesn't really tell me anything, as "uint8_t" is also a typedef. "struct gfx3_object" tells me that it is a structure and has elements.
* It avoids issues with direct assignment. For example, you can do "uint8_t a = b;", but " you shouldn't do "gfx3_object_t a = b;".
Okay, I will avoid them in the future. Thank you!
It been a while but I'm having an issue with rotating a sprite using gfx_RotateScaleSprite. Every time I free temp_layer the sprites in gfx3_object->layers[z_index] get messed up.


Code:
void gfx3_RotateObjectLayer(struct gfx3_object_t *gfx3_object, uint8_t angle, uint8_t z_index)
{
   gfx_sprite_t *temp_layer = NULL;
   
   temp_layer = gfx_MallocSprite(gfx3_object->layers[z_index]->width, gfx3_object->layers[z_index]->height);
   gfx3_object->layers[z_index] = gfx_RotateScaleSprite(gfx3_object->layers[z_index], temp_layer, angle, 68);
   free(temp_layer);
   
   return;
}


here are some screenshots: (left, no free(temp_layer) | Right, has free(temp_layer))


The issue is that the left crashes with no free(temp_layer), but when I add free temp it lead to "layers being copied".
The issue is a use-after-free. gfx_RotateScaleSprite just returns its second argument, so gfx3_object->layers[z_index] points to the same location as temp_layer. Freeing temp_layer thus causes the memory pointed to by gfx3_object->layers[z_index] to become invalid, as it's the same region of memory.

One solution would be to free the old gfx3_object->layers[z_index] after allocating the new one, rather than freeing the new one.

Another would be to have the object reuse the same locations for layers, rather than dynamically allocating new ones each time. This would be faster as malloc is slow on ez80.

Also, gfx_RotateScaleSprite is destructive - repeatedly rotating a sprite 1/10th of a turn 10 times doesn't always give back the original sprite. You might just end up with a single color for a sprite if you call this function enough.

You also should have a NULL check after every malloc to avoid a potential null pointer dereference, which causes a crash.

Finally, you don't need to include the return at the end unless you're returning a value.
Hello, Cemetech. It's been a long time since I posted about this project... uhm necroposting.
However I had some spare time (from college) and wanted to work on some of my unfinished simple projects.

Here is some eye candy!


Left: Teapot render with 61 layers / Right: Van render with 22 layers

The library has the ability to render large object but is very slow, I was wondering if there was a faster way to render sprites "without asm <_<". I've also added the ability to render compressed sprites/objects these sprites can be both transparent and non-transparent. As for rendering the sprites they are all noclip nothing new there.

If you want to check out the code or try it out for yourself here's the link to the github: https://github.com/Overload02/GFX3

*Documentation hasn't been added so I would suggest looking in the "/test" folder to see how to set it up.*
Alvajoy123 wrote:
The library has the ability to render large object but is very slow, I was wondering if there was a faster way to render sprites "without asm <_<".


Unfortunately, I don't think there's a whole lot that you can do in terms of performance without making additional assumptions about user input or completely changing your approach to rendering. Although gfx_RotatedScaledSprite_NoClip is quite well optimized for what it's doing, drawing a rotated sprite is just inherently a more time-consuming operation than drawing a regular sprite, and it also prevents you from using optimizations like run-length encoding.

The main optimization that I could see is using a different sprite size for each layer, to ensure that each sprite is no larger than it needs to be. gfx_RotatedScaledSprite_NoClip still needs to do some amount of work for each pixel in the sprite even if that pixel is transparent. So, using the smallest possible sprite size for each layer, and then adding an offset to the sprite so that it renders in the correct place, could potentially speed things up quite a bit, as well as saving space.
commandblockguy wrote:
Alvajoy123 wrote:
The library has the ability to render large object but is very slow, I was wondering if there was a faster way to render sprites "without asm <_<".


Unfortunately, I don't think there's a whole lot that you can do in terms of performance without making additional assumptions about user input or completely changing your approach to rendering. Although gfx_RotatedScaledSprite_NoClip is quite well optimized for what it's doing, drawing a rotated sprite is just inherently a more time-consuming operation than drawing a regular sprite, and it also prevents you from using optimizations like run-length encoding.

The main optimization that I could see is using a different sprite size for each layer, to ensure that each sprite is no larger than it needs to be. gfx_RotatedScaledSprite_NoClip still needs to do some amount of work for each pixel in the sprite even if that pixel is transparent. So, using the smallest possible sprite size for each layer, and then adding an offset to the sprite so that it renders in the correct place, could potentially speed things up quite a bit, as well as saving space.


I have 2 questions.

First question, I feel like allowing for different sprite sizes raises the question of whether computing the center of the previous sprite will consume calculation time.

Second question, using RLE seems like a really good idea, by the way. Would it be better if I rotated the sprite and made it an RLE sprite? or would speed be consumed by computation of rotating and converting?

----

As for now I've cleaned up the github repository and worked on the documentation a bit!! which you can view here: https://github.com/Overload02/GFX3

Also made some more eye candy!

I tried working with different sprites in the test bence and this is how it turned out:


Left: Star sprite from toolchain demo / Right: House sprite testing different functions
Alvajoy123 wrote:
First question, I feel like allowing for different sprite sizes raises the question of whether computing the center of the previous sprite will consume calculation time.


It will obviously take some computation time, but if you optimize it correctly it should take less time than the extra pixels would have in most cases.

Alvajoy123 wrote:
Second question, using RLE seems like a really good idea, by the way. Would it be better if I rotated the sprite and made it an RLE sprite? or would speed be consumed by computation of rotating and converting?

I believe that converting a sprite to RLET takes strictly more time than drawing said sprite onto the screen, so if you're converting every sprite to RLET every frame you're not going to save any time. Converting each possible rotation into a sprite once ahead of time would save time, but you then lose most of the benefits of sprite stacking in the first place.


I've released the first version of GFX3 on GitHub and Cemetech!

Features:
  • Allows you to stack numerous sprites on top of each other.
  • Each sprites' position, scale, and rotation can be adjusted.
  • Individual sprite transparency support.
  • Straightforward syntax for object rendering.


Changelog: Version 1.0.0-beta.1
  • Added padding to objects.
  • Implemented a new algorithm for calculating the width and height of objects.


Edit: I was low on time had to use ChatGPT.
---

commandblockguy wrote:
Alvajoy123 wrote:
First question, I feel like allowing for different sprite sizes raises the question of whether computing the center of the previous sprite will consume calculation time.


It will obviously take some computation time, but if you optimize it correctly it should take less time than the extra pixels would have in most cases.

Alvajoy123 wrote:
Second question, using RLE seems like a really good idea, by the way. Would it be better if I rotated the sprite and made it an RLE sprite? or would speed be consumed by computation of rotating and converting?

I believe that converting a sprite to RLET takes strictly more time than drawing said sprite onto the screen, so if you're converting every sprite to RLET every frame you're not going to save any time. Converting each possible rotation into a sprite once ahead of time would save time, but you then lose most of the benefits of sprite stacking in the first place.



Thanks for the explanation, I've made a new branch to test rendering objects with different layer sizes. I'll be posting more updates soon!
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement