#ifndef RC_GFX_CORE_H_INCLUDED #define RC_GFX_CORE_H_INCLUDED #ifdef RC_ANDROID #include "SDL.h" #include "btBulletDynamicsCommon.h" #include "BulletSoftBody/btSoftRigidDynamicsWorld.h" #else #include #include #include #endif // _IRR_ANDROID_PLATFORM_ #include #include #include #include #include #include #include #include #include "gui_freetype_font.h" #include "rc_utf8.h" #include "camera.h" #include #include "rc_sprite2D.h" #include #ifdef RC_ANDROID #include "an8parser.h" #else #include #endif using namespace irr; using namespace core; using namespace video; using namespace scene; #define MAX_JOYSTICKS 32 #define MAX_FINGERS 10 #define MAX_ACCELS 32 #define MAX_GYROS 32 SDL_Joystick * rc_joystick[MAX_JOYSTICKS]; int rc_joy_axis[MAX_JOYSTICKS][100]; int rc_numJoysticks = 0; int rc_joybutton[MAX_JOYSTICKS][100]; SDL_JoystickID rc_joyID[MAX_JOYSTICKS]; SDL_Joystick * tmp_joy; SDL_JoystickID tmp_joy_id; int tmp_joy_flag = 0; SDL_Haptic * rc_haptic[MAX_JOYSTICKS]; //1 for each joystick double rc_pressure = 0; int rc_touchX = 0; int rc_touchY = 0; int rc_motionX = 0; int rc_motionY = 0; int rc_touch = 0; int rc_mt_status = 0; int rc_mt_x = 0; int rc_mt_y = 0; int rc_mt_numFingers = 0; double rc_mt_theta = 0; double rc_mt_dist = 0; SDL_TouchID rc_touchDevice; SDL_Finger rc_finger[MAX_FINGERS]; set rc_fingers_pressed; SDL_Sensor * rc_accel[MAX_ACCELS]; int num_accels = 0; SDL_Sensor * rc_gyro[MAX_GYROS]; int num_gyros = 0; struct SDLKeyMap { SDLKeyMap() {} SDLKeyMap(s32 x11, s32 win32) : SDLKey(x11), Win32Key(win32) { } s32 SDLKey; s32 Win32Key; bool operator<(const SDLKeyMap& o) const { return SDLKey KeyMap; void createKeyMap() { // I don't know if this is the best method to create // the lookuptable, but I'll leave it like that until // I find a better version. KeyMap.reallocate(105); // buttons missing KeyMap.push_back(SDLKeyMap(SDLK_BACKSPACE, irr::EKEY_CODE::KEY_BACK)); KeyMap.push_back(SDLKeyMap(SDLK_TAB, irr::EKEY_CODE::KEY_TAB)); KeyMap.push_back(SDLKeyMap(SDLK_CLEAR, irr::EKEY_CODE::KEY_CLEAR)); KeyMap.push_back(SDLKeyMap(SDLK_RETURN, irr::EKEY_CODE::KEY_RETURN)); // combined modifiers missing KeyMap.push_back(SDLKeyMap(SDLK_PAUSE, irr::EKEY_CODE::KEY_PAUSE)); KeyMap.push_back(SDLKeyMap(SDLK_CAPSLOCK, irr::EKEY_CODE::KEY_CAPITAL)); // asian letter keys missing KeyMap.push_back(SDLKeyMap(SDLK_ESCAPE, irr::EKEY_CODE::KEY_ESCAPE)); // asian letter keys missing KeyMap.push_back(SDLKeyMap(SDLK_SPACE, irr::EKEY_CODE::KEY_SPACE)); KeyMap.push_back(SDLKeyMap(SDLK_PAGEUP, irr::EKEY_CODE::KEY_PRIOR)); KeyMap.push_back(SDLKeyMap(SDLK_PAGEDOWN, irr::EKEY_CODE::KEY_NEXT)); KeyMap.push_back(SDLKeyMap(SDLK_END, irr::EKEY_CODE::KEY_END)); KeyMap.push_back(SDLKeyMap(SDLK_HOME, irr::EKEY_CODE::KEY_HOME)); KeyMap.push_back(SDLKeyMap(SDLK_LEFT, irr::EKEY_CODE::KEY_LEFT)); KeyMap.push_back(SDLKeyMap(SDLK_UP, irr::EKEY_CODE::KEY_UP)); KeyMap.push_back(SDLKeyMap(SDLK_RIGHT, irr::EKEY_CODE::KEY_RIGHT)); KeyMap.push_back(SDLKeyMap(SDLK_DOWN, irr::EKEY_CODE::KEY_DOWN)); // select missing KeyMap.push_back(SDLKeyMap(SDLK_PRINTSCREEN, irr::EKEY_CODE::KEY_PRINT)); // execute missing KeyMap.push_back(SDLKeyMap(SDLK_PRINTSCREEN, irr::EKEY_CODE::KEY_SNAPSHOT)); KeyMap.push_back(SDLKeyMap(SDLK_INSERT, irr::EKEY_CODE::KEY_INSERT)); KeyMap.push_back(SDLKeyMap(SDLK_DELETE, irr::EKEY_CODE::KEY_DELETE)); KeyMap.push_back(SDLKeyMap(SDLK_HELP, irr::EKEY_CODE::KEY_HELP)); KeyMap.push_back(SDLKeyMap(SDLK_0, irr::EKEY_CODE::KEY_KEY_0)); KeyMap.push_back(SDLKeyMap(SDLK_1, irr::EKEY_CODE::KEY_KEY_1)); KeyMap.push_back(SDLKeyMap(SDLK_2, irr::EKEY_CODE::KEY_KEY_2)); KeyMap.push_back(SDLKeyMap(SDLK_3, irr::EKEY_CODE::KEY_KEY_3)); KeyMap.push_back(SDLKeyMap(SDLK_4, irr::EKEY_CODE::KEY_KEY_4)); KeyMap.push_back(SDLKeyMap(SDLK_5, irr::EKEY_CODE::KEY_KEY_5)); KeyMap.push_back(SDLKeyMap(SDLK_6, irr::EKEY_CODE::KEY_KEY_6)); KeyMap.push_back(SDLKeyMap(SDLK_7, irr::EKEY_CODE::KEY_KEY_7)); KeyMap.push_back(SDLKeyMap(SDLK_8, irr::EKEY_CODE::KEY_KEY_8)); KeyMap.push_back(SDLKeyMap(SDLK_9, irr::EKEY_CODE::KEY_KEY_9)); KeyMap.push_back(SDLKeyMap(SDLK_a, irr::EKEY_CODE::KEY_KEY_A)); KeyMap.push_back(SDLKeyMap(SDLK_b, irr::EKEY_CODE::KEY_KEY_B)); KeyMap.push_back(SDLKeyMap(SDLK_c, irr::EKEY_CODE::KEY_KEY_C)); KeyMap.push_back(SDLKeyMap(SDLK_d, irr::EKEY_CODE::KEY_KEY_D)); KeyMap.push_back(SDLKeyMap(SDLK_e, irr::EKEY_CODE::KEY_KEY_E)); KeyMap.push_back(SDLKeyMap(SDLK_f, irr::EKEY_CODE::KEY_KEY_F)); KeyMap.push_back(SDLKeyMap(SDLK_g, irr::EKEY_CODE::KEY_KEY_G)); KeyMap.push_back(SDLKeyMap(SDLK_h, irr::EKEY_CODE::KEY_KEY_H)); KeyMap.push_back(SDLKeyMap(SDLK_i, irr::EKEY_CODE::KEY_KEY_I)); KeyMap.push_back(SDLKeyMap(SDLK_j, irr::EKEY_CODE::KEY_KEY_J)); KeyMap.push_back(SDLKeyMap(SDLK_k, irr::EKEY_CODE::KEY_KEY_K)); KeyMap.push_back(SDLKeyMap(SDLK_l, irr::EKEY_CODE::KEY_KEY_L)); KeyMap.push_back(SDLKeyMap(SDLK_m, irr::EKEY_CODE::KEY_KEY_M)); KeyMap.push_back(SDLKeyMap(SDLK_n, irr::EKEY_CODE::KEY_KEY_N)); KeyMap.push_back(SDLKeyMap(SDLK_o, irr::EKEY_CODE::KEY_KEY_O)); KeyMap.push_back(SDLKeyMap(SDLK_p, irr::EKEY_CODE::KEY_KEY_P)); KeyMap.push_back(SDLKeyMap(SDLK_q, irr::EKEY_CODE::KEY_KEY_Q)); KeyMap.push_back(SDLKeyMap(SDLK_r, irr::EKEY_CODE::KEY_KEY_R)); KeyMap.push_back(SDLKeyMap(SDLK_s, irr::EKEY_CODE::KEY_KEY_S)); KeyMap.push_back(SDLKeyMap(SDLK_t, irr::EKEY_CODE::KEY_KEY_T)); KeyMap.push_back(SDLKeyMap(SDLK_u, irr::EKEY_CODE::KEY_KEY_U)); KeyMap.push_back(SDLKeyMap(SDLK_v, irr::EKEY_CODE::KEY_KEY_V)); KeyMap.push_back(SDLKeyMap(SDLK_w, irr::EKEY_CODE::KEY_KEY_W)); KeyMap.push_back(SDLKeyMap(SDLK_x, irr::EKEY_CODE::KEY_KEY_X)); KeyMap.push_back(SDLKeyMap(SDLK_y, irr::EKEY_CODE::KEY_KEY_Y)); KeyMap.push_back(SDLKeyMap(SDLK_z, irr::EKEY_CODE::KEY_KEY_Z)); // TODO: //KeyMap.push_back(SDLKeyMap(SDLK_LSUPER, KEY_LWIN)); // TODO: //KeyMap.push_back(SDLKeyMap(SDLK_RSUPER, KEY_RWIN)); // apps missing KeyMap.push_back(SDLKeyMap(SDLK_POWER, irr::EKEY_CODE::KEY_SLEEP)); //?? KeyMap.push_back(SDLKeyMap(SDLK_KP_0, irr::EKEY_CODE::KEY_NUMPAD0)); KeyMap.push_back(SDLKeyMap(SDLK_KP_1, irr::EKEY_CODE::KEY_NUMPAD1)); KeyMap.push_back(SDLKeyMap(SDLK_KP_2, irr::EKEY_CODE::KEY_NUMPAD2)); KeyMap.push_back(SDLKeyMap(SDLK_KP_3, irr::EKEY_CODE::KEY_NUMPAD3)); KeyMap.push_back(SDLKeyMap(SDLK_KP_4, irr::EKEY_CODE::KEY_NUMPAD4)); KeyMap.push_back(SDLKeyMap(SDLK_KP_5, irr::EKEY_CODE::KEY_NUMPAD5)); KeyMap.push_back(SDLKeyMap(SDLK_KP_6, irr::EKEY_CODE::KEY_NUMPAD6)); KeyMap.push_back(SDLKeyMap(SDLK_KP_7, irr::EKEY_CODE::KEY_NUMPAD7)); KeyMap.push_back(SDLKeyMap(SDLK_KP_8, irr::EKEY_CODE::KEY_NUMPAD8)); KeyMap.push_back(SDLKeyMap(SDLK_KP_9, irr::EKEY_CODE::KEY_NUMPAD9)); KeyMap.push_back(SDLKeyMap(SDLK_KP_MULTIPLY, irr::EKEY_CODE::KEY_MULTIPLY)); KeyMap.push_back(SDLKeyMap(SDLK_KP_PLUS, irr::EKEY_CODE::KEY_ADD)); // KeyMap.push_back(SDLKeyMap(SDLK_KP_, KEY_SEPARATOR)); KeyMap.push_back(SDLKeyMap(SDLK_KP_MINUS, irr::EKEY_CODE::KEY_SUBTRACT)); KeyMap.push_back(SDLKeyMap(SDLK_KP_PERIOD, irr::EKEY_CODE::KEY_DECIMAL)); KeyMap.push_back(SDLKeyMap(SDLK_KP_DIVIDE, irr::EKEY_CODE::KEY_DIVIDE)); KeyMap.push_back(SDLKeyMap(SDLK_F1, irr::EKEY_CODE::KEY_F1)); KeyMap.push_back(SDLKeyMap(SDLK_F2, irr::EKEY_CODE::KEY_F2)); KeyMap.push_back(SDLKeyMap(SDLK_F3, irr::EKEY_CODE::KEY_F3)); KeyMap.push_back(SDLKeyMap(SDLK_F4, irr::EKEY_CODE::KEY_F4)); KeyMap.push_back(SDLKeyMap(SDLK_F5, irr::EKEY_CODE::KEY_F5)); KeyMap.push_back(SDLKeyMap(SDLK_F6, irr::EKEY_CODE::KEY_F6)); KeyMap.push_back(SDLKeyMap(SDLK_F7, irr::EKEY_CODE::KEY_F7)); KeyMap.push_back(SDLKeyMap(SDLK_F8, irr::EKEY_CODE::KEY_F8)); KeyMap.push_back(SDLKeyMap(SDLK_F9, irr::EKEY_CODE::KEY_F9)); KeyMap.push_back(SDLKeyMap(SDLK_F10, irr::EKEY_CODE::KEY_F10)); KeyMap.push_back(SDLKeyMap(SDLK_F11, irr::EKEY_CODE::KEY_F11)); KeyMap.push_back(SDLKeyMap(SDLK_F12, irr::EKEY_CODE::KEY_F12)); KeyMap.push_back(SDLKeyMap(SDLK_F13, irr::EKEY_CODE::KEY_F13)); KeyMap.push_back(SDLKeyMap(SDLK_F14, irr::EKEY_CODE::KEY_F14)); KeyMap.push_back(SDLKeyMap(SDLK_F15, irr::EKEY_CODE::KEY_F15)); // no higher F-keys // TODO: //KeyMap.push_back(SDLKeyMap(SDLK_NUMLOCK, KEY_NUMLOCK)); KeyMap.push_back(SDLKeyMap(SDLK_SCROLLLOCK, irr::EKEY_CODE::KEY_SCROLL)); KeyMap.push_back(SDLKeyMap(SDLK_LSHIFT, irr::EKEY_CODE::KEY_LSHIFT)); KeyMap.push_back(SDLKeyMap(SDLK_RSHIFT, irr::EKEY_CODE::KEY_RSHIFT)); KeyMap.push_back(SDLKeyMap(SDLK_LCTRL, irr::EKEY_CODE::KEY_LCONTROL)); KeyMap.push_back(SDLKeyMap(SDLK_RCTRL, irr::EKEY_CODE::KEY_RCONTROL)); KeyMap.push_back(SDLKeyMap(SDLK_LALT, irr::EKEY_CODE::KEY_LMENU)); KeyMap.push_back(SDLKeyMap(SDLK_RALT, irr::EKEY_CODE::KEY_RMENU)); KeyMap.push_back(SDLKeyMap(SDLK_PLUS, irr::EKEY_CODE::KEY_PLUS)); KeyMap.push_back(SDLKeyMap(SDLK_COMMA, irr::EKEY_CODE::KEY_COMMA)); KeyMap.push_back(SDLKeyMap(SDLK_MINUS, irr::EKEY_CODE::KEY_MINUS)); KeyMap.push_back(SDLKeyMap(SDLK_PERIOD, irr::EKEY_CODE::KEY_PERIOD)); // some special keys missing KeyMap.sort(); } IrrlichtDevice* device; irr::video::IVideoDriver * VideoDriver; irr::scene::ISceneManager *SceneManager; SDL_Window* rc_window; irr::core::dimension2d rc_window_size; struct rc_scene_properties_obj { irr::scene::ISceneNode* sky = NULL; }; rc_scene_properties_obj rc_scene_properties; #define RC_CONSTRAINT_TYPE_POINT 1 #define RC_CONSTRAINT_TYPE_HINGE 2 #define RC_CONSTRAINT_TYPE_SLIDER 3 #define RC_CONSTRAINT_TYPE_CONE 4 struct rc_constraint_obj { btTypedConstraint* constraint; int type; }; struct rc_physicsWorld3D_obj { irrBulletWorld* world; irr::f32 DeltaTime; irr::u32 maxSubSteps; irr::f32 fixedTimeStep; irr::u32 TimeStamp; irr::core::array constraints; }; rc_physicsWorld3D_obj rc_physics3D; //Canvases class rc_contactListener_obj : public b2ContactListener { void BeginContact(b2Contact* contact) { rc_sprite2D_obj* spriteA = (rc_sprite2D_obj*) contact->GetFixtureA()->GetBody()->GetUserData().pointer; rc_sprite2D_obj* spriteB = (rc_sprite2D_obj*) contact->GetFixtureB()->GetBody()->GetUserData().pointer; //std::cout << "sprite[" << spriteA->id << "] collide with sprite[" << spriteB->id << "]" << std::endl; } void EndContact(b2Contact* contact) { } }; struct rc_physicsWorld2D_obj { bool enabled = false; b2World* world; rc_contactListener_obj* contact_listener; Uint32 time_stamp; float timeStep = 1/60.0; //the length of time passed to simulate (seconds) int velocityIterations = 8; //how strongly to correct velocity int positionIterations = 3; //how strongly to correct position }; #define RC_CANVAS_TYPE_2D 0 #define RC_CANVAS_TYPE_3D 1 #define RC_CANVAS_TYPE_SPRITE 2 #define RC_PROJECTION_TYPE_ORTHOGRAPHIC 0 #define RC_PROJECTION_TYPE_PERSPECTIVE 1 struct rc_canvas_obj { irr::video::ITexture* texture; //irr::video::ITexture* sprite_layer; int type; irr::core::dimension2d dimension; struct rc_canvas_viewport { irr::core::vector2d position; irr::core::dimension2d dimension; } viewport; bool show3D = false; Camera camera; irr::core::vector2d offset; int mode; bool visible = true; int z = 0; irr::u32 color_mod; rc_physicsWorld2D_obj physics2D; irr::core::array sprite; }; irr::core::array rc_canvas; irr::core::array rc_canvas_zOrder; int rc_active_canvas = -1; bool hasPreUpdated = false; irr::video::SColor rc_active_color(0,0,0,0); irr::video::SColor rc_clear_color(0,0,0,0); bool rc_init_events = false; bool rc_init_timer = false; bool rc_init_video = false; bool rc_init_joystick = false; bool rc_init_haptic = false; bool rc_init_sensor = false; bool rc_init_noparachute = false; bool rc_init_audio = false; irr::s32 MouseX, MouseY, MouseXRel, MouseYRel; irr::u32 MouseButtonStates; int rc_win_event = -1; #define RC_WIN_EVENT_CLOSE 1 #define RC_WIN_EVENT_MINIMIZE 2 #define RC_WIN_EVENT_MAXIMIZE 3 #define RC_WIN_EVENT_RESIZE 4 bool rc_win_exitOnClose = true; std::string rc_textinput_string = ""; std::string rc_textinput_char = ""; int rc_textinput_timer = 0; int rc_textinput_delay = 100; bool rc_textinput_flag = true; bool rc_textinput_isActive = false; int rc_textinput_waitHold = 800; bool rc_textinput_hold = false; bool rc_toggleBackspace = true; static Uint32 baseticks = 0; int rc_inkey_val = 0; const Uint8 * keyState = NULL; std::wstring_convert> converter; struct rc_font_obj { CGUITTFace* face; CGUIFreetypeFont* font; int font_size; }; irr::core::array rc_font; int rc_active_font = -1; bool mobile_active_window_flag = true; //------------ 3D Graphics ----------------// struct rc_material_obj { irr::video::SMaterial mat; bool isUsed = false; bool isReference = false; int refActor = -1; int refMatNum = 0; }; irr::core::array rc_material; #define RC_MESH_TYPE_NONE 0 #define RC_MESH_TYPE_ANIMATED 1 struct rc_mesh_obj { int mesh_type = 0; irr::scene::IAnimatedMesh* mesh; }; irr::core::array rc_mesh; struct rc_an8_obj { bool active; an8::an8_project project; }; irr::core::array rc_an8; #define RC_NODE_TYPE_NONE 0 #define RC_NODE_TYPE_MESH 1 #define RC_NODE_TYPE_OTMESH 2 #define RC_NODE_TYPE_LIGHT 3 #define RC_NODE_TYPE_TERRAIN 4 #define RC_NODE_TYPE_WATER 5 #define RC_NODE_TYPE_BILLBOARD 6 #define RC_NODE_TYPE_PARTICLE 7 #define RC_NODE_SHAPE_TYPE_NONE 0 #define RC_NODE_SHAPE_TYPE_BOX 1 #define RC_NODE_SHAPE_TYPE_SPHERE 2 #define RC_NODE_SHAPE_TYPE_CYLINDER 3 #define RC_NODE_SHAPE_TYPE_CAPSULE 4 #define RC_NODE_SHAPE_TYPE_CONE 5 #define RC_NODE_SHAPE_TYPE_CONVEXHULL 6 #define RC_NODE_SHAPE_TYPE_TRIMESH 7 #define RC_NODE_SHAPE_TYPE_HEIGHTFIELD 8 struct rc_node_physics_collision { int actorA; int actorB; irr::core::array pointA; irr::core::array pointB; irr::core::array normalB; }; irr::core::array rc_collisions; struct rc_node_physics { IRigidBody* rigid_body; int shape_type; bool isSolid; double mass; irr::core::vector3df gravity; //only used when changing from Solid to Non-Solid and vice versa irr::core::array collisions; }; #define RC_PARTICLE_TYPE_POINT 1 #define RC_PARTICLE_TYPE_BOX 2 #define RC_PARTICLE_TYPE_SPHERE 3 #define RC_PARTICLE_TYPE_CYLINDER 4 #define RC_PARTICLE_TYPE_MESH 5 #define RC_PARTICLE_TYPE_RING 6 struct rc_particle_properties_obj { int particle_type = 0; bool everyMeshVertex; irr::s32 mbNumber = 0; irr::f32 normalDirectionModifier; bool useNormalDirection; irr::s32 mesh_id; irr::core::vector3df direction; irr::u32 minParticlesPerSecond; irr::u32 maxParticlesPerSecond; irr::video::SColor minStartColor; irr::video::SColor maxStartColor; irr::u32 lifeTimeMin; irr::u32 lifeTimeMax; irr::s32 maxAngleDegrees; irr::core::dimension2df minStartSize; irr::core::dimension2df maxStartSize; irr::core::vector3df center; irr::f32 radius; irr::f32 ringThickness; irr::core::aabbox3df box; irr::core::vector3df normal; irr::f32 length; bool outlineOnly; }; #define RC_ANIMATION_MD2 -2 #define RC_ANIMATION_TRANSITION -3 struct rc_actor_animation_obj { bool active; int start_frame; int end_frame; double fps; irr::u32 frame_start_time; irr::u32 frame_swap_time; }; struct rc_scene_node { int node_type = 0; irr::scene::ISceneNode* mesh_node; irr::scene::IShadowVolumeSceneNode* shadow; rc_node_physics physics; bool transition; double transition_frame; double transition_time; double transition_start_time; rc_particle_properties_obj particle_properties; int material_ref_index = -1; int current_animation; int num_animation_loops; int current_animation_loop; bool isPlaying; irr::core::array deleted_animation; irr::core::array animation; }; irr::core::array rc_actor; irr::core::array rc_transition_actor; class rc_animEndCallBack : public IAnimationEndCallBack { public: rc_scene_node* ref_actor; void OnAnimationEnd( IAnimatedMeshSceneNode *node) { if(ref_actor->current_animation_loop < ref_actor->num_animation_loops || ref_actor->num_animation_loops < 0) { //std::cout << "animating" << std::endl; irr::scene::IAnimatedMeshSceneNode* node = (irr::scene::IAnimatedMeshSceneNode*) ref_actor->mesh_node; int animation = ref_actor->current_animation; if(animation == RC_ANIMATION_MD2) { int start_frame = node->getStartFrame(); int end_frame = node->getEndFrame(); node->setFrameLoop(start_frame, end_frame); ref_actor->current_animation_loop++; } else if(animation == RC_ANIMATION_TRANSITION) { //TODO: Transitions are currently broken } else if(animation < 0 || animation >= ref_actor->animation.size()) { return; } else { if(!ref_actor->animation[animation].active) { ref_actor->isPlaying = false; ref_actor->current_animation_loop = 0; return; } int start_frame = ref_actor->animation[animation].start_frame; int end_frame = ref_actor->animation[animation].end_frame; node->setFrameLoop(start_frame, end_frame); ref_actor->current_animation_loop++; } } else { ref_actor->isPlaying = false; } //std::cout << "The animation has ended!" << std::endl; // Your callback code goes there. } }; void myTickCallback2(btSoftRigidDynamicsWorld* dynamicsWorld, btScalar timeStep) { rc_collisions.clear(); int numManifolds = dynamicsWorld->getDispatcher()->getNumManifolds(); int c_index = 0; rc_node_physics_collision collision; for(int i = 0; i < rc_actor.size(); i++) { rc_actor[i].physics.collisions.clear(); } for (int i = 0; i < rc_physics3D.world->getNumManifolds(); i++) { ICollisionCallbackInformation* manifold = rc_physics3D.world->getCollisionCallback(i); int numContacts = manifold->getPointer()->getNumContacts(); int actorA = manifold->getBody0()->getIdentification()->getId(); int actorB = manifold->getBody1()->getIdentification()->getId(); collision.actorA = actorA; collision.actorB = actorB; //std::cout << "Collision Details: " << actorA << ", " << actorB << ", " << numContacts << std::endl; if(numContacts < 1) continue; for (int j = 0; j < numContacts; j++) { SManifoldPoint pt = manifold->getContactPoint(j); collision.pointA.push_back(pt.getPositionWorldOnA()); collision.pointB.push_back(pt.getPositionWorldOnB()); collision.normalB.push_back(pt.getNormalWorldOnB()); } c_index = rc_collisions.size(); rc_collisions.push_back(collision); rc_actor[actorA].physics.collisions.push_back(c_index); rc_actor[actorB].physics.collisions.push_back(c_index); } for(int i = 0; i < rc_actor.size(); i++) { if(!rc_actor[i].physics.isSolid) { if(rc_actor[i].physics.collisions.size() > 0) { rc_physics3D.world->removeCollisionObject(rc_actor[i].physics.rigid_body, false); rc_physics3D.world->addRigidBody(rc_actor[i].physics.rigid_body); rc_actor[i].physics.rigid_body->setMassProps(1, irr::core::vector3df(0,0,0)); rc_actor[i].physics.rigid_body->setGravity(irr::core::vector3df(0,0,0)); } } } } #define RC_ACTOR_TEXTURE_TYPE_IMAGE 0 #define RC_ACTOR_TEXTURE_TYPE_CANVAS 1 // Function to calculate a point on a cubic Bezier curve vector3df bezierPoint(const vector3df& p0, const vector3df& p1, const vector3df& p2, const vector3df& p3, float t) { float u = 1.0f - t; float tt = t * t; float uu = u * u; float uuu = uu * u; float ttt = tt * t; vector3df p = uuu * p0; // (1-t)^3 * p0 p += 3 * uu * t * p1; // 3 * (1-t)^2 * t * p1 p += 3 * u * tt * p2; // 3 * (1-t) * t^2 * p2 p += ttt * p3; // t^3 * p3 return p; } // Function to draw a Bezier curve void drawBezierCurve(IVideoDriver* driver, const vector3df& p0, const vector3df& p1, const vector3df& p2, const vector3df& p3, SColor color, int segments) { std::vector points; for (int i = 0; i <= segments; ++i) { float t = static_cast(i) / segments; points.push_back(bezierPoint(p0, p1, p2, p3, t)); } for (size_t i = 0; i < points.size() - 1; ++i) { driver->draw3DLine(points[i], points[i + 1], color); } } void printIrrMatrix(irr::core::matrix4 m) { for(int i = 0; i < 4; i++) std::cout << "[ " << m[i*4] << ", " << m[i*4+1] << ", " << m[i*4+2] << ", " << m[i*4+3] << " ]" << std::endl; } struct rc_image_obj { irr::video::ITexture* image; Uint8 alpha = 255; irr::video::SColor color_mod = irr::video::SColor(255,255,255,255); }; irr::core::array rc_image; irr::video::E_BLEND_OPERATION rc_blend_mode = irr::video::EBO_ADD; bool rc_bilinear_filter = false; void rc_setDriverMaterial() { if(!VideoDriver) return; irr::video::SMaterial material; material.Lighting = false; material.ZWriteEnable = irr::video::EZW_OFF; material.ZBuffer = false; material.BackfaceCulling = false; material.TextureLayer[0].Texture = 0; material.TextureLayer[0].BilinearFilter = rc_bilinear_filter; material.MaterialTypeParam = irr::video::pack_textureBlendFunc(irr::video::EBF_SRC_ALPHA, irr::video::EBF_ONE_MINUS_SRC_ALPHA, irr::video::EMFN_MODULATE_1X, irr::video::EAS_TEXTURE | irr::video::EAS_VERTEX_COLOR); material.BlendOperation = rc_blend_mode; material.BlendOperation = irr::video::EBO_ADD; material.MaterialType = irr::video::EMT_ONETEXTURE_BLEND; VideoDriver->setMaterial(material); } void draw2DImage(irr::video::IVideoDriver *driver, irr::video::ITexture* texture, irr::core::rect sourceRect, irr::core::position2d position, irr::core::position2d rotationPoint, irr::f32 rotation, irr::core::vector2df scale, bool useAlphaChannel, irr::video::SColor color, irr::core::vector2d screenSize) { if(rc_active_canvas < 0 || rc_active_canvas >= rc_canvas.size()) return; // Store and clear the projection matrix irr::core::matrix4 oldProjMat = driver->getTransform(irr::video::ETS_PROJECTION); driver->setTransform(irr::video::ETS_PROJECTION,irr::core::matrix4()); // Store and clear the view matrix irr::core::matrix4 oldViewMat = driver->getTransform(irr::video::ETS_VIEW); driver->setTransform(irr::video::ETS_VIEW,irr::core::matrix4()); // Store and clear the world matrix irr::core::matrix4 oldWorldMat = driver->getTransform(irr::video::ETS_WORLD); driver->setTransform(irr::video::ETS_WORLD,irr::core::matrix4()); // Find horizontal and vertical axes after rotation irr::f32 c = cos(-rotation*irr::core::DEGTORAD); irr::f32 s = sin(-rotation*irr::core::DEGTORAD); irr::core::vector2df horizontalAxis(c,s); irr::core::vector2df verticalAxis(s,-c); // First, we'll find the offset of the center and then where the center would be after rotation irr::core::vector2df centerOffset(position.X+sourceRect.getWidth()/2.0f*scale.X-rotationPoint.X,position.Y+sourceRect.getHeight()/2.0f*scale.Y-rotationPoint.Y); irr::core::vector2df center = centerOffset.X*horizontalAxis - centerOffset.Y*verticalAxis; center.X += rotationPoint.X; center.Y += rotationPoint.Y; // Now find the corners based off the center irr::core::vector2df cornerOffset(sourceRect.getWidth()*scale.X/2.0f,sourceRect.getHeight()*scale.Y/2.0f); verticalAxis *= cornerOffset.Y; horizontalAxis *= cornerOffset.X; irr::core::vector2df corner[4]; corner[0] = center + verticalAxis - horizontalAxis; corner[1] = center + verticalAxis + horizontalAxis; corner[2] = center - verticalAxis - horizontalAxis; corner[3] = center - verticalAxis + horizontalAxis; // Find the uv coordinates of the sourceRect irr::core::vector2df textureSize(texture->getSize().Width, texture->getSize().Height); irr::core::vector2df uvCorner[4]; uvCorner[0] = irr::core::vector2df(sourceRect.UpperLeftCorner.X,sourceRect.UpperLeftCorner.Y); uvCorner[1] = irr::core::vector2df(sourceRect.LowerRightCorner.X,sourceRect.UpperLeftCorner.Y); uvCorner[2] = irr::core::vector2df(sourceRect.UpperLeftCorner.X,sourceRect.LowerRightCorner.Y); uvCorner[3] = irr::core::vector2df(sourceRect.LowerRightCorner.X,sourceRect.LowerRightCorner.Y); for (irr::s32 i = 0; i < 4; i++) uvCorner[i] /= textureSize; // Vertices for the image irr::video::S3DVertex vertices[4]; irr::u16 indices[6] = { 0, 1, 2, 3 ,2 ,1 }; // Convert pixels to world coordinates //irr::core::vector2df screenSize(rc_canvas[rc_active_canvas].dimension.Width, rc_canvas[rc_active_canvas].dimension.Height); for (irr::s32 i = 0; i < 4; i++) { vertices[i].Pos = irr::core::vector3df(((corner[i].X/screenSize.X)-0.5f)*2.0f,((corner[i].Y/screenSize.Y)-0.5f)*-2.0f,1); vertices[i].TCoords = uvCorner[i]; vertices[i].Color = color; } // Create the material // IMPORTANT: For irrlicht 1.8 and above you MUST ADD THIS LINE: // material.BlendOperation = irr::video::EBO_ADD; irr::video::SMaterial material; material.Lighting = false; material.ZWriteEnable = irr::video::EZW_OFF; material.ZBuffer = false; material.BackfaceCulling = false; material.TextureLayer[0].Texture = texture; material.TextureLayer[0].BilinearFilter = rc_bilinear_filter; material.MaterialTypeParam = irr::video::pack_textureBlendFunc(irr::video::EBF_SRC_ALPHA, irr::video::EBF_ONE_MINUS_SRC_ALPHA, irr::video::EMFN_MODULATE_1X, irr::video::EAS_TEXTURE | irr::video::EAS_VERTEX_COLOR); material.BlendOperation = rc_blend_mode; //material.BlendOperation = irr::video::EBO_ADD; if (useAlphaChannel) material.MaterialType = irr::video::EMT_ONETEXTURE_BLEND; else material.MaterialType = irr::video::EMT_SOLID; driver->setMaterial(material); driver->drawIndexedTriangleList(&vertices[0],4,&indices[0],2); // Restore projection, world, and view matrices driver->setTransform(irr::video::ETS_PROJECTION,oldProjMat); driver->setTransform(irr::video::ETS_VIEW,oldViewMat); driver->setTransform(irr::video::ETS_WORLD,oldWorldMat); rc_setDriverMaterial(); } void draw2DImage2(irr::video::IVideoDriver *driver, irr::video::ITexture* texture, irr::core::rect sourceRect, irr::core::rect destRect, irr::core::position2d rotationPoint, irr::f32 rotation, bool useAlphaChannel, irr::video::SColor color, irr::core::vector2d screenSize ) { if(rc_active_canvas < 0 || rc_active_canvas >= rc_canvas.size()) return; // Store and clear the projection matrix irr::core::matrix4 oldProjMat = driver->getTransform(irr::video::ETS_PROJECTION); driver->setTransform(irr::video::ETS_PROJECTION,irr::core::matrix4()); // Store and clear the view matrix irr::core::matrix4 oldViewMat = driver->getTransform(irr::video::ETS_VIEW); driver->setTransform(irr::video::ETS_VIEW,irr::core::matrix4()); // Store and clear the world matrix irr::core::matrix4 oldWorldMat = driver->getTransform(irr::video::ETS_WORLD); driver->setTransform(irr::video::ETS_WORLD,irr::core::matrix4()); // Find horizontal and vertical axes after rotation irr::f32 c = cos(-rotation*irr::core::DEGTORAD); irr::f32 s = sin(-rotation*irr::core::DEGTORAD); irr::core::vector2df horizontalAxis(c,s); irr::core::vector2df verticalAxis(s,-c); // First, we'll find the offset of the center and then where the center would be after rotation irr::core::vector2df centerOffset(destRect.UpperLeftCorner.X+destRect.getWidth()/2.0f-rotationPoint.X,destRect.UpperLeftCorner.Y+destRect.getHeight()/2.0f-rotationPoint.Y); irr::core::vector2df center = centerOffset.X*horizontalAxis - centerOffset.Y*verticalAxis; center.X += rotationPoint.X; center.Y += rotationPoint.Y; // Now find the corners based off the center irr::core::vector2df cornerOffset(destRect.getWidth()/2.0f,destRect.getHeight()/2.0f); verticalAxis *= cornerOffset.Y; horizontalAxis *= cornerOffset.X; irr::core::vector2df corner[4]; corner[0] = center + verticalAxis - horizontalAxis; corner[1] = center + verticalAxis + horizontalAxis; corner[2] = center - verticalAxis - horizontalAxis; corner[3] = center - verticalAxis + horizontalAxis; // Find the uv coordinates of the sourceRect irr::core::vector2df textureSize(texture->getSize().Width, texture->getSize().Height); irr::core::vector2df uvCorner[4]; uvCorner[0] = irr::core::vector2df(sourceRect.UpperLeftCorner.X,sourceRect.UpperLeftCorner.Y); uvCorner[1] = irr::core::vector2df(sourceRect.LowerRightCorner.X,sourceRect.UpperLeftCorner.Y); uvCorner[2] = irr::core::vector2df(sourceRect.UpperLeftCorner.X,sourceRect.LowerRightCorner.Y); uvCorner[3] = irr::core::vector2df(sourceRect.LowerRightCorner.X,sourceRect.LowerRightCorner.Y); for (irr::s32 i = 0; i < 4; i++) uvCorner[i] /= textureSize; // Vertices for the image irr::video::S3DVertex vertices[4]; irr::u16 indices[6] = { 0, 1, 2, 3 ,2 ,1 }; // Convert pixels to world coordinates //irr::core::vector2df screenSize(rc_canvas[rc_active_canvas].dimension.Width, rc_canvas[rc_active_canvas].dimension.Height); for (irr::s32 i = 0; i < 4; i++) { vertices[i].Pos = irr::core::vector3df(((corner[i].X/screenSize.X)-0.5f)*2.0f,((corner[i].Y/screenSize.Y)-0.5f)*-2.0f,1); vertices[i].TCoords = uvCorner[i]; vertices[i].Color = color; } // Create the material // IMPORTANT: For irrlicht 1.8 and above you MUST ADD THIS LINE: // material.BlendOperation = irr::video::EBO_ADD; irr::video::SMaterial material; material.Lighting = false; material.ZWriteEnable = irr::video::EZW_OFF; material.ZBuffer = false; material.BackfaceCulling = false; material.TextureLayer[0].Texture = texture; material.TextureLayer[0].BilinearFilter = rc_bilinear_filter; //TODO: Add option to switch this on/off material.BlendOperation = rc_blend_mode; material.MaterialTypeParam = irr::video::pack_textureBlendFunc(irr::video::EBF_SRC_ALPHA, irr::video::EBF_ONE_MINUS_SRC_ALPHA, irr::video::EMFN_MODULATE_1X, irr::video::EAS_TEXTURE | irr::video::EAS_VERTEX_COLOR); //material.AntiAliasing = irr::video::EAAM_OFF; if (useAlphaChannel) material.MaterialType = irr::video::EMT_ONETEXTURE_BLEND; else material.MaterialType = irr::video::EMT_SOLID; driver->setMaterial(material); driver->drawIndexedTriangleList(&vertices[0],4,&indices[0],2); // Restore projection, world, and view matrices driver->setTransform(irr::video::ETS_PROJECTION,oldProjMat); driver->setTransform(irr::video::ETS_VIEW,oldViewMat); driver->setTransform(irr::video::ETS_WORLD,oldWorldMat); rc_setDriverMaterial(); } SDL_Surface* convertTextureToSurface(irr::video::ITexture* itexture) { Uint32 t_width, t_height; t_width = itexture->getSize().Width; t_height = itexture->getSize().Height; SDL_Surface* surface = SDL_CreateRGBSurface(0, t_width, t_height, 32, 0, 0, 0, 0); if(surface) { Uint32* surface_pixels = (Uint32*)surface->pixels; Uint32* texture_pixels = (Uint32*)rc_canvas[rc_active_canvas].texture->lock(); int i = 0; for(int y = 0; y < t_height; y++) { for(int x = 0; x < t_width; x++) { surface_pixels[i] = texture_pixels[i]; } } rc_canvas[rc_active_canvas].texture->unlock(); } return surface; } #endif // RC_GFX_CORE_H_INCLUDED