Example #1
0
    void init()
    {
        const char* svgFile = "butterfly.svg";
        SVGPath* plist;
        plist = svgParseFromFile(svgFile);
        SVGPath* cur = plist;

        while (cur && cur->hasFill)
        {
            vg::Path path = vg::createPath(cur->numCmd, cur->cmd, cur->numData, cur->data);
            mPaths.push_back(path);

            vg::Paint paint = vg::createSolidPaint(cur->fillColor);
            mPaints.push_back(paint);

            cur = cur->next;
        }

        svgDelete(plist);

        mAAEnabled = ui::checkBoxAdd(25.0f, 83.0f, 41.0f, 99.0f, FALSE);

        gfx::gpu_timer_init(&gpuTimer);

        fwk::setCaption("GPU accelerated SVG rendering");
    }
Example #2
0
Game::Game(const std::string &level, float near, float far, float fov) :
    camera(fov, resolution.x/(float)resolution.y, near, far)
    , music(nullptr)
    , current_mode(MODE_READY)
{
    composition = new RenderTarget(resolution, GL_RGB8, RenderTarget::DEPTH_BUFFER | RenderTarget::DOUBLE_BUFFER);
    geometry = new RenderTarget(resolution, GL_RGB8, RenderTarget::DEPTH_BUFFER);

    printf("Loading level %s\n", level.c_str());

    std::string base_dir = PATH_BASE "data/levels/" + level;

    Config config = Config::parse(base_dir + "/level.cfg");

    //Read config:
    start_position = config["/player/start_position"]->as_float();
    sky_color = config["/environment/sky_color"]->as_color();
    static const glm::vec2 terrain_scale = config["/environment/terrain/scale"]->as_vec2();
    static const float fog_intensity = config["/environment/fog_intensity"]->as_float();
    camera_offset = config["/player/camera/offset"]->as_vec3();
    look_at_offset = config["/player/camera/look_at_offset"]->as_float();
    movement_speed = config["/player/speed/normal"]->as_float();
    brake_movement_speed = config["/player/speed/brake"]->as_float();

    spawn_area_start = config["/game/spawn_area/start"]->as_float();
    spawn_area_end = config["/game/spawn_area/end"]->as_float();
    spawn_area_size = spawn_area_end - spawn_area_start;
    spawn_distance = config["/game/spawn_area/distance"]->as_float();
    despawn_distance = config["/game/spawn_area/despawn_distance"]->as_float();
    difficulty_increase = config["/game/difficulty_increase"]->as_float();

    static const Shader::fog_t fog = { glm::vec4(sky_color.to_vec3(), 1.f), fog_intensity };
    Shader::upload_fog(fog);

    TextureArray * colors = TextureArray::from_filename( (base_dir +"/color0.png").c_str(),
                            (base_dir + "/color1.png").c_str(), nullptr);
    TextureArray *  normals = TextureArray::from_filename( (base_dir +"/normal0.png").c_str(),
                              (base_dir + "/normal1.png").c_str(), nullptr);

    terrain = new Terrain(base_dir + "/map.png", terrain_scale.x, terrain_scale.y, colors, normals);

    Data * path_file = Data::open(base_dir + "/path.svg");

    SVGPath * svg_path = svgParse((char*) path_file->data());

    delete path_file;

    std::vector<glm::vec3> path_nodes;

    for(int i=0; i< svg_path->npts; ++i) {
        path_nodes.push_back(glm::vec3(
                                 svg_path->pts[i*2],
                                 0,
                                 svg_path->pts[i*2 + 1]
                             ) * terrain_scale.x);
    }

    svgDelete(svg_path);

    Path::optimize_vector(path_nodes);

    // Gets max elevation for a radius around a point to avoid the rails cliping into the ground.
    for(glm::vec3 &v : path_nodes) {
        v.y = glm::max(glm::max(glm::max(terrain->height_at(v.x+1.5f, v.z),terrain->height_at(v.x-1.5f, v.z)),terrain->height_at(v.x, v.z+1.5f)),terrain->height_at(v.x, v.z-1.5f)) + 0.2f;
    }

    path = new Path(path_nodes, false);

    rails = new Rails(path, 1.f);
    rail_texture = Texture2D::from_filename(PATH_BASE "data/textures/rails.png");
    rail_material.texture = rail_texture;

    //Setup player:
    player.canon_offset = config["/player/canon_offset"]->as_vec3();
    player.canon_length = config["/player/canon_length"]->as_float();
    //Configure lights:

    lights.ambient_intensity() = config["/environment/light/ambient"]->as_vec3();
    lights.num_lights() = 1;

    lights.lights[0]->intensity = config["/environment/light/sunlight"]->as_vec3();
    lights.lights[0]->type = MovableLight::DIRECTIONAL_LIGHT;

    //Load enemies:
    EnemyTemplate::init(Config::parse(base_dir + "/enemies.cfg"), this);

//Set up camera:

    update_camera();

//Create particle systems:

    wind_velocity = config["/environment/wind_velocity"]->as_vec3();
    gravity = glm::vec4(config["/environment/gravity"]->as_vec3(), 1.f);

    particle_shader = Shader::create_shader("particles");
    passthru = Shader::create_shader("passthru");

    static const Config particle_config = Config::parse(base_dir + "/particles.cfg");

    static const float canon_inner_radius = particle_config["/particles/spawn_radius"]->as_float();

    particle_textures = TextureArray::from_filename( PATH_BASE "data/textures/smoke.png",
                        PATH_BASE "data/textures/fog.png",
                        PATH_BASE "data/textures/particle.png",
                        PATH_BASE "data/textures/fire1.png",
                        PATH_BASE "data/textures/fire2.png",
                        PATH_BASE "data/textures/fire3.png",
                        nullptr);

    static const int max_attack_particles = particle_config["/particles/max_attack_particles"]->as_int();
    static const int max_smoke_particles = particle_config["/particles/max_smoke_particles"]->as_int();
    static const int max_dust_particles = particle_config["/particles/max_dust_particles"]->as_int();
    static const int max_explosion_particles = particle_config["/particles/max_explosion_particles"]->as_int();

    attack_particles = new HittingParticles(max_attack_particles, particle_textures, EnemyTemplate::max_num_enemies, false);
    attack_particles->config.gravity = gravity;
    system_configs.push_back(&(attack_particles->config));
    attack_particles->config.spawn_area = glm::vec4(0.f, 0.f, 0.f, canon_inner_radius);

    for(auto &p : particle_types) {
        p.config = attack_particles->config; //Get reasonable defaults
        system_configs.push_back(&(p.config));
    }

    read_particle_config(particle_config["/particles/light"], particle_types[LIGHT_PARTICLES].config);
    particle_types[LIGHT_PARTICLES].count = particle_config["/particles/light/count"]->as_int();
    particle_types[LIGHT_PARTICLES].spawn_speed = particle_config["/particles/light/spawn_speed"]->as_float();
    particle_types[LIGHT_PARTICLES].damage = particle_config["/particles/light/damage"]->as_float();

    read_particle_config(particle_config["/particles/medium"], particle_types[MEDIUM_PARTICLES].config);
    particle_types[MEDIUM_PARTICLES].count = particle_config["/particles/medium/count"]->as_int();
    particle_types[MEDIUM_PARTICLES].spawn_speed = particle_config["/particles/medium/spawn_speed"]->as_float();
    particle_types[MEDIUM_PARTICLES].damage = particle_config["/particles/medium/damage"]->as_float();

    read_particle_config(particle_config["/particles/heavy"], particle_types[HEAVY_PARTICLES].config);
    particle_types[HEAVY_PARTICLES].count = particle_config["/particles/heavy/count"]->as_int();
    particle_types[HEAVY_PARTICLES].spawn_speed = particle_config["/particles/heavy/spawn_speed"]->as_float();
    particle_types[HEAVY_PARTICLES].damage = particle_config["/particles/heavy/damage"]->as_float();

    //Smoke:
    smoke = new ParticleSystem(max_smoke_particles, particle_textures, false);
    smoke->config.gravity = gravity;
    system_configs.push_back(&(smoke->config));
    smoke->config.spawn_area = glm::vec4(0.f, 0.f, 0.f, canon_inner_radius * 2.0);

    read_particle_config(particle_config["/particles/smoke"], smoke->config);
    smoke_count = particle_config["/particles/smoke/count"]->as_int();
    smoke_spawn_speed = particle_config["/particles/smoke/spawn_speed"]->as_float();

    //Dust:
    dust = new ParticleSystem(max_dust_particles, particle_textures, true);

    read_particle_config(particle_config["/particles/dust"], dust->config);

    dust->config.gravity = gravity;
    system_configs.push_back(&(dust->config));
    dust->config.spawn_area = particle_config["/particles/dust/spawn_area"]->as_vec4();
    dust->config.avg_spawn_velocity = glm::vec4(particle_config["/particles/dust/avg_spawn_velocity"]->as_vec3(), 0);
    dust->avg_spawn_rate = particle_config["/particles/dust/avg_spawn_rate"]->as_float();
    dust->spawn_rate_var = particle_config["/particles/dust/spawn_rate_var"]->as_float();
    dust_spawn_ahead = particle_config["/particles/dust/spawn_ahead"]->as_float();
    half_dust_spawn_area = glm::vec3(dust->config.spawn_area.x, dust->config.spawn_area.y, dust->config.spawn_area.z) / 2.f;

    dust->config.spawn_position = glm::vec4(player.position() - half_dust_spawn_area, 1.f);
    dust->update_config();
    dust->spawn(dust->avg_spawn_rate * 5.0);
    dust->config.spawn_position += glm::vec4(path->at(player.path_position() + dust_spawn_ahead / 2.f), 0.f);
    dust->spawn(dust->avg_spawn_rate * 5.0);

    //Explosions
    explosions = new ParticleSystem(max_explosion_particles, particle_textures, false);

    hit_explosion = explosions->config;
    system_configs.push_back(&(hit_explosion));
    kill_explosion = explosions->config;
    system_configs.push_back(&(kill_explosion));
    read_particle_config(particle_config["/particles/hit_explosion"], hit_explosion);
    read_particle_config(particle_config["/particles/kill_explosion"], kill_explosion);

    explosions->config.gravity = gravity;
    system_configs.push_back(&(explosions->config));
    hit_explosion_count = particle_config["/particles/hit_explosion/count"]->as_int();
    kill_explosion_count = particle_config["/particles/kill_explosion/count"]->as_int();
    kill_explosion.spawn_area = particle_config["/particles/kill_explosion/spawn_area"]->as_vec4();
    kill_explosion.avg_spawn_velocity = glm::vec4(particle_config["/particles/kill_explosion/avg_spawn_velocity"]->as_vec3(), 0);
    hit_explosion.spawn_area = particle_config["/particles/hit_explosion/spawn_area"]->as_vec4();
    hit_explosion.avg_spawn_velocity = glm::vec4(particle_config["/particles/hit_explosion/avg_spawn_velocity"]->as_vec3(), 0);

    update_wind_velocity();
    //Setup HUD




    hud_scale = glm::vec2(resolution.x / 800.f, resolution.y / 600.f);
    hud_static_elements_tex = Texture2D::from_filename(PATH_BASE "/data/textures/hudStatic.png");
    fullscreen_quad = new Quad();
    fullscreen_quad->set_scale(glm::vec3(resolution.x,resolution.y,0));

    hud_lightpos =  glm::vec2(594,490) * hud_scale;
    hud_mediumpos = glm::vec2(644,490) * hud_scale;
    hud_heavypos =  glm::vec2(700,490) * hud_scale;

    hud_choice_tex = Texture2D::from_filename(PATH_BASE "/data/textures/weap_select.png");
    hud_choice_quad = new Quad();
    hud_choice_quad->set_scale(glm::vec3(97,92,0) * glm::vec3(hud_scale , 0));

    hud_break_tex = Texture2D::from_filename(PATH_BASE "/data/textures/breaks_ready.png");
    hud_break_quad = new Quad();
    hud_break_quad->set_scale(glm::vec3(190, 25, 0) * glm::vec3(hud_scale, 0));
    hud_break_quad->set_position(glm::vec3(glm::vec2(30, 530) * hud_scale, 0.f));

    life_text.set_color(hud_font_color);
    life_text.set_scale(20.0 * hud_scale.x);
    life_text.set_position(glm::vec3(glm::vec2(26.f, 44.5f) * hud_scale, 0.f));

    //Highscore stuff:
    highscore = new Highscore(base_dir + "/highscore", NUM_HIGHSCORE_ENTRIES);
    float hs_scale = 40.f;
    glm::vec2 higscore_base = glm::vec2(735.f, 85.f);
    int i=0;
    for(Text &t : highscore_entries) {
        t.set_position(glm::vec3( (higscore_base + glm::vec2(0.f, (i++)*hs_scale)) * hud_scale, 0.f));
        t.set_scale(hs_scale);
        t.set_text("");
        t.set_alignment(Text::RIGHT_ALIGNED);
    }

    //Textures
    game_over_texture = Texture2D::from_filename(PATH_BASE "/data/textures/gameover.png");
    startscreen_texture = Texture2D::from_filename(PATH_BASE "/data/textures/start_screen.png");
}
Example #3
0
int main(int argc, char *argv[])
{
	GLFWwindow* window;
	const GLFWvidmode* mode;
	int width,height,i,j;
	struct SVGPath* bg;
	struct SVGPath* fg;
	struct SVGPath* it;
	float bounds[4],view[4],cx,cy,w,offx,offy;
	float t = 0.0f, pt = 0.0f;
	TESSalloc ma;
	TESStesselator* tess = 0;
	const int nvp = 6;
	unsigned char* vflags = 0;
	int nvflags = 0;
#ifdef USE_POOL
	struct MemPool pool;
	unsigned char mem[1024*1024];
#else
	int allocated = 0;
#endif
	TESS_NOTUSED(argc);
	TESS_NOTUSED(argv);

	if (!glfwInit()) {
		printf("Failed to init GLFW.");
		return -1;
	}

	printf("loading...\n");
	// Load assets
	bg = svgParseFromFile("../Bin/bg.svg");
	if (!bg) return -1;
	fg = svgParseFromFile("../Bin/fg.svg");
	if (!fg) return -1;

	printf("go...\n");
	
	// Flip y
	for (it = bg; it != NULL; it = it->next)
		for (i = 0; i < it->npts; ++i)
			it->pts[i*2+1] = -it->pts[i*2+1];
	for (it = fg; it != NULL; it = it->next)
		for (i = 0; i < it->npts; ++i)
			it->pts[i*2+1] = -it->pts[i*2+1];

	// Find FG bounds and center.
	bounds[0] = bounds[2] = fg->pts[0];
	bounds[1] = bounds[3] = fg->pts[1];
	for (it = fg; it != NULL; it = it->next)
	{
		for (i = 0; i < it->npts; ++i)
		{
			const float x = it->pts[i*2];
			const float y = it->pts[i*2+1];
			if (x < bounds[0]) bounds[0] = x;
			if (y < bounds[1]) bounds[1] = y;
			if (x > bounds[2]) bounds[2] = x;
			if (y > bounds[3]) bounds[3] = y;
		}
	}
	cx = (bounds[0]+bounds[2])/2;
	cy = (bounds[1]+bounds[3])/2;
	for (it = fg; it != NULL; it = it->next)
	{
		for (i = 0; i < it->npts; ++i)
		{
			it->pts[i*2] -= cx;
			it->pts[i*2+1] -= cy;
		}
	}
			
	// Find BG bounds.
	bounds[0] = bounds[2] = bg->pts[0];
	bounds[1] = bounds[3] = bg->pts[1];
	for (it = bg; it != NULL; it = it->next)
	{
		for (i = 0; i < it->npts; ++i)
		{
			const float x = it->pts[i*2];
			const float y = it->pts[i*2+1];
			if (x < bounds[0]) bounds[0] = x;
			if (y < bounds[1]) bounds[1] = y;
			if (x > bounds[2]) bounds[2] = x;
			if (y > bounds[3]) bounds[3] = y;
		}
	}
		
#ifdef USE_POOL

	pool.size = 0;
	pool.cap = sizeof(mem);
	pool.buf = mem;
	memset(&ma, 0, sizeof(ma));
	ma.memalloc = poolAlloc;
	ma.memfree = poolFree;
	ma.userData = (void*)&pool;
	ma.extraVertices = 256; // realloc not provided, allow 256 extra vertices.

#else

	memset(&ma, 0, sizeof(ma));
	ma.memalloc = stdAlloc;
	ma.memfree = stdFree;
	ma.userData = (void*)&allocated;
	ma.extraVertices = 256; // realloc not provided, allow 256 extra vertices.

	tess = tessNewTess(&ma);
	if (!tess)
		return -1;

	// Offset the foreground shape to center of the bg.
	offx = (bounds[2]+bounds[0])/2;
	offy = (bounds[3]+bounds[1])/2;
	for (it = fg; it != NULL; it = it->next)
	{
		for (i = 0; i < it->npts; ++i)
		{
			it->pts[i*2] += offx;
			it->pts[i*2+1] += offy;
		}
	}
	
	// Add contours.
	for (it = bg; it != NULL; it = it->next)
		tessAddContour(tess, 2, it->pts, sizeof(float)*2, it->npts);
	for (it = fg; it != NULL; it = it->next)
		tessAddContour(tess, 2, it->pts, sizeof(float)*2, it->npts);
	if (!tessTesselate(tess, TESS_WINDING_POSITIVE, TESS_POLYGONS, nvp, 2, 0))
		return -1;
	printf("Memory used: %.1f kB\n", allocated/1024.0f);
	
#endif
	
	mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
	width = mode->width - 40;
	height = mode->height - 80;
    window = glfwCreateWindow(width, height, "Libtess2 Demo", NULL, NULL);
	if (!window) {
		glfwTerminate();
		return -1;
	}

	glfwSetKeyCallback(window, key);
	glfwMakeContextCurrent(window);

	// Adjust bounds so that we get nice view of the bg.
	cx = (bounds[0]+bounds[2])/2;
	cy = (bounds[3]+bounds[1])/2;
	w = (bounds[2]-bounds[0])/2;
	view[0] = cx - w*1.2f;
	view[2] = cx + w*1.2f;
	view[1] = cy - w*1.2f*(float)height/(float)width;
	view[3] = cy + w*1.2f*(float)height/(float)width;
		
	glfwSetTime(0);

	while (!glfwWindowShouldClose(window))
	{
		float ct = (float)glfwGetTime();
		if (run) t += ct - pt;
		pt = ct;
		
		// Update and render
		glViewport(0, 0, width, height);
		glClearColor(0.3f, 0.3f, 0.32f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		glDisable(GL_TEXTURE_2D);
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		glOrtho(view[0],view[2],view[1],view[3],-1,1);
		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		glDisable(GL_DEPTH_TEST);
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

#ifdef USE_POOL
		pool.size = 0; // reset pool
		tess = tessNewTess(&ma);
		if (tess)
		{
			offx = (view[2]+view[0])/2 + sinf(t) * (view[2]-view[0])/2;
			offy = (view[3]+view[1])/2 + cosf(t*3.13f) * (view[3]-view[1])/6;
			
			for (it = fg; it != NULL; it = it->next)
			{
				for (i = 0; i < it->npts; ++i)
				{
					it->pts[i*2] += offx;
					it->pts[i*2+1] += offy;
				}
			}

			for (it = bg; it != NULL; it = it->next)
				tessAddContour(tess, 2, it->pts, sizeof(float)*2, it->npts);
			for (it = fg; it != NULL; it = it->next)
				tessAddContour(tess, 2, it->pts, sizeof(float)*2, it->npts);

			for (it = fg; it != NULL; it = it->next)
			{
				for (i = 0; i < it->npts; ++i)
				{
					it->pts[i*2] -= offx;
					it->pts[i*2+1] -= offy;
				}
			}

			// First combine contours and then triangulate, this removes unnecessary inner vertices.
			if (tessTesselate(tess, TESS_WINDING_POSITIVE, TESS_BOUNDARY_CONTOURS, 0, 0, 0))
			{
				const float* verts = tessGetVertices(tess);
				const int* vinds = tessGetVertexIndices(tess);
				const int nverts = tessGetVertexCount(tess);
				const int* elems = tessGetElements(tess);
				const int nelems = tessGetElementCount(tess);

				if (nverts > nvflags)
				{
					if (vflags)
						free(vflags);
					nvflags = nverts;
					vflags = (unsigned char*)malloc(sizeof(unsigned char)*nvflags);
				}
				
				if (vflags)
				{
					// Vertex indices describe the order the indices were added and can be used
					// to map the tesselator output to input. Vertices marked as TESS_UNDEF
					// are the ones that were created at the intersection of segments.
					// That is, if vflags is set it means that the vertex comes from intersegment.
					for (i = 0; i < nverts; ++i)
						vflags[i] = vinds[i] == TESS_UNDEF ? 1 : 0;
				}
				
				for (i = 0; i < nelems; ++i)
				{
					int b = elems[i*2];
					int n = elems[i*2+1];
					tessAddContour(tess, 2, &verts[b*2], sizeof(float)*2, n);
				}
				if (!tessTesselate(tess, TESS_WINDING_POSITIVE, TESS_POLYGONS, nvp, 2, 0))
					tess = 0;
			}
			else
				tess = 0;				
		}
#endif		

		// Draw tesselated pieces.
		if (tess)
		{
			const float* verts = tessGetVertices(tess);
			const int* vinds = tessGetVertexIndices(tess);
			const int* elems = tessGetElements(tess);
			const int nverts = tessGetVertexCount(tess);
			const int nelems = tessGetElementCount(tess);
			
			// Draw polygons.
			glColor4ub(255,255,255,128);
			for (i = 0; i < nelems; ++i)
			{
				const int* p = &elems[i*nvp];
				glBegin(GL_TRIANGLE_FAN);
				for (j = 0; j < nvp && p[j] != TESS_UNDEF; ++j)
					glVertex2f(verts[p[j]*2], verts[p[j]*2+1]);
				glEnd();
			}
			
			glColor4ub(0,0,0,16);
			for (i = 0; i < nelems; ++i)
			{
				const int* p = &elems[i*nvp];
				glBegin(GL_LINE_LOOP);
				for (j = 0; j < nvp && p[j] != TESS_UNDEF; ++j)
					glVertex2f(verts[p[j]*2], verts[p[j]*2+1]);
				glEnd();
			}
			
			glColor4ub(0,0,0,128);
			glPointSize(3.0f);
			glBegin(GL_POINTS);
			for (i = 0; i < nverts; ++i)
			{
				if (vflags && vflags[vinds[i]])
					glColor4ub(255,0,0,192);
				else
					glColor4ub(0,0,0,128);
				glVertex2f(verts[i*2], verts[i*2+1]);
			}
			glEnd();
			glPointSize(1.0f);
		}
		
		glEnable(GL_DEPTH_TEST);
		glfwSwapBuffers(window);
		glfwPollEvents();
	}
	
	if (tess) tessDeleteTess(tess);
	
	if (vflags)
		free(vflags);
	
	svgDelete(bg);	
	svgDelete(fg);	

	glfwTerminate();
	return 0;
}