add transformation matrix

Mon, 04 Mar 2024 21:16:46 +0100

author
Mike Becker <universe@uap-core.de>
date
Mon, 04 Mar 2024 21:16:46 +0100
changeset 32
86468a71dd73
parent 31
8324037e0148
child 33
e7ddb52facd3

add transformation matrix

src/Makefile file | annotate | diff | comparison | revisions
src/ascension/datatypes.h file | annotate | diff | comparison | revisions
src/ascension/scene.h file | annotate | diff | comparison | revisions
src/ascension/text.h file | annotate | diff | comparison | revisions
src/ascension/transform.h file | annotate | diff | comparison | revisions
src/scene.c file | annotate | diff | comparison | revisions
src/text.c file | annotate | diff | comparison | revisions
test/Makefile file | annotate | diff | comparison | revisions
test/sandbox.c file | annotate | diff | comparison | revisions
     1.1 --- a/src/Makefile	Mon Feb 26 21:16:00 2024 +0100
     1.2 +++ b/src/Makefile	Mon Mar 04 21:16:46 2024 +0100
     1.3 @@ -43,14 +43,15 @@
     1.4  
     1.5  $(BUILD_DIR)/context.o: context.c ascension/context.h \
     1.6   ascension/datatypes.h ascension/window.h ascension/primitives.h \
     1.7 - ascension/mesh.h ascension/scene.h ascension/font.h ascension/error.h \
     1.8 - ascension/utils.h ascension/shader.h
     1.9 + ascension/mesh.h ascension/scene.h ascension/transform.h \
    1.10 + ascension/font.h ascension/error.h ascension/utils.h ascension/shader.h
    1.11  	@echo "Compiling $<"
    1.12  	$(CC) -o $@ $(CFLAGS) -c $<
    1.13  
    1.14  $(BUILD_DIR)/error.o: error.c ascension/context.h ascension/datatypes.h \
    1.15   ascension/window.h ascension/primitives.h ascension/mesh.h \
    1.16 - ascension/scene.h ascension/font.h ascension/error.h ascension/utils.h
    1.17 + ascension/scene.h ascension/transform.h ascension/font.h \
    1.18 + ascension/error.h ascension/utils.h
    1.19  	@echo "Compiling $<"
    1.20  	$(CC) -o $@ $(CFLAGS) -c $<
    1.21  
    1.22 @@ -60,18 +61,20 @@
    1.23  
    1.24  $(BUILD_DIR)/font.o: font.c ascension/font.h ascension/context.h \
    1.25   ascension/datatypes.h ascension/window.h ascension/primitives.h \
    1.26 - ascension/mesh.h ascension/scene.h ascension/font.h ascension/error.h
    1.27 + ascension/mesh.h ascension/scene.h ascension/transform.h \
    1.28 + ascension/font.h ascension/error.h
    1.29  	@echo "Compiling $<"
    1.30  	$(CC) -o $@ $(CFLAGS) -c $<
    1.31  
    1.32  $(BUILD_DIR)/primitives.o: primitives.c ascension/primitives.h \
    1.33   ascension/mesh.h ascension/error.h ascension/context.h \
    1.34   ascension/datatypes.h ascension/window.h ascension/primitives.h \
    1.35 - ascension/scene.h ascension/font.h
    1.36 + ascension/scene.h ascension/transform.h ascension/font.h
    1.37  	@echo "Compiling $<"
    1.38  	$(CC) -o $@ $(CFLAGS) -c $<
    1.39  
    1.40 -$(BUILD_DIR)/scene.o: scene.c ascension/scene.h ascension/error.h
    1.41 +$(BUILD_DIR)/scene.o: scene.c ascension/scene.h ascension/transform.h \
    1.42 + ascension/datatypes.h ascension/error.h
    1.43  	@echo "Compiling $<"
    1.44  	$(CC) -o $@ $(CFLAGS) -c $<
    1.45  
    1.46 @@ -81,16 +84,16 @@
    1.47  	$(CC) -o $@ $(CFLAGS) -c $<
    1.48  
    1.49  $(BUILD_DIR)/text.o: text.c ascension/text.h ascension/font.h \
    1.50 - ascension/datatypes.h ascension/scene.h ascension/context.h \
    1.51 - ascension/window.h ascension/primitives.h ascension/mesh.h \
    1.52 - ascension/error.h ascension/shader.h
    1.53 + ascension/scene.h ascension/transform.h ascension/datatypes.h \
    1.54 + ascension/context.h ascension/window.h ascension/primitives.h \
    1.55 + ascension/mesh.h ascension/error.h ascension/shader.h
    1.56  	@echo "Compiling $<"
    1.57  	$(CC) -o $@ $(CFLAGS) -c $<
    1.58  
    1.59  $(BUILD_DIR)/window.o: window.c ascension/window.h ascension/datatypes.h \
    1.60   ascension/primitives.h ascension/mesh.h ascension/scene.h \
    1.61 - ascension/context.h ascension/window.h ascension/font.h \
    1.62 - ascension/error.h ascension/utils.h
    1.63 + ascension/transform.h ascension/context.h ascension/window.h \
    1.64 + ascension/font.h ascension/error.h ascension/utils.h
    1.65  	@echo "Compiling $<"
    1.66  	$(CC) -o $@ $(CFLAGS) -c $<
    1.67  
     2.1 --- a/src/ascension/datatypes.h	Mon Feb 26 21:16:00 2024 +0100
     2.2 +++ b/src/ascension/datatypes.h	Mon Mar 04 21:16:46 2024 +0100
     2.3 @@ -92,7 +92,7 @@
     2.4  }
     2.5  
     2.6  static inline SDL_Color asc_col_sdl(asc_col4i col) {
     2.7 -    return (SDL_Color) {.r = col.red, .g = col.green, .b =col.blue, .a = col.alpha};
     2.8 +    return (SDL_Color) {.r = col.red, .g = col.green, .b = col.blue, .a = col.alpha};
     2.9  }
    2.10  
    2.11  // --------------------------------------------------------------------------
     3.1 --- a/src/ascension/scene.h	Mon Feb 26 21:16:00 2024 +0100
     3.2 +++ b/src/ascension/scene.h	Mon Mar 04 21:16:46 2024 +0100
     3.3 @@ -28,9 +28,12 @@
     3.4  #ifndef ASCENSION_SCENE_H
     3.5  #define ASCENSION_SCENE_H
     3.6  
     3.7 +#include "transform.h"
     3.8 +
     3.9  typedef struct AscSceneNode AscSceneNode;
    3.10  
    3.11  typedef void(*asc_scene_free_func)(AscSceneNode*);
    3.12 +typedef void(*asc_scene_update_func)(AscSceneNode*);
    3.13  typedef void(*asc_scene_draw_func)(AscSceneNode const*);
    3.14  
    3.15  struct AscSceneNode {
    3.16 @@ -39,16 +42,21 @@
    3.17      AscSceneNode *next;
    3.18      AscSceneNode *children;
    3.19      asc_scene_free_func free_func;
    3.20 +    asc_scene_update_func update_func;
    3.21      asc_scene_draw_func draw_func;
    3.22 +    asc_transform transform;
    3.23 +    bool need_update;
    3.24      // TODO: add more node contents
    3.25  };
    3.26  
    3.27  /**
    3.28   * Place this as first member of a structure that shall be usable as a scene node.
    3.29   */
    3.30 -#define extend_asc_scene_node AscSceneNode node
    3.31 +#define extend_asc_scene_node AscSceneNode base
    3.32  
    3.33 -#define asc_node(obj) (&((obj)->node))
    3.34 +#define asc_node(obj) ((AscSceneNode*)obj)
    3.35 +
    3.36 +#define asc_node_update(node) ((AscSceneNode*)node)->need_update = true
    3.37  
    3.38  typedef struct AscScene {
    3.39      AscSceneNode *root;
     4.1 --- a/src/ascension/text.h	Mon Feb 26 21:16:00 2024 +0100
     4.2 +++ b/src/ascension/text.h	Mon Mar 04 21:16:46 2024 +0100
     4.3 @@ -29,7 +29,6 @@
     4.4  #define ASCENSION_TEXT_H
     4.5  
     4.6  #include "font.h"
     4.7 -#include "datatypes.h"
     4.8  #include "scene.h"
     4.9  
    4.10  typedef struct AscText {
    4.11 @@ -42,7 +41,6 @@
    4.12      bool hidden;
    4.13      bool centered;
    4.14      struct {
    4.15 -        asc_vec2i dimension;
    4.16          unsigned tex_id;
    4.17      } internal;
    4.18  } AscText;
    4.19 @@ -65,16 +63,6 @@
    4.20  AscText *asc_text(int x, int y, char const* text);
    4.21  
    4.22  /**
    4.23 - * Updates the internal state of the text node.
    4.24 - *
    4.25 - * You must invoke this method after changing the state of the struct,
    4.26 - * but not in every frame.
    4.27 - *
    4.28 - * @param node the text node
    4.29 - */
    4.30 -void asc_text_update(AscText *node);
    4.31 -
    4.32 -/**
    4.33   * Releases all the memory of this node.
    4.34   *
    4.35   * @param node the text node
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/ascension/transform.h	Mon Mar 04 21:16:46 2024 +0100
     5.3 @@ -0,0 +1,98 @@
     5.4 +/*
     5.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     5.6 + * Copyright 2023 Mike Becker. All rights reserved.
     5.7 + *
     5.8 + * Redistribution and use in source and binary forms, with or without
     5.9 + * modification, are permitted provided that the following conditions are met:
    5.10 + *
    5.11 + *   1. Redistributions of source code must retain the above copyright
    5.12 + *      notice, this list of conditions and the following disclaimer.
    5.13 + *
    5.14 + *   2. Redistributions in binary form must reproduce the above copyright
    5.15 + *      notice, this list of conditions and the following disclaimer in the
    5.16 + *      documentation and/or other materials provided with the distribution.
    5.17 + *
    5.18 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    5.19 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    5.20 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    5.21 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    5.22 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    5.23 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    5.24 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    5.25 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    5.26 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    5.27 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    5.28 + * POSSIBILITY OF SUCH DAMAGE.
    5.29 + */
    5.30 +
    5.31 +#ifndef ASCENSION_TRANSFORM_H
    5.32 +#define ASCENSION_TRANSFORM_H
    5.33 +
    5.34 +#include "datatypes.h"
    5.35 +
    5.36 +typedef asc_mat4f asc_transform;
    5.37 +
    5.38 +#define ASC_TRANSFORM_SIZE (sizeof(float)*16)
    5.39 +
    5.40 +#ifdef __GNUC__
    5.41 +#define ASC_TRANFORM_FUNC_ATTRIBUTES \
    5.42 +    __attribute__((__nonnull__, __always_inline__))
    5.43 +#else
    5.44 +#define ASC_TRANFORM_FUNC_ATTRIBUTES
    5.45 +#endif
    5.46 +#define ASC_TRANFORM_FUNC ASC_TRANFORM_FUNC_ATTRIBUTES static inline
    5.47 +
    5.48 +
    5.49 +ASC_TRANFORM_FUNC void asc_transform_identity(asc_transform transform) {
    5.50 +    memset(transform, 0, ASC_TRANSFORM_SIZE);
    5.51 +    transform[asc_mat4_index(0, 0)] = 1;
    5.52 +    transform[asc_mat4_index(1, 1)] = 1;
    5.53 +    transform[asc_mat4_index(2, 2)] = 1;
    5.54 +    transform[asc_mat4_index(3, 3)] = 1;
    5.55 +}
    5.56 +
    5.57 +ASC_TRANFORM_FUNC void asc_transform_copy(asc_transform dest, asc_transform src) {
    5.58 +    memcpy(dest, src, ASC_TRANSFORM_SIZE);
    5.59 +}
    5.60 +
    5.61 +ASC_TRANFORM_FUNC void asc_transform_translate(
    5.62 +        asc_transform transform,
    5.63 +        float x, float y, float z
    5.64 +) {
    5.65 +    transform[asc_mat4_index(3, 0)] += x;
    5.66 +    transform[asc_mat4_index(3, 1)] += y;
    5.67 +    transform[asc_mat4_index(3, 2)] += z;
    5.68 +}
    5.69 +
    5.70 +ASC_TRANFORM_FUNC void asc_transform_translate2i(
    5.71 +        asc_transform transform,
    5.72 +        asc_vec2i position
    5.73 +) {
    5.74 +    asc_transform_translate(
    5.75 +            transform,
    5.76 +            (float) position.x, (float) position.y, 0
    5.77 +    );
    5.78 +}
    5.79 +
    5.80 +ASC_TRANFORM_FUNC void asc_transform_scale(
    5.81 +        asc_transform transform,
    5.82 +        float x, float y, float z
    5.83 +) {
    5.84 +    for (unsigned i = 0 ; i < 3 ; i++) {
    5.85 +        transform[asc_mat4_index(0, i)] *= x;
    5.86 +        transform[asc_mat4_index(1, i)] *= y;
    5.87 +        transform[asc_mat4_index(2, i)] *= z;
    5.88 +    }
    5.89 +}
    5.90 +
    5.91 +ASC_TRANFORM_FUNC void asc_transform_scale2i(
    5.92 +        asc_transform transform,
    5.93 +        asc_vec2i dimensions
    5.94 +) {
    5.95 +    asc_transform_scale(
    5.96 +            transform,
    5.97 +            (float) dimensions.width, (float) dimensions.height, 0
    5.98 +    );
    5.99 +}
   5.100 +
   5.101 +#endif //ASCENSION_TRANSFORM_H
     6.1 --- a/src/scene.c	Mon Feb 26 21:16:00 2024 +0100
     6.2 +++ b/src/scene.c	Mon Mar 04 21:16:46 2024 +0100
     6.3 @@ -52,12 +52,23 @@
     6.4  
     6.5  void asc_scene_add(AscScene *scene, AscSceneNode *node) {
     6.6      asc_scene_node_link(scene->root, node);
     6.7 +    asc_node_update(node);
     6.8  }
     6.9  
    6.10  void asc_scene_draw(AscScene const *scene) {
    6.11 -    // TODO: don't visit the tree, visit the render groups
    6.12      CxTreeIterator iter = cx_tree_iterator(scene->root, false, child_list_off_);
    6.13 +
    6.14 +    // skip the root node deliberately, we know it's just the container
    6.15 +    cxIteratorNext(iter);
    6.16 +
    6.17 +    // draw the children
    6.18      cx_foreach(AscSceneNode*, node, iter) {
    6.19 +        if (node->need_update && node->update_func != NULL) {
    6.20 +            node->need_update = false;
    6.21 +            asc_transform_copy(node->transform, node->parent->transform);
    6.22 +            node->update_func(node);
    6.23 +        }
    6.24 +        // TODO: don't visit the tree for drawing, visit the render groups
    6.25          if (node->draw_func != NULL) {
    6.26              node->draw_func(node);
    6.27          }
    6.28 @@ -65,10 +76,10 @@
    6.29  }
    6.30  
    6.31  AscSceneNode *asc_scene_node_empty(void) {
    6.32 -    // TODO: check if this can remain a calloc or if it's too expensive
    6.33      AscSceneNode *node = calloc(1, sizeof(AscSceneNode));
    6.34      assert(node != NULL);
    6.35      node->free_func = (asc_scene_free_func) free;
    6.36 +    asc_transform_identity(node->transform);
    6.37      return node;
    6.38  }
    6.39  
     7.1 --- a/src/text.c	Mon Feb 26 21:16:00 2024 +0100
     7.2 +++ b/src/text.c	Mon Mar 04 21:16:46 2024 +0100
     7.3 @@ -37,21 +37,15 @@
     7.4          return;
     7.5      }
     7.6  
     7.7 +    // TODO: when we group draw calls, we don't need to activate shader here
     7.8      glUseProgram(ASC_SHADER_FONT.base.id);
     7.9  
    7.10 -    // Upload projection
    7.11 -    // TODO: when we group UI draw calls, we don't need this
    7.12 +    // TODO: when we group UI draw calls, we don't need to upload matrices here
    7.13 +    // Upload matrices
    7.14      glUniformMatrix4fv(ASC_SHADER_FONT.base.projection, 1,
    7.15                         GL_FALSE, asc_context.active_window->projection);
    7.16 -
    7.17 -    // Upload model matrix
    7.18 -    asc_mat4f model = {0};
    7.19 -    model[asc_mat4_index(0, 0)] = node->internal.dimension.width;
    7.20 -    model[asc_mat4_index(1, 1)] = node->internal.dimension.height;
    7.21 -    model[asc_mat4_index(3, 0)] = node->position.x;
    7.22 -    model[asc_mat4_index(3, 1)] = node->position.y;
    7.23 -    model[asc_mat4_index(3, 3)] = 1;
    7.24 -    glUniformMatrix4fv(ASC_SHADER_FONT.base.model, 1, GL_FALSE, model);
    7.25 +    glUniformMatrix4fv(ASC_SHADER_FONT.base.model, 1,
    7.26 +                       GL_FALSE, node->base.transform);
    7.27  
    7.28      // Upload surface
    7.29      glActiveTexture(GL_TEXTURE0);
    7.30 @@ -62,27 +56,7 @@
    7.31      asc_primitives_draw_plane();
    7.32  }
    7.33  
    7.34 -AscText *asc_text(int x, int y, char const *text) {
    7.35 -    AscText *node = calloc(1, sizeof(AscText));
    7.36 -    if (node == NULL) {
    7.37 -        asc_error("Out of memory.");
    7.38 -        return NULL;
    7.39 -    }
    7.40 -
    7.41 -    node->node.free_func = (asc_scene_free_func) asc_text_free;
    7.42 -    node->node.draw_func = (asc_scene_draw_func) asc_text_draw;
    7.43 -
    7.44 -    node->position = (asc_vec2i) {x, y};
    7.45 -    node->font = asc_context.active_font;
    7.46 -    node->color = asc_context.ink;
    7.47 -    if (text != NULL) {
    7.48 -        node->text = strdup(text);
    7.49 -    }
    7.50 -
    7.51 -    return node;
    7.52 -}
    7.53 -
    7.54 -void asc_text_update(AscText *node) {
    7.55 +static void asc_text_update(AscText *node) {
    7.56      // short circuit if fully transparent or hidden, we don't need anything
    7.57      if (node->color.alpha == 0 || node->hidden) {
    7.58          return;
    7.59 @@ -109,10 +83,9 @@
    7.60          return;
    7.61      }
    7.62  
    7.63 -    // Store basic node information
    7.64 -    node->position = node->position;
    7.65 -    node->internal.dimension.width = surface->w;
    7.66 -    node->internal.dimension.height = surface->h;
    7.67 +    // Transform
    7.68 +    asc_transform_scale(node->base.transform, (float) surface->w, (float) surface->h, 0);
    7.69 +    asc_transform_translate2i(node->base.transform, node->position);
    7.70  
    7.71      // Transfer Image Data
    7.72      // TODO: move the image data transfer to a separate function - we will need it more often
    7.73 @@ -126,6 +99,28 @@
    7.74      SDL_FreeSurface(surface);
    7.75  }
    7.76  
    7.77 +AscText *asc_text(int x, int y, char const *text) {
    7.78 +    AscText *node = calloc(1, sizeof(AscText));
    7.79 +    if (node == NULL) {
    7.80 +        asc_error("Out of memory.");
    7.81 +        return NULL;
    7.82 +    }
    7.83 +
    7.84 +    node->base.free_func = (asc_scene_free_func) asc_text_free;
    7.85 +    node->base.update_func = (asc_scene_update_func) asc_text_update;
    7.86 +    node->base.draw_func = (asc_scene_draw_func) asc_text_draw;
    7.87 +
    7.88 +    node->position.x = x;
    7.89 +    node->position.y = y;
    7.90 +    node->font = asc_context.active_font;
    7.91 +    node->color = asc_context.ink;
    7.92 +    if (text != NULL) {
    7.93 +        node->text = strdup(text);
    7.94 +    }
    7.95 +
    7.96 +    return node;
    7.97 +}
    7.98 +
    7.99  void asc_text_free(AscText *node) {
   7.100      asc_dprintf("Release text node texture: %u", node->internal.tex_id);
   7.101      glDeleteTextures(1, &node->internal.tex_id);
     8.1 --- a/test/Makefile	Mon Feb 26 21:16:00 2024 +0100
     8.2 +++ b/test/Makefile	Mon Mar 04 21:16:46 2024 +0100
     8.3 @@ -45,8 +45,9 @@
     8.4   ../src/ascension/error.h ../src/ascension/context.h \
     8.5   ../src/ascension/datatypes.h ../src/ascension/window.h \
     8.6   ../src/ascension/primitives.h ../src/ascension/mesh.h \
     8.7 - ../src/ascension/scene.h ../src/ascension/font.h \
     8.8 - ../src/ascension/shader.h ../src/ascension/text.h
     8.9 + ../src/ascension/scene.h ../src/ascension/transform.h \
    8.10 + ../src/ascension/font.h ../src/ascension/shader.h \
    8.11 + ../src/ascension/text.h
    8.12  	@echo "Compiling $<"
    8.13  	$(CC) -o $@ $(CFLAGS) -c $<
    8.14  
     9.1 --- a/test/sandbox.c	Mon Feb 26 21:16:00 2024 +0100
     9.2 +++ b/test/sandbox.c	Mon Mar 04 21:16:46 2024 +0100
     9.3 @@ -69,7 +69,7 @@
     9.4              if (fps != last_fps) {
     9.5                  last_fps = fps;
     9.6                  snprintf(fps_counter->text, 9, "%u FPS", fps);
     9.7 -                asc_text_update(fps_counter);
     9.8 +                asc_node_update(fps_counter);
     9.9              }
    9.10          }
    9.11      } while (asc_loop_next());

mercurial