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;

		}
    }
}
Beispiel #2
0
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
    }
}