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")); }