void print_vec(const char *prefix, struct array *array, const char *suffix) {
assert(array->n_dims == 2);
- assert(array->stride[1] == sizeof(float));
+ assert(array->dim[1] == sizeof(float));
printf("%s[", prefix);
- for (int i = 0; i < array->dim[0]; ++i)
+ for (size_t i = 0; i < array->dim[0]; ++i)
printf("%s%7.3f", i ? ", " : "", *(float *)array_index1(array, i));
printf("]%s", suffix);
}
void print_mat(const char *prefix, struct array *array, const char *suffix) {
assert(array->n_dims == 3);
- assert(array->stride[2] == sizeof(float));
+ assert(array->dim[2] == sizeof(float));
printf("%s[", prefix);
- for (int i = 0; i < array->dim[0]; ++i) {
+ for (size_t i = 0; i < array->dim[0]; ++i) {
printf("%s[", i ? " " : "");
- for (int j = 0; j < array->dim[1]; ++j)
+ for (size_t j = 0; j < array->dim[1]; ++j)
printf("%s%7.3f", j ? ", " : "", *(float *)array_index2(array, i, j));
printf("]%s", i < array->dim[0] - 1 ? "\n" : "");
}
// compute C = A B
struct array *mul_mat_mat(const struct array *A, const struct array *B) {
assert(A->n_dims == 3);
- assert(A->stride[2] == sizeof(float));
+ assert(A->dim[2] == sizeof(float));
assert(B->n_dims == 3);
- assert(B->stride[2] == sizeof(float));
+ assert(B->dim[2] == sizeof(float));
size_t I = A->dim[0];
size_t J = B->dim[1];
size_t K = A->dim[1];
assert(K == B->dim[0]);
struct array *C = array_new3(I, J, sizeof(float));
- for (int i = 0; i < I; ++i)
- for (int j = 0; j < J; ++j) {
+ for (size_t i = 0; i < I; ++i)
+ for (size_t j = 0; j < J; ++j) {
float v = 0.f;
- for (int k = 0; k < K; ++k)
+ for (size_t k = 0; k < K; ++k)
v += *(float *)array_index2(A, i, k) * *(float *)array_index2(B, k, j);
*(float *)array_index2(C, i, j) = v;
}
// compute c = A b
struct array *mul_mat_vec(const struct array *A, const struct array *b) {
assert(A->n_dims == 3);
- assert(A->stride[2] == sizeof(float));
+ assert(A->dim[2] == sizeof(float));
assert(b->n_dims == 2);
- assert(b->stride[1] == sizeof(float));
+ assert(b->dim[1] == sizeof(float));
size_t I = A->dim[0];
size_t J = A->dim[1];
assert(J == b->dim[0]);
struct array *c = array_new2(I, sizeof(float));
- for (int i = 0; i < I; ++i) {
+ for (size_t i = 0; i < I; ++i) {
float v = 0.f;
- for (int j = 0; j < J; ++j)
+ for (size_t j = 0; j < J; ++j)
v += *(float *)array_index2(A, i, j) * *(float *)array_index1(b, j);
*(float *)array_index1(c, i) = v;
}
*min = 1e30f;
*max = -1e30f;
assert(p->n_dims == 2);
- assert(p->stride[1] == sizeof(float));
- for (int i = 0; i < p->dim[0]; ++i) {
+ assert(p->dim[1] == sizeof(float));
+ for (size_t i = 0; i < p->dim[0]; ++i) {
float v = *(float *)array_index1(p, i);
if (v < *min)
*min = v;
}
void mat_min_max(struct array *p) {
- for (int i = 0; i < p->dim[0]; ++i) {
+ for (size_t i = 0; i < p->dim[0]; ++i) {
struct array *q = array_dup1(p, i);
float min, max;
vec_min_max(q, &min, &max);
- printf("dim %d min %7.3f max %7.3f\n", i, min, max);
+ printf("dim %ld min %7.3f max %7.3f\n", i, min, max);
array_free(q);
}
}
+float vec_dot(struct array *a, struct array *b) {
+ assert(a->n_dims == 2);
+ assert(a->dim[1] == sizeof(float));
+ assert(b->n_dims == 2);
+ assert(b->dim[1] == sizeof(float));
+ size_t I = a->dim[0];
+ assert(I == b->dim[0]);
+ float v = 0.f;
+ for (size_t i = 0; i < I; ++i)
+ v += *(float *)array_index1(a, i) * *(float *)array_index1(b, i);
+ return v;
+}
+
+struct array *vec_cross(struct array *a, struct array *b) {
+ assert(a->n_dims == 2);
+ assert(a->dim[0] == 3);
+ assert(a->dim[1] == sizeof(float));
+ assert(b->n_dims == 2);
+ assert(b->dim[0] == 3);
+ assert(b->dim[1] == sizeof(float));
+ struct array *c = array_new2(3, sizeof(float));
+ *(float *)array_index1(c, 0) =
+ *(float *)array_index1(a, 1) * *(float *)array_index1(b, 2) -
+ *(float *)array_index1(a, 2) * *(float *)array_index1(b, 1);
+ *(float *)array_index1(c, 1) =
+ *(float *)array_index1(a, 2) * *(float *)array_index1(b, 0) -
+ *(float *)array_index1(a, 0) * *(float *)array_index1(b, 2);
+ *(float *)array_index1(c, 2) =
+ *(float *)array_index1(a, 0) * *(float *)array_index1(b, 1) -
+ *(float *)array_index1(a, 1) * *(float *)array_index1(b, 0);
+ return c;
+}
+
+struct array *mat_unproject(struct array *A) {
+ assert(A->n_dims == 3);
+ assert(A->dim[2] == sizeof(float));
+ size_t I = A->dim[1];
+ size_t J = A->dim[0];
+ assert(J >= 1);
+ struct array *B = array_new3(--J, I, sizeof(float));
+ for (size_t i = 0; i < I; ++i) {
+ float d = *(float *)array_index2(A, J, i);
+ assert(d < -EPSILON || d >= EPSILON);
+ d = 1.f / d;
+ for (size_t j = 0; j < J; ++j)
+ *(float *)array_index2(B, j, i) = *(float *)array_index2(A, j, i) * d;
+ }
+ return B;
+}
+
+// special for column-wise vertex arrays
+// construct row-wise array for a given face
+struct array *gather(struct array *A, int n_cols, int *cols) {
+ assert(A->n_dims == 3);
+ assert(A->dim[2] == sizeof(float));
+ size_t J = A->dim[0];
+ struct array *B = array_new3(n_cols, J, sizeof(float));
+ for (int i = 0; i < n_cols; ++i) {
+ int col = cols[i];
+ assert(col >= 0 && col < A->dim[1]);
+ for (size_t j = 0; j < J; ++j)
+ *(float *)array_index2(B, i, j) = *(float *)array_index2(A, j, col);
+ }
+ return B;
+}
+
int main(void) {
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
fprintf(stderr, "SDL_Init(): %s\n\n", SDL_GetError());
// model
#if 1
obj *o = obj_create("grey_bliss_set.obj"); //"Chest.obj");
- struct array *model_vertices = array_new3(
- 4,
- obj_num_vert(o),
- sizeof(float)
- );
- for (int i = 0; i < model_vertices->dim[1]; ++i) {
- float v[4];
- obj_get_vert_v(o, i, v);
- v[3] = 1.f;
- array_set2(model_vertices, 0, i, v);
- array_set2(model_vertices, 1, i, v + 1);
- array_set2(model_vertices, 2, i, v + 2);
- array_set2(model_vertices, 3, i, v + 3);
+ struct array *model_vertices;
+ {
+ int I = obj_num_vert(o);
+ model_vertices = array_new3(4, I, sizeof(float));
+ for (int i = 0; i < I; ++i) {
+ float v[4];
+ obj_get_vert_v(o, i, v);
+ v[3] = 1.f;
+ *(float *)array_index2(model_vertices, 0, i) = v[0];
+ *(float *)array_index2(model_vertices, 1, i) = v[1];
+ *(float *)array_index2(model_vertices, 2, i) = v[2];
+ *(float *)array_index2(model_vertices, 3, i) = v[3];
+ }
}
#else
struct array *model_vertices = array_new3(4, 8, sizeof(float));
for (int j = 0; j < 2; ++j)
for (int k = 0; k < 2; ++k) {
float v[4] = {i * 2 - 1, j * 2 - 1, k * 2 - 1, 1.f};
- array_set2(model_vertices, 0, i * 4 + j * 2 + k, v);
- array_set2(model_vertices, 1, i * 4 + j * 2 + k, v + 1);
- array_set2(model_vertices, 2, i * 4 + j * 2 + k, v + 2);
- array_set2(model_vertices, 3, i * 4 + j * 2 + k, v + 3);
+ int l = i * 4 + j * 2 + k;
+ *(float *)array_index2(model_vertices, 0, l) = v[0];
+ *(float *)array_index2(model_vertices, 1, l) = v[1];
+ *(float *)array_index2(model_vertices, 2, l) = v[2];
+ *(float *)array_index2(model_vertices, 3, l) = v[3];
}
int model_lines[12][2] = {
{0, 1}, // 0, 0, 0 -> 0, 0, 1
// compose device, perspective, camera and model transforms for speed
struct array *t0 = mul_mat_mat(device_transform, perspective_transform);
- struct array *t1 = mul_mat_mat(t0, camera_rotate);
- struct array *t2 = mul_mat_mat(t1, camera_translate);
- struct array *t3 = mul_mat_mat(t2, model_rotate);
- struct array *t4 = mul_mat_mat(t3, model_translate);
+ struct array *t1 = mul_mat_mat(camera_rotate, camera_translate);
+ struct array *t2 = mul_mat_mat(t1, model_rotate);
+ struct array *t3 = mul_mat_mat(t2, model_translate);
// transform model points
- struct array *p = mul_mat_mat(t4, model_vertices);
-
- // unproject
- for (int i = 0; i < p->dim[1]; ++i) {
- float v[3];
- array_get2(p, v, 0, i);
- array_get2(p, v + 1, 1, i);
- array_get2(p, v + 2, 2, i);
- if (v[2] >= EPSILON) {
- v[0] /= v[2];
- v[1] /= v[2];
- array_set2(p, 0, i, v);
- array_set2(p, 1, i, v + 1);
- }
- }
+ struct array *p = mul_mat_mat(t3, model_vertices);
+ struct array *pu = mat_unproject(p);
+ struct array *q = mul_mat_mat(t0, p);
+ struct array *qu = mat_unproject(q);
// draw
SDL_SetRenderDrawColor(renderer, 0, 0xff, 0, 0xff);
for (int j = 0; j < J; ++j) {
int v[3];
obj_get_poly(o, i, j, v);
- float p0[3];
- array_get2(p, p0, 0, v[0]);
- array_get2(p, p0 + 1, 1, v[0]);
- array_get2(p, p0 + 2, 2, v[0]);
- float p1[3];
- array_get2(p, p1, 0, v[1]);
- array_get2(p, p1 + 1, 1, v[1]);
- array_get2(p, p1 + 2, 2, v[1]);
- float p2[3];
- array_get2(p, p2, 0, v[2]);
- array_get2(p, p2 + 1, 1, v[2]);
- array_get2(p, p2 + 2, 2, v[2]);
- if (p0[2] >= EPSILON && p1[2] >= EPSILON)
- SDL_RenderDrawLine(renderer, p0[0], p0[1], p1[0], p1[1]);
- if (p0[2] >= EPSILON && p2[2] >= EPSILON)
- SDL_RenderDrawLine(renderer, p0[0], p0[1], p2[0], p2[1]);
- if (p1[2] >= EPSILON && p2[2] >= EPSILON)
- SDL_RenderDrawLine(renderer, p1[0], p1[1], p2[0], p2[1]);
+ struct array *qug = gather(qu, 3, v);
+ SDL_RenderDrawLine(
+ renderer,
+ *(float *)array_index2(qug, 0, 0),
+ *(float *)array_index2(qug, 0, 1),
+ *(float *)array_index2(qug, 1, 0),
+ *(float *)array_index2(qug, 1, 1)
+ );
+ SDL_RenderDrawLine(
+ renderer,
+ *(float *)array_index2(qug, 1, 0),
+ *(float *)array_index2(qug, 1, 1),
+ *(float *)array_index2(qug, 2, 0),
+ *(float *)array_index2(qug, 2, 1)
+ );
+ SDL_RenderDrawLine(
+ renderer,
+ *(float *)array_index2(qug, 2, 0),
+ *(float *)array_index2(qug, 2, 1),
+ *(float *)array_index2(qug, 0, 0),
+ *(float *)array_index2(qug, 0, 1)
+ );
+ array_free(qug);
}
/*int*/ J = obj_num_line(o, i);
for (int j = 0; j < J; ++j) {
int v[2];
obj_get_line(o, i, j, v);
- float p0[3];
- array_get2(p, p0, 0, v[0]);
- array_get2(p, p0 + 1, 1, v[0]);
- array_get2(p, p0 + 2, 2, v[0]);
- float p1[3];
- array_get2(p, p1, 0, v[1]);
- array_get2(p, p1 + 1, 1, v[1]);
- array_get2(p, p1 + 2, 2, v[1]);
- if (p0[2] >= EPSILON && p1[2] >= EPSILON)
- SDL_RenderDrawLine(renderer, p0[0], p0[1], p1[0], p1[1]);
+ struct array *qug = gather(qu, 2, v);
+ SDL_RenderDrawLine(
+ renderer,
+ *(float *)array_index2(qug, 0, 0),
+ *(float *)array_index2(qug, 0, 1),
+ *(float *)array_index2(qug, 1, 0),
+ *(float *)array_index2(qug, 1, 1)
+ );
+ array_free(qug);
}
}
}
#else
for (int i = 0; i < 12; ++i) {
- float p0[3];
- array_get2(p, p0, 0, model_lines[i][0]);
- array_get2(p, p0 + 1, 1, model_lines[i][0]);
- array_get2(p, p0 + 2, 2, model_lines[i][0]);
- float p1[3];
- array_get2(p, p1, 0, model_lines[i][1]);
- array_get2(p, p1 + 1, 1, model_lines[i][1]);
- array_get2(p, p1 + 2, 2, model_lines[i][1]);
- if (p0[2] >= EPSILON && p1[2] >= EPSILON)
- SDL_RenderDrawLine(renderer, p0[0], p0[1], p1[0], p1[1]);
+ struct array *qug = gather(qu, 2, model_lines[i]);
+ SDL_RenderDrawLine(
+ renderer,
+ *(float *)array_index2(qug, 0, 0),
+ *(float *)array_index2(qug, 0, 1),
+ *(float *)array_index2(qug, 1, 0),
+ *(float *)array_index2(qug, 1, 1)
+ );
+ array_free(qug);
}
#endif
+ array_free(qu);
+ array_free(q);
+ array_free(pu);
array_free(p);
- array_free(t4);
array_free(t3);
array_free(t2);
array_free(t1);