Esempio n. 1
0
void _serialize(MMLObject* mml, DArray* out, NodeIdx node, uint padding) {
	assert(mml);
	assert(out);

	MMLNode* node_ptr = mml_get_nodeptr(mml, node);
	
	uint i = padding;
	while(i--) {
		darray_append(out, " ");
	}	

	const char* name = mml_get_str(mml, node_ptr->name_start);
	const char* value = mml_get_str(mml, node_ptr->value_start);

	darray_append_multi(out, "( ", 2);
	mml_insert_escapes(name, out);
	darray_append(out, " ");
	mml_insert_escapes(value, out);

	if(node_ptr->first_child_idx == 0) {
		// node has no children, print it on a single line
		darray_append_multi(out, " )\n", 3);
		return;
	}
	else {
		// node has children, recurse
		darray_append(out, "\n");
		NodeIdx child = node_ptr->first_child_idx;
		while(child) {
			_serialize(mml, out, child, padding + 4);
			child = mml_get_next(mml, child);
		}	
		i = padding;
		while(i--) {
			darray_append(out, " ");
		}	
		darray_append_multi(out, ")\n", 2);
	}	
}	
Esempio n. 2
0
DArray _gen_navpoints(DArray geometry, DArray platforms) {
	DArray points = darray_create(sizeof(Vector2), 0);
	darray_append_multi(&points, platforms.data, platforms.size);

	uint fail_count = 0;
	do {
		Vector2 navpoint = vec2(rand_float_range(0.0f, SCREEN_WIDTH),
			rand_float_range(0.0f, SCREEN_HEIGHT));

		float wdist = ai_wall_distance(navpoint, geometry);
		float pdist = _point_distance(navpoint, points);

		if(wdist >= min_wall_distance && pdist >= min_point_distance) {
			darray_append(&points, (void*)&navpoint);
			fail_count = 0;
		}
		else {
			fail_count++;
		}	
	} while(fail_count < 1200);	
	return points;
}	
Esempio n. 3
0
NavMesh ai_precalc_navmesh(DArray geometry, DArray platforms,
	float width, float height) {
	NavMesh res;

	ai_precalc_bounds(width, height);

	DArray navpoints = _gen_navpoints(geometry, platforms);
	DArray edges = _gen_edges(navpoints, geometry);

	Vector2* navpoints_v = DARRAY_DATA_PTR(navpoints, Vector2);
	Edge* edges_e = DARRAY_DATA_PTR(edges, Edge);

	uint n = navpoints.size;

	res.n_nodes = n;
	res.navpoints = MEM_ALLOC(sizeof(Vector2) * n);
	res.neighbour_count = MEM_ALLOC(sizeof(uint) * n);
	res.neighbours_start = MEM_ALLOC(sizeof(uint) * n);
	float* adjacency = MEM_ALLOC(sizeof(float) * n*n);
	res.distance = MEM_ALLOC(sizeof(float) * n*n);
	res.radius = MEM_ALLOC(sizeof(float) * n);
	res.nn_grid_count = MEM_ALLOC(sizeof(uint) * nn_grid_cells);
	res.nn_grid_start = MEM_ALLOC(sizeof(uint) * nn_grid_cells);

	memset(res.neighbour_count, 0, sizeof(uint) * n);
	memset(adjacency, 0, sizeof(float) * n*n);
	memset(res.distance, 0, sizeof(float) * n*n);
	memset(res.nn_grid_count, 0, sizeof(uint) * nn_grid_cells);
	memset(res.nn_grid_start, 0, sizeof(uint) * nn_grid_cells);
		
	for(uint i = 0; i < navpoints.size; ++i) {
		res.navpoints[i] = 	navpoints_v[i];
		res.radius[i] = ai_wall_distance(navpoints_v[i], geometry);
	}

	for(uint i = 0; i < edges.size; ++i) {
		float dist = vec2_length(vec2_sub(
			navpoints_v[edges_e[i].v1], navpoints_v[edges_e[i].v2]));
		adjacency[IDX_2D(edges_e[i].v1, edges_e[i].v2, n)] = dist;
		adjacency[IDX_2D(edges_e[i].v2, edges_e[i].v1, n)] = dist;
		res.neighbour_count[edges_e[i].v1]++;
		res.neighbour_count[edges_e[i].v2]++;
	}

	// Pracalc node neighbour lists
	uint total_neighbours = res.neighbour_count[0];
	res.neighbours_start[0] = 0;
	for(uint i = 1; i < n; ++i) {
		res.neighbours_start[i] = 
			res.neighbours_start[i-1] + res.neighbour_count[i-1];
		total_neighbours +=	res.neighbour_count[i];
	}		
	res.neighbours = MEM_ALLOC(sizeof(uint) * total_neighbours);
	for(uint i = 0; i < n; ++i) {
		uint idx = res.neighbours_start[i];
		for(uint j = 0; j < n; ++j) {
			if(adjacency[IDX_2D(i, j, n)] > 0.0f)
				res.neighbours[idx++] = j;
		}
		assert(idx == res.neighbours_start[i] + res.neighbour_count[i]);
	}

	memcpy(res.distance, adjacency, sizeof(float) * n*n);
	// Change zero distances to infinities
	for(uint i = 0; i < n*n; ++i)
		if(res.distance[i] == 0.0f)
			res.distance[i] = 10000000.0f;

	// Floyd-Warshall
	for(uint i = 0; i < n; ++i)
		for(uint j = 0; j < n; ++j)
			for(uint k = 0; k < n; ++k)
				res.distance[IDX_2D(j, k, n)] = MIN(res.distance[IDX_2D(j, k, n)],
					res.distance[IDX_2D(j, i, n)]+res.distance[IDX_2D(i, k, n)]);

	// Precalc nearest-navpoint grid
	DArray grid_cell;
	DArray nn_grid;

	res.nn_grid_start[0] = 0;

	nn_grid = darray_create(sizeof(uint), 0);
	for(uint i = 0; i < nn_grid_cells; ++i) {
		grid_cell = darray_create(sizeof(uint), 0);
		
		for(uint j = 0; j < nn_samples; ++j) {
			Vector2 p = _rand_point_in_nn_grid_cell(i);
			uint nearest_navpoint = _nearest_navpoint(p, geometry, navpoints);
			if(nearest_navpoint >= n) // Point was inside wall, skip
				continue;

			bool unique = true;

			uint* existing_navpoints = DARRAY_DATA_PTR(grid_cell, uint);
			for(uint k = 0; k < grid_cell.size; ++k)
				if(existing_navpoints[k] == nearest_navpoint)
					unique = false;
			
			if(unique)
				darray_append(&grid_cell, &nearest_navpoint);
		}

		res.nn_grid_count[i] = grid_cell.size;
		if(i > 0)
			res.nn_grid_start[i] = 
				res.nn_grid_start[i-1] + res.nn_grid_count[i-1];
		
		uint* cell_navpoints = DARRAY_DATA_PTR(grid_cell, uint);
		darray_append_multi(&nn_grid, cell_navpoints, grid_cell.size);
		darray_free(&grid_cell);
	}	

	// Hack, works properly as long as darray_free only does
	// MEM_FREE(darray.data);
	res.nn_grid = (uint*)nn_grid.data;

	darray_free(&navpoints);
	darray_free(&edges);
	MEM_FREE(adjacency);

	_precalc_vis(geometry, &res);

	return res;
}