예제 #1
0
gint create_hf_list (gl_preview_struct *hf) {
//	Creates the HF list for the current HF
	gint list, i, j;
	list = glGenLists(1);
//	printf("**************CREATE_HF_LIST\n");
	glNewList(list, GL_COMPILE);
	glColor4fv(terrain_colour);
	for (i=0; i<hf->mesh_size-1; i++)
		for (j=0; j<hf->mesh_size-1; j++) {
			glBegin(GL_TRIANGLES);
			// Triangle 1
		//	glEdgeFlag(TRUE);
			draw_vertex(VECTORIZE(i,j,hf->mesh_size),hf->hf);
			draw_vertex(VECTORIZE(i+1,j,hf->mesh_size),hf->hf);
		//	glEdgeFlag(FALSE);
			draw_vertex(VECTORIZE(i+1,j+1,hf->mesh_size),hf->hf);
			// Triangle 2
			draw_vertex(VECTORIZE(i,j,hf->mesh_size),hf->hf);
		//	glEdgeFlag(TRUE);
			draw_vertex(VECTORIZE(i+1,j+1,hf->mesh_size),hf->hf);
			draw_vertex(VECTORIZE(i,j+1,hf->mesh_size),hf->hf);
			glEnd();
		}

	glEndList();
	glClearColor(0.0, 0.0, 0.0, 1.0);
	return list;
}
예제 #2
0
void create_vertices(gl_preview_struct *gl_hf) {
//	Create the Open GL vertices from the HF buffer
	gint i,j,indx;
	unsigned int lag;
	vertex *p1, *p2, *p3, *p4;
	vertex v1,v2,v3;
	gfloat step,incx, incy, incz, norm, value, height_scale;
	
	switch (gl_hf->data_type) {
		case GDOUBLE_ID:
			height_scale = 1.0 / HEIGHT_SCALE;
			break;
		case HF_TYPE_ID:
			height_scale = 65535.0 / HEIGHT_SCALE;
			break;
		case GINT_ID:
			height_scale = 65535.0 / HEIGHT_SCALE;
			break;
		default: // UNSIGNED_CHAR_ID
			height_scale = 256.0 / HEIGHT_SCALE;
	}

	step = 2.0 / (gl_hf->mesh_size-1);
	if (gl_hf->hf)
		x_free(gl_hf->hf);
	gl_hf->hf = (vertex *) x_malloc(sizeof(vertex) * (gl_hf->mesh_size+1) * (gl_hf->mesh_size+1), "vertex");
//	printf("CREATE_VERTICES - MESH_SIZE: %d; step: %6.4f; Height scale: %5.3f\n", gl_hf->mesh_size, step, height_scale);
//	Initializing normals
	for (i=0; i<gl_hf->mesh_size; i++)
		for (j=0; j<gl_hf->mesh_size; j++) {
			gl_hf->hf[VECTORIZE(i,j,gl_hf->mesh_size)].nx = 0.0;
			gl_hf->hf[VECTORIZE(i,j,gl_hf->mesh_size)].ny = 0.0;
			gl_hf->hf[VECTORIZE(i,j,gl_hf->mesh_size)].nz = 0.0;
		}
// printf("********* Normals initialized *************\n");

//	Filling vertices array
// 	**** MODIFY TO ALLOW NON SQUARE GRIDS ****
	lag = log2i(gl_hf->max_x)-log2i(gl_hf->mesh_size);
// printf("***************MAX_X: %d;  MESH_SIZE: %d; LAG: %d\n", gl_hf->max_x, gl_hf->mesh_size, lag);
	for (i=0; i<gl_hf->mesh_size; i++)
		for (j=0; j<gl_hf->mesh_size; j++) {
			gl_hf->hf[VECTORIZE(i,j,gl_hf->mesh_size)].x = -1+i*step;
			gl_hf->hf[VECTORIZE(i,j,gl_hf->mesh_size)].y = -1+j*step;
			indx = VECTORIZE(j<<lag,i<<lag,gl_hf->max_x);
			switch (gl_hf->data_type) {
				case GDOUBLE_ID:
					value = (gfloat) *(((gdouble*) gl_hf->grid)+indx);
					break;
				case HF_TYPE_ID:
					value = (gfloat) *(((hf_type*) gl_hf->grid)+indx);
					break;
				case GINT_ID:
					value = (gfloat) *(((gint*) gl_hf->grid)+indx);
					break;
				default: // UNSIGNED_CHAR_ID
					value = (gfloat) *(((unsigned char*) gl_hf->grid)+indx);
			}
			gl_hf->hf[VECTORIZE(i,j,gl_hf->mesh_size)].z = value / height_scale;

		}

// printf("********* Vertices array filled *************\n");

	for (i=0; i<gl_hf->mesh_size-1; i++)
		for (j=0; j<gl_hf->mesh_size-1; j++) {
			p1 = &gl_hf->hf[VECTORIZE(i,j,gl_hf->mesh_size)];
			p2 = &gl_hf->hf[VECTORIZE(i+1,j,gl_hf->mesh_size)];
			p3 = &gl_hf->hf[VECTORIZE(i+1,j+1,gl_hf->mesh_size)];
			p4 = &gl_hf->hf[VECTORIZE(i,j+1,gl_hf->mesh_size)];
			// v1, v2, v3:  vectors used to calculate normals to triangles
			v1.x = p2->x - p1->x;
			v1.y = p2->y - p1->y;
			v1.z = p2->z - p1->z;
			v2.x = p3->x - p1->x;
			v2.y = p3->y - p1->y;
			v2.z = p3->z - p1->z;
			v3.x = p4->x - p1->x;
			v3.y = p4->y - p1->y;
			v3.z = p4->z - p1->z;
			// Vector product = unnormalized normal
			incx = v2.y*v1.z - v1.y*v2.z;
			incy = v2.z*v1.x - v1.z*v2.x;
			incz = v2.x*v1.y - v1.x*v2.y;
			norm = sqrt(incx*incx+incy*incy+incz*incz);
			incx = incx / norm;
			incy = incy / norm;
			incz = incz / norm;
			p1->nx -= incx;
			p1->ny -= incy;
			p1->nz -= incz;
			p2->nx -= incx;
			p2->ny -= incy;
			p2->nz -= incz;
			p3->nx -= incx;
			p3->ny -= incy;
			p3->nz -= incz;
			incx = v3.y*v2.z - v2.y*v3.z;
			incy = v3.z*v2.x - v2.z*v3.x;
			incz = v3.x*v2.y - v2.x*v3.y;
			p1->nx -= incx;
			p1->ny -= incy;
			p1->nz -= incz;
			p3->nx -= incx;
			p3->ny -= incy;
			p3->nz -= incz;
			p4->nx -= incx;
			p4->ny -= incy;
			p4->nz -= incz;
		}
//	Nomalizing normals
	for (i=0; i<gl_hf->mesh_size; i++)
		for (j=0; j<gl_hf->mesh_size; j++) {
			p1 = &gl_hf->hf[VECTORIZE(i,j,gl_hf->mesh_size)];
			norm = sqrt(p1->nx*p1->nx + p1->ny*p1->ny + p1->nz*p1->nz);
			p1->nx = p1->nx / norm;
			p1->ny = p1->ny / norm;
			p1->nz = p1->nz / norm;
// printf("(%d,%d): (x,y,z): (%f, %f, %f);  (nx,ny,nz): (%f,%f,%f); \n",i,j,p1->x,p1->y,p1->z,p1->nx,p1->ny,p1->nz);
		}

// printf("********* Normals normalized *************\n");

}
예제 #3
0
파일: fill.c 프로젝트: didier13150/geomorph
void fill_span_from_shadow (hf_type *buffer_in, hf_type *buffer_out, gint xmax, gint ymax,
	hf_type v1, hf_type v2, hf_type filling_value,
	gint y, gint x1, gint x2, gint direction, gint select_mode) {
	
	gint i, mark1, mark2;
	glong value_to_test;
	hf_type output_value;
	gboolean span_end, filled, to_fill;

	filled = FALSE;

//	printf("FILLING y = %d, from x = %d to %d, direction = %d; value: %d\n",y, x1, x2, direction, filling_value);

	if (write_span(y,encode_span(direction,x1,x2))) { 
	
//		printf("FILLING in DOUBLE y = %d, from x = %d to %d, direction = %s; value: %d; mode: %s\n",y, x1, x2, 
//		((direction==0)?"FILL_UP":((direction==1)?"FILL_DOWN":"FILL_BOTH")), filling_value,
//		 ((select_mode==0)?"SELECT_REPLACE":((select_mode==1)?"SELECT_ADD":"SELECT_SUBTRACT")));
		return;
	}
//	Direction: FILL_UP (North), FILL_DOWN (South), FILL_BOTH

	if ( direction==FILL_BOTH ) {

		if ( (y-1) >= 0 )
			fill_span_from_shadow (buffer_in, buffer_out, xmax,ymax, v1,v2,
				filling_value, y, x1, x2, FILL_UP, select_mode);
		if ( (y+1) <= ymax)
			fill_span_from_shadow (buffer_in, buffer_out, xmax,ymax, v1,v2,
				filling_value, y, x1, x2, FILL_DOWN, select_mode);
		return;
	}

	// 1. Calculate direction (FILL_UP or FILL_DOWN)

	if ( direction==FILL_UP )
		y--;
	else
		y++;

	// Test the boundaries in case the function is called
	// at the first recursivity level with direction <> FILL_BOTH
	if ( (y<0) || (y>=ymax) )
		return;

	// 2. Process span

	// 2.1 Backup original span
	mark1 = x1;
	mark2 = x2;

	// 2.2 For x1, if the filling test is true, extend the span as needed

	output_value = *(buffer_out + VECTORIZE(x1,y,xmax));
	if ( (buffer_out==buffer_in) || (select_mode==SELECT_SUBTRACT))
		value_to_test  = *(buffer_in + VECTORIZE(x1,y,xmax));
	else // select_mode==SELECT_ADD / REPLACE || buffer_in != buffer_out
		value_to_test = ((glong) *(buffer_in + VECTORIZE(x1,y,xmax))) + ((glong) output_value);

	if ( test_fill (value_to_test, v1, v2, select_mode, output_value) ) {
	
		// Filling test is true, we extend the span backwards, filling pixels
		for (mark1 = x1-1; mark1>=0; mark1--) {
				
			output_value = *(buffer_out + VECTORIZE(mark1,y,xmax));
			if ( (buffer_out==buffer_in) || (select_mode==SELECT_SUBTRACT))
				value_to_test  = *(buffer_in + VECTORIZE(mark1,y,xmax));
			else // select_mode==SELECT_ADD / REPLACE || buffer_in != buffer_out
				value_to_test = ((glong) *(buffer_in + VECTORIZE(mark1,y,xmax))) + ((glong) output_value);
				
			// Stop when the filling test is false
			if (! test_fill (value_to_test, v1, v2, select_mode, output_value)){
				break;
			}
			else
				*(buffer_out + VECTORIZE(mark1,y,xmax)) = filling_value;
		}
		mark1++;
	}
	else {
	//	If the filling test is false, narrow the span as needed
		while ( mark1<=mark2 ) {
			mark1++;
			
			output_value = 	*(buffer_out + VECTORIZE(mark1,y,xmax));	
			if ( (buffer_out==buffer_in) || (select_mode==SELECT_SUBTRACT))
				value_to_test  = *(buffer_in + VECTORIZE(mark1,y,xmax));
			else // select_mode==SELECT_ADD / REPLACE || buffer_in != buffer_out
				value_to_test = ((glong) *(buffer_in + VECTORIZE(mark1,y,xmax))) + ((glong) output_value);
			
			if ( test_fill (value_to_test, v1, v2, select_mode, output_value) ) 
				break;
		}
	}

	if (mark1>mark2)
		return;

	// Run from mark1 through mark2, filling pixels and calling recursively fill_from_shadow
	// for the current span, each time a discontinuity is encountered

	// At this point, the filling test is true for mark1
	// If mark1 < x1, then the mark1-x1 range is already filled, including x1

	span_end = FALSE;

	// 	We don't need to fill pixels before x1,
 	//	but we need mark1 to specify the shadow for the span on the next y
	i = MAX(x1,mark1);

	// We need to fill the shadow between x1 and mark1, if mark1<(x1-1)
	
	if (mark1<(x1-1))
		fill_span_from_shadow (buffer_in, buffer_out, xmax,ymax, v1,v2, filling_value, y, mark1, x1, ((direction==FILL_UP) ? FILL_DOWN : FILL_UP ), select_mode );
	
	to_fill = TRUE;
	while (i<=mark2) {
//		count++;
//		if (i==384)
//		printf("Count: %d; I: %d; Mark1: %d; Mark2: %d\n",count, i, mark1, mark2);
		if ( to_fill ) {
			*(buffer_out + VECTORIZE(i,y,xmax)) = filling_value;
			if (span_end) // begin a new span
				mark1 = i;
			span_end = FALSE;
			filled = TRUE;
		}
		else {
			// The first time the fill condition is false, a span has ended,
			// we must call "fill_from_shadow" for this span
			// After, we're looking for the beginning of a new span
			if ( (!span_end) && (i>x1)) {
				fill_span_from_shadow (buffer_in, buffer_out, xmax,ymax, v1, v2, filling_value, y, mark1, i-1, direction, select_mode);
				// If the new span boundary exceeds the old one by more than one pixel,
				// we start a filling movement on the other direction
				if ( (i-1) > x2 )
					fill_span_from_shadow (buffer_in, buffer_out, xmax,ymax, v1,v2, filling_value, y, x2+1, i-1,
					((direction==FILL_UP) ? FILL_DOWN : FILL_UP ), select_mode );
				span_end = TRUE;
				filled = TRUE;
			}
			mark1 = i+1;
			if (mark1>=x2)
				break;
		}
		i++;
		if (i==xmax)
			break;

		output_value = *(buffer_out + VECTORIZE(i,y,xmax));
		if ( (buffer_out==buffer_in) || (select_mode==SELECT_SUBTRACT))
			value_to_test  = *(buffer_in + VECTORIZE(i,y,xmax));
		else // select_mode==SELECT_ADD / REPLACE || buffer_in != buffer_out
			value_to_test = ((glong) *(buffer_in + VECTORIZE(i,y,xmax))) + ((glong) output_value);
					
		if ( test_fill (value_to_test, v1, v2, select_mode, output_value) ) {	
			to_fill = TRUE;
			if (i>x2) {
				mark2++; // We extend the span as necessary
				if (mark2==xmax) {
					mark2--;
					break;
				}
			}
		}
		else
			to_fill = FALSE;
	}

	// "Flush" the last span if required

	if (filled && ((i>mark2) || (i==xmax-1))) {
		fill_span_from_shadow (buffer_in, buffer_out, xmax,ymax, v1,v2,
			filling_value, y, mark1, mark2, direction, select_mode);

			// If the new span boundary exceeds the old one by more than one pixel,
			// we start a filling movement on the other direction
		if ( mark2 > x2 )
			fill_span_from_shadow (buffer_in, buffer_out, xmax,ymax, v1,v2, filling_value, y, x2+1, mark2, ((direction==FILL_UP) ? FILL_DOWN : FILL_UP ), select_mode );
	}
}
예제 #4
0
파일: fill.c 프로젝트: didier13150/geomorph
void fill_area_with_mode (hf_type *buffer_in, hf_type *buffer_out, gint xmax, gint ymax,
	hf_type filling_value, hf_type range, gint x, gint y, gint fill_mode, gint select_mode) {

//	Fill area in buffer_out around filling seed (x,y) in buffer_in with filling_value
//	if surrounding pixels value are in a � range
//	1.	Determine first span
//	2.	Fill first span
//	3.	Fill top and bottom spans from shadow

//	buffer_in and buffer_out could be the same (ex. when drawing faults)
//	They would be different, for instance, when buffer_in is used as
//	a select tool

//	2005-04-20 Modified to allow filling up to a maximum

	gint i, x1, x2;
	hf_type v1, v2, value_to_test;	// v1, v2: value to replace (range)

	// Initialize our control structure
	if (xmax<=SPAN_MAX) {
		for (i=0; i<SPAN_LIST_LENGTH; i++)
			span_list[i]=0;
		span_count=0;
	}
		
	// Range & filling_value should be >= 1
	range = MAX(range,1);
	filling_value = MAX(filling_value,MIN_FILLING_VALUE);
	
	if (fill_mode==FILL_MAX) {
		v1 = 0;
		v2 = range;
	}
	else { // fill_mode == FILL_RANGE
		v2 = v1 = *(buffer_in + VECTORIZE(x,y,xmax));
		if (v1 >= range)
			v1 = v1 - range;
		else
			v1 = 0;
		if (range <= (MAX_HF_VALUE - v2))
			v2 = v2 + range;
		else
			v2 = MAX_HF_VALUE;
	}

	*(buffer_out + VECTORIZE(x,y,xmax)) = filling_value;

	// Find the first span
	for (x1=x-1; x1>=0; x1--) {
		value_to_test = *(buffer_in + VECTORIZE(x1,y,xmax));
		if (!test_fill(value_to_test,v1,v2,select_mode,*(buffer_out + VECTORIZE(x1,y,xmax)))) {
			break;
		}
		else
			*(buffer_out + VECTORIZE(x1,y,xmax)) = filling_value;
	} // end for x1
	x1++;

	for (x2=x+1; x2<xmax; x2++) {
		value_to_test = *(buffer_in + VECTORIZE(x2,y,xmax));
		if (!test_fill(value_to_test,v1,v2,select_mode,*(buffer_out + VECTORIZE(x2,y,xmax)))) {
			break;
		}
		else
			*(buffer_out + VECTORIZE(x2,y,xmax)) = filling_value;
	} // end for x2
	x2--;

	fill_span_from_shadow (buffer_in, buffer_out, xmax,ymax, v1,v2,
		filling_value, y, x1, x2, FILL_BOTH, select_mode);
		
//	printf("LAST COUNT: %d\n",span_count);
}
예제 #5
0
파일: draw.c 프로젝트: consultit/geomorph
void map_init (map_struct *map, gint size,
               gint level, gint shape, gdouble spacing) {

    gint x,y, radius, ss;
    gdouble dlevel, offset, ddist, p, maxd = (gdouble) MAX_HF_VALUE;
    shape_type *shape_data=NULL;
    radius = size >> 1;
    // The map size should always be odd
    size = 2*radius+1;
    ss = size * size;
    map->data = (hf_type *) x_realloc (map->data, sizeof(hf_type) * ss, "hf_type (map->data in draw.c)");
    map->tmp = (hf_type *) x_realloc (map->tmp, sizeof(hf_type) * ss, "hf_type (map->tmp in draw.c)");
    map->map_to_use = map->data;
    map->units = (hf_type *) x_realloc (map->units, sizeof(hf_type) * ss, "hf_type (map->units in draw.c)");

    FILL_MAP(map->units,ss,1);

    if (spacing == SPACING_HIGH_QUALITY) {
        dlevel = LEVEL_HQ_SPACING;
    }
    else {
        if (spacing == SPACING_STANDARD_QUALITY)
            dlevel = LEVEL_SQ_SPACING;
        else if (spacing == SPACING_VHIGH_QUALITY)
            dlevel = LEVEL_VHQ_SPACING;
        else
            dlevel = LEVEL_LQ_SPACING;
    }
    if (shape != NO_WAVE_SHAPE) {
        shape_data = shape_type_new(shape, size);
        map->square_symmetry = FALSE;
    }
    else
        map->square_symmetry = TRUE;

    // Position (0,0) in the map is the minimum value
    // We "clamp" all the edges to 0
    // The maximum edge value is at (0,radius) or (radius,0) or (2*radius, radius) or (radius, 2*radius)
    offset = BELLD(CONST_E,2.0,1.5*DIST2(0,0,0,radius),radius);
    if (shape_data) { // square_symmetry == FALSE
        dlevel = ((gdouble) level)*dlevel/(100.0*(gdouble) MAX_HF_VALUE);
        // We intersect the gaussian bell (values from 0.0 to 1.0) with the pen tip shape
        for (x=0; x<size; x++)
            for (y=0; y<size; y++) {
                // Technique #1: gaussian bell on x axis, shape on y axis
                // A basic technique, giving, with sharps tips, straight lines when the stroke curves
                /*				*(map->data+VECTORIZE(x,y,size)) = (hf_type)
                					(dlevel * *(shape_data+y) *
                 					MAX(0.0, BELLD(e,2.0,1.5*ABS(radius-x),radius) - offset) );
                */
                // Technique #2: same as technique #1, but the shape
                // is emphasized only around the center
                // Towards the edges, we average it with a gaussian bell
                // in proportion with the square of the distance
                // Increasing the base to 10.0 shortens the shape
                // so that even with sharp tips, straight lines are invisible in stroke curves
                p = MAX(0.0, BELLD(10.0,2.0,1.5*ABS(radius-x),radius) - offset);
                *(map->data+VECTORIZE(x,y,size)) = (hf_type) (dlevel *
                                                   (p * *(shape_data+y) + (1.0-p) * MAX(0.0, BELLD(CONST_E,2.0,1.5*ABS(radius-y),radius) - offset) * maxd ) *
                                                   MAX(0.0, BELLD(CONST_E,2.0,1.5*ABS(radius-x),radius) - offset) );

            }
    }
    else {
        // Level is relative (50 means 50%)
        dlevel = ((gdouble) level)*dlevel/100.0;
        for (x=0; x<(radius+1); x++)
            for (y=0; y<(radius+1); y++) {
                ddist = (gdouble) DIST2(0,0,x,y);
                if (ddist >= radius)
                    *(map->data+VECTORIZE(radius-x,radius-y,radius+1)) = 0;
                else
                    *(map->data+VECTORIZE(radius-x,radius-y,radius+1)) =
                        (hf_type) (dlevel * MAX(0.0, BELLD(CONST_E,2.0,1.5*ddist,radius) - offset) );
//						 0x04FF; // TEST
            }
    }
    map->radius = radius;
    if (map->dr_buf)
        draw_buf_free(map->dr_buf);
    map->dr_buf = draw_buf_new (MULT_SIZE*size/DIV_SIZE);
    draw_buf_init (map, spacing);
    if (shape_data)
        free(shape_data);
}