static void put_text (void *tileidx, int row, int startcol, unsigned char *text, unsigned int textlen, int offset, int len) { unsigned char *c = tileidx; int i; for (i = 0; i < len; i++) { int offset2 = offset + i * 4; int idx = tex_index (startcol + i, row, TILES_W, 8); c[idx] = (offset2 >= 0 && offset2 < textlen) ? ascii_to_char[text[offset2]] : 0; } DCFlushRange (c, GX_GetTexBufferSize (TILES_W, TILES_H, TILES_FMT, GX_FALSE, 0)); }
// Returns final color uint8_t raytrace(vec3 pos, vec3 dir, hit* info) { // Finish early if there's no direction if (dir.x == 0.0f && dir.y == 0.0f && dir.z == 0.0f) { goto nohit; } vec3 start = pos; int x = (int) pos.x; int y = (int) pos.y; int z = (int) pos.z; int x_dir = dir.x >= 0.0f ? 1 : -1; int y_dir = dir.y >= 0.0f ? 1 : -1; int z_dir = dir.z >= 0.0f ? 1 : -1; float dx_off = x_dir > 0 ? 1.0f : 0.0f; float dy_off = y_dir > 0 ? 1.0f : 0.0f; float dz_off = z_dir > 0 ? 1.0f : 0.0f; int x_face = x_dir > 0 ? FACE_LEFT : FACE_RIGHT; int y_face = y_dir > 0 ? FACE_BOTTOM : FACE_TOP; int z_face = z_dir > 0 ? FACE_BACK : FACE_FRONT; int face = FACE_TOP; // Assumption is made that the camera is never outside the world while (IN_WORLD(x, y, z)) { // Determine if block is solid if (get_block(x, y, z) != BLOCK_AIR) { float dx = start.x - pos.x; float dy = start.y - pos.y; float dz = start.z - pos.z; float dist = dx*dx + dy*dy + dz*dz; vec3 relPos = pos; relPos.x -= x; relPos.y -= y; relPos.z -= z; // If hit info is requested, no color computation is done if (info != NULL) { int nx, ny, nz; face_normal(face, &nx, &ny, &nz); info->hit = true; info->x = x; info->y = y; info->z = z; info->nx = nx; info->ny = ny; info->nz = nz; info->dist = dist; return 0; } int tex = tex_index(relPos, face); return ray_color(x, y, z, pos, tex, face); } // Remaining distance inside this block given ray direction float dx = x - pos.x + dx_off; float dy = y - pos.y + dy_off; float dz = z - pos.z + dz_off; // Calculate distance for each dimension float t1 = dx / dir.x; float t2 = dy / dir.y; float t3 = dz / dir.z; // Find closest hit if (t1 <= t2 && t1 <= t3) { pos.x += dx; pos.y += t1 * dir.y; pos.z += t1 * dir.z; x += x_dir; face = x_face; } if (t2 <= t1 && t2 <= t3) { pos.x += t2 * dir.x; pos.y += dy; pos.z += t2 * dir.z; y += y_dir; face = y_face; } if (t3 <= t1 && t3 <= t2) { pos.x += t3 * dir.x; pos.y += t3 * dir.y; pos.z += dz; z += z_dir; face = z_face; } } nohit: if (info != NULL) { info->hit = false; } // Sky color return skyColor; }