#include #include // USAGE: see brightspot.sh (and in the future brightspot.bat) // It should output the right parameters for the sun direction in q3map2's format. // But probably is broken. #define false 0 #define true 1 int flip[6*3] = { false, false, true, // "rt" true, true, true, // "lf" false, true, false, // "bk" true, false, false, // "ft" false, false, true, // "up" false, false, true // "dn" }; static const double skyboxtexcoord2f[6*4*2] = { // skyside[0] 0, 1, 1, 1, 1, 0, 0, 0, // skyside[1] 1, 0, 0, 0, 0, 1, 1, 1, // skyside[2] 1, 1, 1, 0, 0, 0, 0, 1, // skyside[3] 0, 0, 0, 1, 1, 1, 1, 0, // skyside[4] 0, 1, 1, 1, 1, 0, 0, 0, // skyside[5] 0, 1, 1, 1, 1, 0, 0, 0 }; #define GET_SKY_IMAGE(x,y,z) \ (fabs(x)>=fabs(y) && fabs(x)>=fabs(z)) ? (((x) > 0) ? 0 : 1) : \ (fabs(y)>=fabs(x) && fabs(y)>=fabs(z)) ? (((y) > 0) ? 2 : 3) : \ (((z) > 0) ? 4 : 5) int highest[6] = { 0, 0, 1, 1, 2, 2 }; static const double skyboxvertex3f[6*4*3] = { // skyside[0] 16, -16, 16, 16, -16, -16, 16, 16, -16, 16, 16, 16, // skyside[1] -16, 16, 16, -16, 16, -16, -16, -16, -16, -16, -16, 16, // skyside[2] 16, 16, 16, 16, 16, -16, -16, 16, -16, -16, 16, 16, // skyside[3] -16, -16, 16, -16, -16, -16, 16, -16, -16, 16, -16, 16, // skyside[4] -16, -16, 16, 16, -16, 16, 16, 16, 16, -16, 16, 16, // skyside[5] 16, -16, -16, -16, -16, -16, -16, 16, -16, 16, 16, -16 }; void Unmap2f(double x, double y, const double *corners, double *u, double *v) { // x - corners[0] == *u * (corners[2] - corners[0]) + *v * (corners[4] - corners[2]); // y - corners[1] == *u * (corners[3] - corners[1]) + *v * (corners[5] - corners[3]); double xc0 = x - corners[0]; double yc1 = y - corners[1]; double c20 = corners[2] - corners[0]; double c31 = corners[3] - corners[1]; double c42 = corners[4] - corners[2]; double c53 = corners[5] - corners[3]; // xc0 == *u * c20 + *v * c42; // yc1 == *u * c31 + *v * c53; double det = c20 * c53 - c31 * c42; double du = xc0 * c53 - yc1 * c42; double dv = c20 * yc1 - c31 * xc0; *u = du / det; *v = dv / det; } void Map3f(double u, double v, const double *corners, double *x, double *y, double *z) { *x = corners[0] + u * (corners[3] - corners[0]) + v * (corners[6] - corners[3]); *y = corners[1] + u * (corners[4] - corners[1]) + v * (corners[7] - corners[4]); *z = corners[2] + u * (corners[5] - corners[2]) + v * (corners[8] - corners[5]); } void Map2f(double u, double v, const double *corners, double *x, double *y) { *x = u * (corners[2] - corners[0]) + v * (corners[4] - corners[2]) + corners[0]; *y = u * (corners[3] - corners[1]) + v * (corners[5] - corners[3]) + corners[1]; } void Unmap3f(double x, double y, double z, const double *corners, double *u, double *v) { //*x = corners[0] + u * (corners[3] - corners[0]) + v * (corners[6] - corners[3]); //*y = corners[1] + u * (corners[4] - corners[1]) + v * (corners[7] - corners[4]); //*z = corners[2] + u * (corners[5] - corners[2]) + v * (corners[8] - corners[5]); // THREE equations, TWO would be better! Let's simply use the two "better" ones double xc0 = x - corners[0]; double yc1 = y - corners[1]; double zc2 = z - corners[2]; double c30 = corners[3] - corners[0]; double c41 = corners[4] - corners[1]; double c52 = corners[5] - corners[2]; double c63 = corners[6] - corners[3]; double c74 = corners[7] - corners[4]; double c85 = corners[8] - corners[5]; double det_x = c41 * c85 - c52 * c74; double det_y = c30 * c85 - c52 * c63; double det_z = c30 * c74 - c41 * c63; if(fabs(det_x) >= fabs(det_y) && fabs(det_x) >= fabs(det_z)) { double du = yc1 * c85 - zc2 * c74; double dv = c41 * zc2 - c52 * yc1; *u = du / det_x; *v = dv / det_x; } else if(fabs(det_y) >= fabs(det_z)) { double du = xc0 * c85 - zc2 * c63; double dv = c30 * zc2 - c52 * xc0; *u = du / det_y; *v = dv / det_y; } else { double du = xc0 * c74 - yc1 * c63; double dv = c30 * yc1 - c41 * xc0; *u = du / det_z; *v = dv / det_z; } } void MapCoord(int pic, int y, int x, double vec[3]) { int h; int flipx = flip[3*pic+0]; int flipy = flip[3*pic+1]; int flipdiag = flip[3*pic+2]; double u, v; if(flipx) x = 511 - x; if(flipy) y = 511 - y; if(flipdiag) { h = x; x = y; y = h; } Unmap2f((x + 0.5) / 512.0, (y + 0.5) / 512.0, skyboxtexcoord2f + 4*2*pic, &u, &v); Map3f(u, v, skyboxvertex3f + 6*2*pic, &vec[0], &vec[1], &vec[2]); } void UnmapCoord(const double vec_[3], int *pic, int *y, int *x) { int h; int flipx; int flipy; int flipdiag; double u, v, xx, yy; double f; double vec[3]; // identify which pic it is *pic = GET_SKY_IMAGE(vec_[0], vec_[1], vec_[2]); f = 16.0/fabs(vec_[highest[*pic]]); vec[0] = vec_[0] * f; vec[1] = vec_[1] * f; vec[2] = vec_[2] * f; flipx = flip[3*(*pic)+0]; flipy = flip[3*(*pic)+1]; flipdiag = flip[3*(*pic)+2]; *x = *y = 0; Unmap3f(vec[0], vec[1], vec[2], skyboxvertex3f + 6*2*(*pic), &u, &v); Map2f(u, v, skyboxtexcoord2f + 4*2*(*pic), &xx, &yy); *x = (int) (xx * 512.0 + 0.5); *y = (int) (yy * 512.0 + 0.5); if(flipdiag) { h = *x; *x = *y; *y = h; } if(flipy) *y = 511 - *y; if(flipx) *x = 511 - *x; } int main(int argc, char **argv) { FILE *f; int i, j, k; unsigned char picture[6][512][512]; unsigned char max; double brightvec[3]; double pitch, yaw, l; if(argc != 2) { fprintf(stderr, "Usage: %s imagefile.gray\n", *argv); return 1; } f = fopen(argv[1], "rb"); if(!f) { perror("fopen"); return 1; } fread(&picture, sizeof(picture), 1, f); fclose(f); brightvec[0] = brightvec[1] = brightvec[2] = 0; max = 0; for(i = 0; i < 6; ++i) for(j = 0; j < 512; ++j) for(k = 0; k < 512; ++k) if(picture[i][j][k] > max) max = picture[i][j][k]; for(i = 0; i < 6; ++i) for(j = 0; j < 512; ++j) for(k = 0; k < 512; ++k) { double vec[3], f; MapCoord(i, j, k, vec); f = pow(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2], -1.5); // I know what I am doing. f *= exp(10 * (picture[i][j][k] - max)); brightvec[0] += f * vec[0]; brightvec[1] += f * vec[1]; brightvec[2] += f * vec[2]; } l = sqrt(brightvec[0]*brightvec[0] + brightvec[1]*brightvec[1] + brightvec[2]*brightvec[2]); l /= 16; brightvec[0] /= l; brightvec[1] /= l; brightvec[2] /= l; fprintf(stderr, "vec = %f %f %f\n", brightvec[0], brightvec[1], brightvec[2]); UnmapCoord(brightvec, &i, &j, &k); fprintf(stderr, "picture %d pixel (%d %d) value %d\n", i, k, j, picture[i][j][k]); pitch = atan2(brightvec[2], sqrt(brightvec[0]*brightvec[0] + brightvec[1]*brightvec[1])); yaw = atan2(brightvec[1], brightvec[0]); printf("%f %f\n", yaw * 180 / M_PI, pitch * 180 / M_PI); return 0; }