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