|
| 1 | +#include "bvh.h" |
| 2 | +#include <stdint.h> |
| 3 | +#include <cassert> |
| 4 | + |
| 5 | +// "Insert" a 0 bit after each of the 16 low bits of x |
| 6 | +uint32_t Part1By1(uint32_t x) |
| 7 | +{ |
| 8 | + x &= 0x0000ffff; // x = ---- ---- ---- ---- fedc ba98 7654 3210 |
| 9 | + x = (x ^ (x << 8)) & 0x00ff00ff; // x = ---- ---- fedc ba98 ---- ---- 7654 3210 |
| 10 | + x = (x ^ (x << 4)) & 0x0f0f0f0f; // x = ---- fedc ---- ba98 ---- 7654 ---- 3210 |
| 11 | + x = (x ^ (x << 2)) & 0x33333333; // x = --fe --dc --ba --98 --76 --54 --32 --10 |
| 12 | + x = (x ^ (x << 1)) & 0x55555555; // x = -f-e -d-c -b-a -9-8 -7-6 -5-4 -3-2 -1-0 |
| 13 | + return x; |
| 14 | +} |
| 15 | + |
| 16 | +// "Insert" two 0 bits after each of the 10 low bits of x |
| 17 | +uint32_t Part1By2(uint32_t x) |
| 18 | +{ |
| 19 | + x &= 0x000003ff; // x = ---- ---- ---- ---- ---- --98 7654 3210 |
| 20 | + x = (x ^ (x << 16)) & 0xff0000ff; // x = ---- --98 ---- ---- ---- ---- 7654 3210 |
| 21 | + x = (x ^ (x << 8)) & 0x0300f00f; // x = ---- --98 ---- ---- 7654 ---- ---- 3210 |
| 22 | + x = (x ^ (x << 4)) & 0x030c30c3; // x = ---- --98 ---- 76-- --54 ---- 32-- --10 |
| 23 | + x = (x ^ (x << 2)) & 0x09249249; // x = ---- 9--8 --7- -6-- 5--4 --3- -2-- 1--0 |
| 24 | + return x; |
| 25 | +} |
| 26 | + |
| 27 | +uint32_t EncodeMorton2(uint32_t x, uint32_t y) |
| 28 | +{ |
| 29 | + return (Part1By1(y) << 1) + Part1By1(x); |
| 30 | +} |
| 31 | + |
| 32 | +uint32_t EncodeMorton3(uint32_t x, uint32_t y, uint32_t z) |
| 33 | +{ |
| 34 | + return (Part1By2(z) << 2) + (Part1By2(y) << 1) + Part1By2(x); |
| 35 | +} |
| 36 | + |
| 37 | +#define MSB_MORTON 29 |
| 38 | + |
| 39 | +int classify(uint32_t mc, int i) |
| 40 | +{ |
| 41 | + return 0; |
| 42 | +} |
| 43 | + |
| 44 | +BVHNode* create_bvh_node() |
| 45 | +{ |
| 46 | + return new BVHNode(); |
| 47 | +} |
| 48 | + |
| 49 | +#define MAX_DEPTH 3 |
| 50 | + |
| 51 | + |
| 52 | +void swap(float* radius, float (*pos)[3], int src, int dst) |
| 53 | +{ |
| 54 | + float r = radius[dst]; |
| 55 | + float x = pos[dst][0]; |
| 56 | + float y = pos[dst][1]; |
| 57 | + float z = pos[dst][2]; |
| 58 | + |
| 59 | + radius[dst] = radius[src]; |
| 60 | + pos[dst][0] = pos[src][0]; |
| 61 | + pos[dst][1] = pos[src][1]; |
| 62 | + pos[dst][2] = pos[src][2]; |
| 63 | + |
| 64 | + radius[dst] = r; |
| 65 | + pos[dst][0] = x; |
| 66 | + pos[dst][1] = y; |
| 67 | + pos[dst][2] = z; |
| 68 | +} |
| 69 | + |
| 70 | +void get_sphere_aabb(AABB* paabb, float r, float x, float y, float z) |
| 71 | +{ |
| 72 | + assert(paabb); |
| 73 | + paabb->min[0] = x - r; |
| 74 | + paabb->max[0] = x + r; |
| 75 | + paabb->min[1] = y - r; |
| 76 | + paabb->max[1] = y + r; |
| 77 | + paabb->min[2] = z - r; |
| 78 | + paabb->max[2] = z + r; |
| 79 | +} |
| 80 | +// one = one U two |
| 81 | +void union_aabb(AABB* one, AABB* two) |
| 82 | +{ |
| 83 | + assert(one && two); |
| 84 | + |
| 85 | + one->min[0] = one->min[0] < two->min[0] ? one->min[0] : two->min[0]; |
| 86 | + one->max[0] = one->max[0] > two->max[0] ? one->max[0] : two->max[0]; |
| 87 | + one->min[1] = one->min[1] < two->min[1] ? one->min[1] : two->min[1]; |
| 88 | + one->max[1] = one->max[1] > two->max[1] ? one->max[1] : two->max[1]; |
| 89 | + one->min[2] = one->min[2] < two->min[2] ? one->min[2] : two->min[2]; |
| 90 | + one->max[2] = one->max[2] > two->max[2] ? one->max[2] : two->max[2]; |
| 91 | +} |
| 92 | + |
| 93 | +BVHNode* construct_bvh(BVHNode* pnode, float* radius, float (*pos)[3], int num, int offset, int depth, float* oradius, float (*opos)[3]) |
| 94 | +{ |
| 95 | + int left = 0; |
| 96 | + int right = 0; |
| 97 | + AABB laabb, raabb; |
| 98 | + |
| 99 | + for(int i=offset;i<offset + num;++i) |
| 100 | + { |
| 101 | + uint32_t morton_code = EncodeMorton3( (uint32_t)(pos[i][0] + 0.5f), (uint32_t)(pos[i][1] + 0.5f), (uint32_t)(pos[i][2] + 0.5f) ); |
| 102 | + int side = (morton_code & (1<<(MSB_MORTON - depth))) >> (MSB_MORTON - depth); |
| 103 | + right += side; |
| 104 | + left += (1-side); |
| 105 | + //if(side==0 && i > left - 1 - offset) |
| 106 | + //{ |
| 107 | + //swap(radius, pos, i, offset + left -1); |
| 108 | + //} |
| 109 | + if(side==0) |
| 110 | + { |
| 111 | + AABB l; |
| 112 | + oradius[offset + left-1] = radius[i]; |
| 113 | + opos[offset + left-1][0] = pos[i][0]; |
| 114 | + opos[offset + left-1][1] = pos[i][1]; |
| 115 | + opos[offset + left-1][2] = pos[i][2]; |
| 116 | + get_sphere_aabb(&l, radius[i], pos[i][0], pos[i][1], pos[i][2]); |
| 117 | + union_aabb(&laabb, &l); |
| 118 | + } |
| 119 | + else |
| 120 | + { |
| 121 | + AABB r; |
| 122 | + oradius[offset + num - right] = radius[i]; |
| 123 | + opos[offset + num - right][0] = pos[i][0]; |
| 124 | + opos[offset + num - right][1] = pos[i][1]; |
| 125 | + opos[offset + num - right][2] = pos[i][2]; |
| 126 | + get_sphere_aabb(&r, radius[i], pos[i][0], pos[i][1], pos[i][2]); |
| 127 | + union_aabb(&raabb, &r); |
| 128 | + } |
| 129 | + } |
| 130 | + |
| 131 | + if(left > 1) |
| 132 | + { |
| 133 | + pnode->left_ = create_bvh_node(); |
| 134 | + pnode->left_->aabb_ = laabb; |
| 135 | + construct_bvh(pnode->left_, oradius, opos, left, offset, depth+1, radius, pos); |
| 136 | + } |
| 137 | + if(right > 1) |
| 138 | + { |
| 139 | + pnode->right_ = create_bvh_node(); |
| 140 | + pnode->right_->aabb_ = raabb; |
| 141 | + construct_bvh(pnode->right_, oradius, opos, right, offset + left, depth+1, radius, pos); |
| 142 | + } |
| 143 | + |
| 144 | + union_aabb(&laabb, &raabb); |
| 145 | + pnode->aabb_ = laabb; |
| 146 | + |
| 147 | + return 0; |
| 148 | +} |
0 commit comments