Blender V5.0
zbuf.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11
12/*---------------------------------------------------------------------------*/
13/* Common includes */
14/*---------------------------------------------------------------------------*/
15
16#include <algorithm>
17#include <cstring>
18
19#include "MEM_guardedalloc.h"
20
21#include "BLI_math_base.h"
22
23/* own includes */
24#include "zbuf.h"
25
26/* could enable at some point but for now there are far too many conversions */
27#ifdef __GNUC__
28# pragma GCC diagnostic ignored "-Wdouble-promotion"
29#endif
30
31/* ****************** Spans ******************************* */
32
33void zbuf_alloc_span(ZSpan *zspan, int rectx, int recty)
34{
35 memset(zspan, 0, sizeof(ZSpan));
36
37 zspan->rectx = rectx;
38 zspan->recty = recty;
39
40 zspan->span1 = MEM_malloc_arrayN<float>(recty, "zspan");
41 zspan->span2 = MEM_malloc_arrayN<float>(recty, "zspan");
42}
43
45{
46 if (zspan) {
47 MEM_SAFE_FREE(zspan->span1);
48 MEM_SAFE_FREE(zspan->span2);
49 }
50}
51
52/* reset range for clipping */
53static void zbuf_init_span(ZSpan *zspan)
54{
55 zspan->miny1 = zspan->miny2 = zspan->recty + 1;
56 zspan->maxy1 = zspan->maxy2 = -1;
57 zspan->minp1 = zspan->maxp1 = zspan->minp2 = zspan->maxp2 = nullptr;
58}
59
60static void zbuf_add_to_span(ZSpan *zspan, const float v1[2], const float v2[2])
61{
62 const float *minv, *maxv;
63 float *span;
64 float xx1, dx0, xs0;
65 int y, my0, my2;
66
67 if (v1[1] < v2[1]) {
68 minv = v1;
69 maxv = v2;
70 }
71 else {
72 minv = v2;
73 maxv = v1;
74 }
75
76 my0 = ceil(minv[1]);
77 my2 = floor(maxv[1]);
78
79 if (my2 < 0 || my0 >= zspan->recty) {
80 return;
81 }
82
83 /* clip top */
84 if (my2 >= zspan->recty) {
85 my2 = zspan->recty - 1;
86 }
87 /* clip bottom */
88 my0 = std::max(my0, 0);
89
90 if (my0 > my2) {
91 return;
92 }
93 /* if (my0>my2) should still fill in, that way we get spans that skip nicely */
94
95 xx1 = maxv[1] - minv[1];
96 if (xx1 > FLT_EPSILON) {
97 dx0 = (minv[0] - maxv[0]) / xx1;
98 xs0 = dx0 * (minv[1] - my2) + minv[0];
99 }
100 else {
101 dx0 = 0.0f;
102 xs0 = min_ff(minv[0], maxv[0]);
103 }
104
105 /* empty span */
106 if (zspan->maxp1 == nullptr) {
107 span = zspan->span1;
108 }
109 else { /* does it complete left span? */
110 if (maxv == zspan->minp1 || minv == zspan->maxp1) {
111 span = zspan->span1;
112 }
113 else {
114 span = zspan->span2;
115 }
116 }
117
118 if (span == zspan->span1) {
119 // printf("left span my0 %d my2 %d\n", my0, my2);
120 if (zspan->minp1 == nullptr || zspan->minp1[1] > minv[1]) {
121 zspan->minp1 = minv;
122 }
123 if (zspan->maxp1 == nullptr || zspan->maxp1[1] < maxv[1]) {
124 zspan->maxp1 = maxv;
125 }
126 zspan->miny1 = std::min(my0, zspan->miny1);
127 zspan->maxy1 = std::max(my2, zspan->maxy1);
128 }
129 else {
130 // printf("right span my0 %d my2 %d\n", my0, my2);
131 if (zspan->minp2 == nullptr || zspan->minp2[1] > minv[1]) {
132 zspan->minp2 = minv;
133 }
134 if (zspan->maxp2 == nullptr || zspan->maxp2[1] < maxv[1]) {
135 zspan->maxp2 = maxv;
136 }
137 zspan->miny2 = std::min(my0, zspan->miny2);
138 zspan->maxy2 = std::max(my2, zspan->maxy2);
139 }
140
141 for (y = my2; y >= my0; y--, xs0 += dx0) {
142 /* xs0 is the X-coordinate! */
143 span[y] = xs0;
144 }
145}
146
147/*-----------------------------------------------------------*/
148/* Functions */
149/*-----------------------------------------------------------*/
150
152 void *handle,
153 float *v1,
154 float *v2,
155 float *v3,
156 void (*func)(void *, int, int, float, float))
157{
158 float x0, y0, x1, y1, x2, y2, z0, z1, z2;
159 float u, v, uxd, uyd, vxd, vyd, uy0, vy0, xx1;
160 const float *span1, *span2;
161 int i, j, x, y, sn1, sn2, rectx = zspan->rectx, my0, my2;
162
163 /* init */
164 zbuf_init_span(zspan);
165
166 /* set spans */
167 zbuf_add_to_span(zspan, v1, v2);
168 zbuf_add_to_span(zspan, v2, v3);
169 zbuf_add_to_span(zspan, v3, v1);
170
171 /* clipped */
172 if (zspan->minp2 == nullptr || zspan->maxp2 == nullptr) {
173 return;
174 }
175
176 my0 = max_ii(zspan->miny1, zspan->miny2);
177 my2 = min_ii(zspan->maxy1, zspan->maxy2);
178
179 // printf("my %d %d\n", my0, my2);
180 if (my2 < my0) {
181 return;
182 }
183
184 /* ZBUF DX DY, in floats still */
185 x1 = v1[0] - v2[0];
186 x2 = v2[0] - v3[0];
187 y1 = v1[1] - v2[1];
188 y2 = v2[1] - v3[1];
189
190 z1 = 1.0f; /* (u1 - u2) */
191 z2 = 0.0f; /* (u2 - u3) */
192
193 x0 = y1 * z2 - z1 * y2;
194 y0 = z1 * x2 - x1 * z2;
195 z0 = x1 * y2 - y1 * x2;
196
197 if (z0 == 0.0f) {
198 return;
199 }
200
201 xx1 = (x0 * v1[0] + y0 * v1[1]) / z0 + 1.0f;
202 uxd = -double(x0) / double(z0);
203 uyd = -double(y0) / double(z0);
204 uy0 = double(my2) * uyd + double(xx1);
205
206 z1 = -1.0f; /* (v1 - v2) */
207 z2 = 1.0f; /* (v2 - v3) */
208
209 x0 = y1 * z2 - z1 * y2;
210 y0 = z1 * x2 - x1 * z2;
211
212 xx1 = (x0 * v1[0] + y0 * v1[1]) / z0;
213 vxd = -double(x0) / double(z0);
214 vyd = -double(y0) / double(z0);
215 vy0 = double(my2) * vyd + double(xx1);
216
217 /* correct span */
218 span1 = zspan->span1 + my2;
219 span2 = zspan->span2 + my2;
220
221 for (i = 0, y = my2; y >= my0; i++, y--, span1--, span2--) {
222
223 sn1 = floor(min_ff(*span1, *span2));
224 sn2 = floor(max_ff(*span1, *span2));
225 sn1++;
226
227 if (sn2 >= rectx) {
228 sn2 = rectx - 1;
229 }
230 sn1 = std::max(sn1, 0);
231
232 u = ((double(sn1) * uxd) + uy0) - (i * uyd);
233 v = ((double(sn1) * vxd) + vy0) - (i * vyd);
234
235 for (j = 0, x = sn1; x <= sn2; j++, x++) {
236 func(handle, x, y, u + (j * uxd), v + (j * vxd));
237 }
238 }
239}
MINLINE float max_ff(float a, float b)
MINLINE int min_ii(int a, int b)
MINLINE float min_ff(float a, float b)
MINLINE int max_ii(int a, int b)
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
#define floor
#define ceil
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
Definition zbuf.h:12
float * span2
Definition zbuf.h:17
const float * maxp2
Definition zbuf.h:16
int maxy2
Definition zbuf.h:15
int miny1
Definition zbuf.h:15
const float * minp2
Definition zbuf.h:16
const float * maxp1
Definition zbuf.h:16
int maxy1
Definition zbuf.h:15
float * span1
Definition zbuf.h:17
int recty
Definition zbuf.h:13
int miny2
Definition zbuf.h:15
int rectx
Definition zbuf.h:13
const float * minp1
Definition zbuf.h:16
i
Definition text_draw.cc:230
void zspan_scanconvert(ZSpan *zspan, void *handle, float *v1, float *v2, float *v3, void(*func)(void *, int, int, float, float))
Definition zbuf.cc:151
static void zbuf_init_span(ZSpan *zspan)
Definition zbuf.cc:53
void zbuf_alloc_span(ZSpan *zspan, int rectx, int recty)
Definition zbuf.cc:33
void zbuf_free_span(ZSpan *zspan)
Definition zbuf.cc:44
static void zbuf_add_to_span(ZSpan *zspan, const float v1[2], const float v2[2])
Definition zbuf.cc:60