Browse Source

Use STB rect pack for texture atlas WIP

master
Macoy Madson 4 months ago
parent
commit
cd289186f5
  1. 54
      src/NanoSVG.cake
  2. 64
      src/VectorPuppetShow.cake

54
src/NanoSVG.cake

@ -1,5 +1,7 @@
;; NanoSVG.cake: Load and rasterize SVG files
(import "CHelpers.cake")
(import "CHelpers.cake"
;; GameLib
"STB.cake")
(c-preprocessor-define-constant NANOSVG_IMPLEMENTATION 1)
(c-preprocessor-define-constant NANOSVGRAST_IMPLEMENTATION 1)
@ -25,7 +27,7 @@
(token-splice-rest body tokens)))
(return true))
(forward-declare (struct NSVGshape))
(forward-declare (struct NSVGshape) (struct NSVGimage))
;; This isn't 100% accurate I think, but does seem to make containment likely
(defun nanosvg-get-shape-bounds-with-stroke-int (shape (addr NSVGshape) bounds-out (addr int))
@ -56,3 +58,51 @@
(type-cast (+ (at i (path shape > bounds))
(path shape > strokeWidth))
float))))
;;
;; Texture atlas creation
;;
(c-preprocessor-define-constant STB_RECT_PACK_IMPLEMENTATION 1)
(export-and-evaluate
(add-c-search-directory-module "Dependencies/stb")
(c-import "stb_rect_pack.h"))
(c-import "<stdlib.h>")
(forward-declare (struct stbrp_rect))
(defun nanosvg-pack-into-atlas (image (addr NSVGimage)
width int height int
rectangles-out (addr (addr stbrp_rect))
&return bool)
(var context stbrp_context (array 0))
(var num-nodes int width)
(var-cast-to nodes (addr stbrp_node)
(malloc (* (sizeof stbrp_node) num-nodes)))
(defer (free nodes))
(stbrp_init_target (addr context) width height nodes num-nodes)
(var num-shapes int 0)
(each-shape-in-svg-image image shape
(unless (bit-and (path shape > flags) NSVG_FLAGS_VISIBLE)
(continue))
(incr num-shapes))
(var-cast-to rectangles (addr stbrp_rect)
(malloc (* (sizeof stbrp_rect) num-shapes)))
(memset rectangles 0 (* (sizeof stbrp_rect) num-shapes))
(var shape-index int 0)
(each-shape-in-svg-image image shape
(unless (bit-and (path shape > flags) NSVG_FLAGS_VISIBLE)
(continue))
(var rectangle (addr stbrp_rect) (addr (at shape-index rectangles)))
(set-fields (deref rectangle)
id shape-index
w (- (at 2 (path shape > bounds)) (at 0 (path shape > bounds)))
h (- (at 3 (path shape > bounds)) (at 1 (path shape > bounds))))
(incr shape-index))
(unless (stbrp_pack_rects (addr context) rectangles num-shapes)
(return false))
(set (deref rectangles-out) rectangles)
(return true))

64
src/VectorPuppetShow.cake

@ -152,6 +152,8 @@
(defer
(when svg-image-texture
(SDL_DestroyTexture svg-image-texture)))
(var packed-rectangles (addr stbrp_rect) null)
(defer (when packed-rectangles (free packed-rectangles)))
(scope
(var filename (addr (const char)) "data/TestPuppet.svg")
(set puppet-image (nsvgParseFromFile filename "px" 96.0f))
@ -177,6 +179,26 @@
(at 2 (path shape > bounds))
(at 3 (path shape > bounds))))
(var max-texture-size int 4096)
(var attempt-pack-width int 256)
(var attempt-pack-height int 256)
(var packed-successfully bool true)
(while (= 0 (nanosvg-pack-into-atlas
puppet-image
attempt-pack-width
attempt-pack-height
(addr packed-rectangles)))
(free packed-rectangles)
(set attempt-pack-width (* 2 attempt-pack-width))
(set attempt-pack-height (* 2 attempt-pack-height))
(when (> attempt-pack-width max-texture-size)
(vpslog "Failed to pack image into atlas\n")
(set packed-successfully false)
(break)))
(when packed-successfully
(vpslog "Packed SVG shapes into %dx%d texture\n" attempt-pack-width
attempt-pack-height))
(nsvgRasterize rasterizer puppet-image 0 0 1 image-buffer
(path puppet-image > width) (path puppet-image > height)
(* 4 (path puppet-image > width)))
@ -267,10 +289,11 @@
(SDL_RenderCopy renderer svg-image-texture
(addr source-rectangle) (addr destination-rectangle)))
(var mouse-x int 0)
(var mouse-y int 0)
(SDL_GetMouseState (addr mouse-x) (addr mouse-y))
(scope ;; Shape selection and debug viewing
(var mouse-x int 0)
(var mouse-y int 0)
(SDL_GetMouseState (addr mouse-x) (addr mouse-y))
(var hovered-shape-id-buffer (array 1024 char) (array 0))
(var hovered-write-head (addr char) hovered-shape-id-buffer)
(each-shape-in-svg-image puppet-image shape
@ -323,10 +346,10 @@
(at 1 sized-bounds))
int)))
(SDL_SetRenderDrawColor renderer 230 10 10 255)
(when (and (>= mouse-x (type-cast (at 0 sized-bounds) float))
(>= mouse-y (type-cast (at 1 sized-bounds) float))
(< mouse-x (type-cast (at 2 sized-bounds) float))
(< mouse-y (type-cast (at 3 sized-bounds) float)))
(when (and (>= mouse-x (at 0 sized-bounds))
(>= mouse-y (at 1 sized-bounds))
(< mouse-x (at 2 sized-bounds))
(< mouse-y (at 3 sized-bounds)))
(SDL_SetRenderDrawColor renderer 10 230 10 255)
(set hovered-write-head
(+ hovered-write-head
@ -343,11 +366,30 @@
(/ true-window-width 9) (- true-window-height 10)
hovered-shape-id-buffer))
(when true
(when packed-rectangles
(var current-rectangle (addr stbrp_rect) packed-rectangles)
(each-shape-in-svg-image puppet-image shape
(unless (bit-and (path shape > flags) NSVG_FLAGS_VISIBLE)
(continue))
(var draw-rectangle SDL_Rect
(array (path current-rectangle > x)
(path current-rectangle > y)
(path current-rectangle > w)
(path current-rectangle > h)))
(SDL_SetRenderDrawColor renderer 100 100 100 255)
(scope ;; Color on hover
(var sized-bounds (array 4 int) (array 0))
(nanosvg-get-shape-bounds-with-stroke-int shape sized-bounds)
(when (and (>= mouse-x (at 0 sized-bounds))
(>= mouse-y (at 1 sized-bounds))
(< mouse-x (at 2 sized-bounds))
(< mouse-y (at 3 sized-bounds)))
(SDL_SetRenderDrawColor renderer 10 10 230 255)))
(SDL_RenderDrawRect renderer (addr draw-rectangle))
(incr current-rectangle)))
(when true ;; Debug position
(var buffer (array 256 char) (array 0))
(var mouse-x int 0)
(var mouse-y int 0)
(SDL_GetMouseState (addr mouse-x) (addr mouse-y))
(snprintf buffer (- (array-size buffer) 1) "Mouse: %4d %4d Percent of window: %.2f %.2f"
mouse-x mouse-y
(/ mouse-x (type-cast true-window-width float)) (/ mouse-y (type-cast true-window-height float)))

Loading…
Cancel
Save