Пример #1
0
void gun_shell::check_collision_voxel(ship& s, const vector3f& oldrelpos, const vector3f& newrelpos)
{
	// positions are relative to bbox of s.
	matrix4f obj2voxel = s.get_model().get_base_mesh_transformation().inverse();
	vector3f oldvoxpos = obj2voxel * oldrelpos, newvoxpos = obj2voxel * newrelpos;
	vector3f diffvoxpos = newvoxpos - oldvoxpos;
	// now iterate in 8 steps between oldvoxpos to newvoxpos,
	// transform both to voxel coordinates (0...N)
	// and determine voxel number by pos.
	// if coordinate is invalid, no hit, otherwise check voxel state (volume > 0.25 or similar)
	// if the voxel is filled.
	vector3f voxel_size_rcp = s.get_model().get_voxel_size().rcp();
	const vector3i& vres = s.get_model().get_voxel_resolution();
	vector3i vidxmax = vres - vector3i(1, 1, 1);
	vector3f voxel_pos_trans = vector3f(vres) * 0.5f;
	int lastvn = -1;
	log_debug("check collision voxel");
	for (unsigned k = 0; k <= 10; ++k) {
		float kf = k/10.0f;
		vector3f voxpos = oldvoxpos + diffvoxpos * kf;
		vector3i v = vector3i(voxpos.coeff_mul(voxel_size_rcp) + voxel_pos_trans);
		v = v.max(vector3i(0,0,0)).min(vidxmax);
		int vn = (v.z * vres.y + v.y)*vres.x + v.x;
		if (vn != lastvn) {
			lastvn = vn;
			log_debug("voxel hit k="<<k<<" voxpos="<<voxpos<<" v="<<v<<" vn="<<vn);
			const model::voxel* vox = s.get_model().get_voxel_by_pos(v);
			if (vox) {
				// we hit a part of the object!
				log_debug("..... Object hit! .....");
				// first compute exact real word position of impact
				vector3 impactpos = s.get_pos()
					+ s.get_orientation().rotate(s.get_model().
						get_base_mesh_transformation() * voxpos);
				// move gun shell pos to hit position to
				// let the explosion be at right position
				position = impactpos;
				log_debug("Hit object at real world pos " << impactpos);
				log_debug("that is relative: " << s.get_pos()-impactpos);
				// now damage the ship
				if (s.damage(impactpos, int(damage_amount))) { // fixme, crude
					gm.ship_sunk(&s);
				} else {
					s.ignite();
				}
#if 0
				//spawn some location marker object for testing
				//at exact impact position
				gm.spawn_particle(new marker_particle(impactpos));
#endif
				gm.add_event(new event_shell_explosion(get_pos()));
				kill(); // grenade is used and dead
				return; // no more checks
			}
		}
	}
}
////////////////////////////////////////////////////////////
// Constructor
////////////////////////////////////////////////////////////
static SQInteger sfVector3f_constructor(HSQUIRRELVM v)
{
    if (sq_gettop(v) == 1) {
        sf::Vector3f* instance = new sf::Vector3f();
        Sqrat::DefaultAllocator<sf::Vector3f>::SetInstance(v, 1, instance);
        return 0;
    } else if (sq_gettop(v) == 2) {
        Sqrat::Var<const sf::Vector3f&> copy(v, 2);
        if (!Sqrat::Error::Occurred(v)) {
            sf::Vector3f* instance = new sf::Vector3f(copy.value);
            Sqrat::DefaultAllocator<sf::Vector3f>::SetInstance(v, 1, instance);
            return 0;
        }
        Sqrat::Error::Clear(v);
        Sqrat::Var<const sf::Vector3i&> vector3i(v, 2);
        if (!Sqrat::Error::Occurred(v)) {
            sf::Vector3f* instance = new sf::Vector3f(vector3i.value);
            Sqrat::DefaultAllocator<sf::Vector3f>::SetInstance(v, 1, instance);
            return 0;
        }
        Sqrat::Error::Clear(v);
        return sq_throwerror(v, Sqrat::FormatTypeError(v, 2, Sqrat::ClassType<sf::Vector3i>::ClassName() + _SC("|") + Sqrat::ClassType<sf::Vector3f>::ClassName()).c_str());
    } else if (sq_gettop(v) == 4) {
        Sqrat::Var<float> x(v, 2);
        Sqrat::Var<float> y(v, 3);
        Sqrat::Var<float> z(v, 4);
        if (!Sqrat::Error::Occurred(v)) {
            sf::Vector3f* instance = new sf::Vector3f(x.value, y.value, z.value);
            Sqrat::DefaultAllocator<sf::Vector3f>::SetInstance(v, 1, instance);
            return 0;
        }
        return sq_throwerror(v, Sqrat::Error::Message(v).c_str());
    }
    return sq_throwerror(v, _SC("wrong number of parameters"));
}