void CCourse::CalcNormals () { for (int y=0; y<ny; y++) { for (int x=0; x<nx; x++) { TVector3 nml(0.0, 0.0, 0.0); TVector3 p0 (XCD(x), ELEV(x,y), ZCD(y)); if ((x + y) % 2 == 0) { if (x > 0 && y > 0) { TVector3 p1 = NMLPOINT(x, y-1); TVector3 p2 = NMLPOINT(x-1,y-1); TVector3 v1 = SubtractVectors (p1, p0); TVector3 v2 = SubtractVectors (p2, p0); TVector3 n = CrossProduct (v2, v1); NormVector (n); nml = AddVectors (nml, n); p1 = NMLPOINT (x-1, y-1); p2 = NMLPOINT (x-1, y); v1 = SubtractVectors (p1, p0); v2 = SubtractVectors (p2, p0); n = CrossProduct (v2, v1); NormVector (n); nml = AddVectors (nml, n); } if (x > 0 && y < ny-1) { TVector3 p1 = NMLPOINT(x-1,y); TVector3 p2 = NMLPOINT(x-1,y+1); TVector3 v1 = SubtractVectors (p1, p0); TVector3 v2 = SubtractVectors (p2, p0); TVector3 n = CrossProduct (v2, v1); NormVector (n); nml = AddVectors (nml, n); p1 = NMLPOINT(x-1,y+1); p2 = NMLPOINT(x ,y+1); v1 = SubtractVectors (p1, p0); v2 = SubtractVectors (p2, p0); n = CrossProduct (v2, v1); NormVector (n); nml = AddVectors (nml, n); } if (x < nx-1 && y > 0) { TVector3 p1 = NMLPOINT(x+1,y); TVector3 p2 = NMLPOINT(x+1,y-1); TVector3 v1 = SubtractVectors (p1, p0); TVector3 v2 = SubtractVectors (p2, p0); TVector3 n = CrossProduct (v2, v1); NormVector (n); nml = AddVectors (nml, n); p1 = NMLPOINT(x+1,y-1); p2 = NMLPOINT(x ,y-1); v1 = SubtractVectors (p1, p0); v2 = SubtractVectors (p2, p0); n = CrossProduct (v2, v1); NormVector (n); nml = AddVectors (nml, n); } if (x < nx-1 && y < ny-1) { TVector3 p1 = NMLPOINT(x+1,y); TVector3 p2 = NMLPOINT(x+1,y+1); TVector3 v1 = SubtractVectors (p1, p0); TVector3 v2 = SubtractVectors (p2, p0); TVector3 n = CrossProduct (v1, v2); NormVector (n); nml = AddVectors (nml, n); p1 = NMLPOINT(x+1,y+1); p2 = NMLPOINT(x ,y+1); v1 = SubtractVectors (p1, p0); v2 = SubtractVectors (p2, p0); n = CrossProduct (v1, v2); NormVector (n); nml = AddVectors (nml, n); } } else { if (x > 0 && y > 0) { TVector3 p1 = NMLPOINT(x, y-1); TVector3 p2 = NMLPOINT(x-1,y); TVector3 v1 = SubtractVectors (p1, p0); TVector3 v2 = SubtractVectors (p2, p0); TVector3 n = CrossProduct (v2, v1); NormVector (n); nml = AddVectors (nml, n); } if (x > 0 && y < ny-1) { TVector3 p1 = NMLPOINT(x-1,y); TVector3 p2 = NMLPOINT(x ,y+1); TVector3 v1 = SubtractVectors (p1, p0); TVector3 v2 = SubtractVectors (p2, p0); TVector3 n = CrossProduct (v2, v1); NormVector (n); nml = AddVectors (nml, n); } if (x < nx-1 && y > 0) { TVector3 p1 = NMLPOINT(x+1,y); TVector3 p2 = NMLPOINT(x ,y-1); TVector3 v1 = SubtractVectors (p1, p0); TVector3 v2 = SubtractVectors (p2, p0); TVector3 n = CrossProduct (v2, v1); NormVector (n); nml = AddVectors (nml, n); } if (x < nx-1 && y < ny-1) { TVector3 p1 = NMLPOINT(x+1,y); TVector3 p2 = NMLPOINT(x ,y+1); TVector3 v1 = SubtractVectors (p1, p0); TVector3 v2 = SubtractVectors (p2, p0); TVector3 n = CrossProduct (v1, v2); NormVector (n); nml = AddVectors (nml, n); } } NormVector (nml); nmls [x + nx * y] = nml; continue; } } }
void calc_normals(const char *course) { scalar_t *elevation; scalar_t courseWidth, courseLength; int nx, ny; int x,y; point_t p0, p1, p2; vector_t n, nml, v1, v2; char buff[BUFF_LEN]; sprintf( buff, "%s/courses/%s/normal.data", getparam_data_dir(), course ); get_course_dimensions( &courseWidth, &courseLength ); get_course_divisions( &nx, &ny ); if(nmls != (void*)-1 && nmls_fd != -1) { munmap(nmls, nmls_len); close(nmls_fd); } #if 0 else { free(nmls); } #endif struct stat buf; int exists = (stat(buff, &buf) == 0); if(exists) { nmls_fd = open(buff, O_RDONLY); if ( nmls_fd == -1) { handle_system_error( 1, "can't open file failed" ); } TRDebugLog("mapping to memory normal.data\n"); nmls_len = sizeof(vector_t)*nx*ny; nmls = mmap(NULL, nmls_len, PROT_READ, MAP_SHARED,nmls_fd, 0); if ( nmls == (void *)-1 ) { handle_system_error( 1, "read mmap failed" ); } } else { nmls_len = sizeof(vector_t)*nx*ny; #if TARGET_IPHONE_SIMULATOR nmls_fd = open(buff, O_RDWR | O_CREAT | O_TRUNC, 0644); if ( nmls_fd == -1) { handle_system_error( 1, "can't open file failed" ); } int result = lseek(nmls_fd, nmls_len-1, SEEK_SET); if (result == -1) { handle_system_error( 1, "can't write file failed" ); } result = write(nmls_fd, "", 1); if (result != 1) { handle_system_error( 1, "can't write file failed" ); } nmls = mmap(NULL, nmls_len, PROT_READ | PROT_WRITE, MAP_SHARED, nmls_fd, 0); if ( nmls == (void *)-1 ) { handle_system_error( 1, "write mmap failed" ); } TRDebugLog("Writing to normal.data\n"); #else # ifdef TR_DEBUG_MODE abort(); // This shouldn't be reached on simulator. Crash to indicate. # endif nmls = malloc(nmls_len); #endif elevation = get_course_elev_data(); for ( y=0; y<ny; y++) { for ( x=0; x<nx; x++) { nml = make_vector( 0., 0., 0. ); p0 = make_point( XCD(x), ELEV(x,y), ZCD(y) ); /* The terrain is meshed as follows: ... +-+-+-+-+ x<---+ |\|/|\|/| | ...+-+-+-+-+... V |/|\|/|\| y +-+-+-+-+ ... So there are two types of vertices: those surrounded by four triangles (x+y is odd), and those surrounded by eight (x+y is even). */ #define POINT(x,y) make_point( XCD(x), ELEV(x,y), ZCD(y) ) if ( (x + y) % 2 == 0 ) { if ( x > 0 && y > 0 ) { p1 = POINT(x, y-1); p2 = POINT(x-1,y-1); v1 = subtract_points( p1, p0 ); v2 = subtract_points( p2, p0 ); n = cross_product( v2, v1 ); check_assertion( n.y > 0, "course normal points down" ); normalize_vector( &n ); nml = add_vectors( nml, n ); p1 = POINT(x-1,y-1); p2 = POINT(x-1,y ); v1 = subtract_points( p1, p0 ); v2 = subtract_points( p2, p0 ); n = cross_product( v2, v1 ); check_assertion( n.y > 0, "course normal points down" ); normalize_vector( &n ); nml = add_vectors( nml, n ); } if ( x > 0 && y < ny-1 ) { p1 = POINT(x-1,y ); p2 = POINT(x-1,y+1); v1 = subtract_points( p1, p0 ); v2 = subtract_points( p2, p0 ); n = cross_product( v2, v1 ); check_assertion( n.y > 0, "course normal points down" ); normalize_vector( &n ); nml = add_vectors( nml, n ); p1 = POINT(x-1,y+1); p2 = POINT(x ,y+1); v1 = subtract_points( p1, p0 ); v2 = subtract_points( p2, p0 ); n = cross_product( v2, v1 ); check_assertion( n.y > 0, "course normal points down" ); normalize_vector( &n ); nml = add_vectors( nml, n ); } if ( x < nx-1 && y > 0 ) { p1 = POINT(x+1,y ); p2 = POINT(x+1,y-1); v1 = subtract_points( p1, p0 ); v2 = subtract_points( p2, p0 ); n = cross_product( v2, v1 ); check_assertion( n.y > 0, "course normal points down" ); normalize_vector( &n ); nml = add_vectors( nml, n ); p1 = POINT(x+1,y-1); p2 = POINT(x ,y-1); v1 = subtract_points( p1, p0 ); v2 = subtract_points( p2, p0 ); n = cross_product( v2, v1 ); check_assertion( n.y > 0, "course normal points down" ); normalize_vector( &n ); nml = add_vectors( nml, n ); } if ( x < nx-1 && y < ny-1 ) { p1 = POINT(x+1,y ); p2 = POINT(x+1,y+1); v1 = subtract_points( p1, p0 ); v2 = subtract_points( p2, p0 ); n = cross_product( v1, v2 ); check_assertion( n.y > 0, "course normal points down" ); normalize_vector( &n ); nml = add_vectors( nml, n ); p1 = POINT(x+1,y+1); p2 = POINT(x ,y+1); v1 = subtract_points( p1, p0 ); v2 = subtract_points( p2, p0 ); n = cross_product( v1, v2 ); check_assertion( n.y > 0, "course normal points down" ); normalize_vector( &n ); nml = add_vectors( nml, n ); } } else { /* x + y is odd */ if ( x > 0 && y > 0 ) { p1 = POINT(x, y-1); p2 = POINT(x-1,y ); v1 = subtract_points( p1, p0 ); v2 = subtract_points( p2, p0 ); n = cross_product( v2, v1 ); check_assertion( n.y > 0, "course normal points down" ); normalize_vector( &n ); nml = add_vectors( nml, n ); } if ( x > 0 && y < ny-1 ) { p1 = POINT(x-1,y ); p2 = POINT(x ,y+1); v1 = subtract_points( p1, p0 ); v2 = subtract_points( p2, p0 ); n = cross_product( v2, v1 ); check_assertion( n.y > 0, "course normal points down" ); normalize_vector( &n ); nml = add_vectors( nml, n ); } if ( x < nx-1 && y > 0 ) { p1 = POINT(x+1,y ); p2 = POINT(x ,y-1); v1 = subtract_points( p1, p0 ); v2 = subtract_points( p2, p0 ); n = cross_product( v2, v1 ); check_assertion( n.y > 0, "course normal points down" ); normalize_vector( &n ); nml = add_vectors( nml, n ); } if ( x < nx-1 && y < ny-1 ) { p1 = POINT(x+1,y ); p2 = POINT(x ,y+1); v1 = subtract_points( p1, p0 ); v2 = subtract_points( p2, p0 ); n = cross_product( v1, v2 ); check_assertion( n.y > 0, "course normal points down" ); normalize_vector( &n ); nml = add_vectors( nml, n ); } } normalize_vector( &nml ); NORMAL(x,y) = nml; continue; } #undef POINT } #if TARGET_IPHONE_SIMULATOR munmap(nmls, nmls_len); close(nmls_fd); nmls_fd = open(buff, O_RDONLY); if (nmls_fd == -1) { handle_system_error( 1, "can't remount normal.data" ); } TRDebugLog("remounting to memory normal.data\n"); nmls_len = sizeof(vector_t)*nx*ny; nmls = mmap(NULL, nmls_len, PROT_READ, MAP_SHARED, nmls_fd, 0); if ( nmls == (void *)-1 ) { handle_system_error( 1, "remount mmap failed" ); } #endif } }