static void load_intersect(bool base, bool out, float dist, t_vertex const *ray, t_intersect *intersect) { intersect->dist = dist; intersect->pos = VEC3_ADD(ray->pos, VEC3_MUL1(ray->dir, dist)); if (base) intersect->norm = VEC3(0, 0, 1.f); else intersect->norm = ft_vec3norm(VEC3_Z(intersect->pos, -intersect->pos.z)); if (out) intersect->norm = VEC3_SUB(VEC3_0(), intersect->norm); if (base) intersect->tex = VEC2(intersect->pos.x, intersect->pos.y); else intersect->tex = VEC2(intersect->norm.z, intersect->norm.y / 2.f + 0.5f); }
/* * Function: vdsClusterOctree * Description: Builds an octree over the given leaf nodes using * vdsClusterNodes(). Takes an array <nodes> of vdsNode pointers * that represent vertices in the original model (i.e., leaf nodes * in the vertex tree to be generated). This array is partitioned * into eight subarrays by splitting across the x, y, and z * midplanes of the tightest-fitting bounding cube, and * vdsClusterOctree() is called recursively on each subarray. * Finally, vdsClusterNodes() is called on the 2-8 nodes returned * by these recursive calls, and vdsClusterOctree returns the newly * created internal node. */ vdsNode *vdsClusterOctree(vdsNode **nodes, int nnodes, int depth) { vdsNode *thisnode; vdsNode *children[8] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; int nchildren = 0; vdsNode **childnodes[8]; int nchildnodes[8] = {0, 0, 0, 0, 0, 0, 0, 0}; int i, j; vdsVec3 min, max, center, average = {0, 0, 0}; assert(depth < VDS_MAXDEPTH); /* Overestimate array size needs for childnodes now; shrink later */ for (i = 0; i < 8; i++) { childnodes[i] = (vdsNode **) malloc(sizeof(vdsNode *) * nnodes); assert(childnodes[i] != NULL); } /* Find the min and max bounds of nodes, and accumulate average coord */ VEC3_COPY(min, nodes[0]->coord); VEC3_COPY(max, nodes[0]->coord); for (i = 0; i < nnodes; i++) { for (j = 0; j < 3; j++) { if (nodes[i]->coord[j] > max[j]) { max[j] = nodes[i]->coord[j]; } if (nodes[i]->coord[j] < min[j]) { min[j] = nodes[i]->coord[j]; } } VEC3_ADD(average, average, nodes[i]->coord); } VEC3_SCALE(average, 1.0 / (float) nnodes, average); VEC3_AVERAGE(center, min, max); if (VEC3_EQUAL(min, max)) { /* vertices coincide, just partition evenly among children */ for (i = 0; i < nnodes; i++) { int index = i % VDS_MAXDEGREE; childnodes[index][nchildnodes[index]] = nodes[i]; nchildnodes[index] ++; } } else { /* Partition the nodes among the 8 octants defined by min and max */ for (i = 0; i < nnodes; i++) { int whichchild = 0; if (nodes[i]->coord[0] > center[0]) { whichchild |= 1; } if (nodes[i]->coord[1] > center[1]) { whichchild |= 2; } if (nodes[i]->coord[2] > center[2]) { whichchild |= 4; } childnodes[whichchild][nchildnodes[whichchild]] = nodes[i]; nchildnodes[whichchild] ++; } } /* Resize childnodes arrays to use only as much space as necessary */ for (i = 0; i < 8; i++) { childnodes[i] = (vdsNode **) realloc(childnodes[i], sizeof(vdsNode *) * nchildnodes[i]); } /* Recurse or store non-empty children */ for (i = 0; i < 8; i++) { if (nchildnodes[i] > 0) { if (nchildnodes[i] == 1) { /* 1 node in octant; store directly */ children[nchildren] = childnodes[i][0]; } else { /* 2 or more nodes in octant; recurse*/ children[nchildren] = vdsClusterOctree(childnodes[i], nchildnodes[i], depth + 1); } nchildren++; } } /* Finally, cluster nonempty children; this node is the resulting parent */ thisnode = vdsClusterNodes(nchildren, children, average[0], average[1], average[2]); for (i = 0; i < 8; i++) { if (nchildnodes[i]) { free(childnodes[i]); } } return thisnode; }