This Code Snippet: Box2D (2D Physics engine) integrated with Irrlicht (3D Graphics engine) successfully!
Models are: One bouncing ball and the ground. I´m sharing this code with you all, but I need help too...
• Everything there works great (until now...) but I need to integrate the cobra function ( http://irrlicht.sourceforge.net/forum// ... hp?t=42350 ), or something similar, in this code.
• Can anyone help, please?... - The idea is to have a visual debugger (showing where the physic bodies are), but drawn by the irrlicht itself (not the Box2D debug draws, or any other external debugger).
• I just couldn´t make that cobra code work in this project, I am not so skilled as cobras, snakes, sheeps and tigers... But I can beat snails...
Code: Select all
#pragma once
/// System headers: (These headers are not all nedded in this sample code, but just in case...)
#include <fstream>
#include <iostream>
#include <exception>
#include <sstream>
#include <vector>
#include <string>
#include <cstring>
#include <stdio.h>
#include <dirent.h>
#include <functional>
#include <algorithm>
#include <ctype.h>
#include <ctime>
#include <cstdlib>
#include <iomanip>
#include <cmath>
#include <stdint.h>
#include <iterator>
#include <numeric>
#include <tchar.h>
using namespace std;
/// Irrlicht headers:
#include <irrlicht.h>
using namespace irr;
using namespace core;
using namespace video;
using namespace scene;
using namespace io;
using namespace gui;
/// Box2D headers:
#include <Box2D/Box2D.h>
#include <Box2D/Common/b2Math.h>
/// Irrlicht Global Variables #1:
irr::u32 SCREEN_WIDTH = 1280;
irr::u32 SCREEN_HEIGHT = 720;
bool FULLSCREEN = false;
bool STENCIL_SHADOWS = false;
bool VSYNC = true; // Limit rendering to the screen refresh rate (true == to avoid crashes and old hardware damages)
/// Irrlicht Global Variables #2:
IrrlichtDevice* device = NULL; // Create Device
irr::video::IVideoDriver* driver = NULL; // Create Driver
irr::scene::ISceneManager* smgr = NULL; // Create Scene Manager
irr::io::IFileSystem* filesys = NULL; // File System;
/// Window Text:
stringw windowtexts = L"Irrlicht vs Box2D ... Fight!";
/// Common Global Variables and Formulas:
#define BOXTOIRR_SCALE 30.0f /// Pixels per meter
#define IRRTOBOX_SCALE (1.0f/BOXTOIRR_SCALE) /// Meters per pixel
#define DEGTORAD 0.0174532925199432957f
#define RADTODEG 57.295779513082320876f
#define PI 3.141592653589793238463f
/// Box2D Global Variables:
b2World* world;
/// Start:
int main(int argc, char** argv){
/// Loop to chose driver from all available:
video::E_DRIVER_TYPE driverType;
for (int i=0; i<irr::video::EDT_COUNT; i++){
if (irr::IrrlichtDevice::isDriverSupported(irr::video::E_DRIVER_TYPE(i))){ driverType = irr::video::E_DRIVER_TYPE(i); };
};
/// Create device from the above found driver:
device = createDevice(driverType, core::dimension2d<u32>(SCREEN_WIDTH, SCREEN_HEIGHT), 16, FULLSCREEN, STENCIL_SHADOWS, VSYNC, 0);
if (device == 0){ return 0; }; // If device fails... Exit...
driver = device->getVideoDriver(); // Create Driver
filesys = device->getFileSystem(); // Load data
smgr = device->getSceneManager(); // Create Scene Manager
/// Global light:
smgr->setAmbientLight(video::SColorf(1.0, 1.0, 1.0, 0.0)); // Ambient Light. SColorf == r, g, b, a (0 = transparent | 255 = opaque)
/// Device - Other Stuff: (Window)
device->setWindowCaption(windowtexts.c_str());
device->getCursorControl()->setVisible(true); // Mouse cursor visibility
device->setResizable(true); // Resizable window
/// Load Data: ( "assets" is the name of the folder where I have my 3D models and textures )
device->getFileSystem()->addFileArchive("assets", true, true, EFAT_ZIP, "none");
/// -----------------------------------------------------------------------------------------------------
/// Add Camera:
scene::ICameraSceneNode* camera = smgr->addCameraSceneNode(0, core::vector3df(0,0,0), core::vector3df(0,0,0), -1, true);
camera->setPosition(core::vector3df(0,800,10000));
camera->setRotation(core::vector3df(0,0,0));
camera->setTarget(core::vector3df(0,800,-10000));
camera->setFOV(0.20f); /// To make the (almost) 2D view effect
camera->setFarValue(20000.0f);
/// Add Ball Node:
IAnimatedMeshSceneNode* node1 = smgr->addAnimatedMeshSceneNode(smgr->getMesh("ball.obj")); // Any other mesh will work too, it just for physics tests
node1->setPosition(core::vector3df(-500,1000,0));
node1->setRotation(core::vector3df(0.0f,0.0f,0.0f));
node1->setScale(core::vector3df(1.0f,1.0f,1.0f));
node1->setMaterialFlag(video::EMF_LIGHTING, true); // Node is affected by LIGHT?
node1->setMaterialFlag(video::EMF_FOG_ENABLE, false); // Node is affected by FOG?
node1->setMaterialFlag(video::EMF_BACK_FACE_CULLING, true); // Render both sides?
node1->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, true);
node1->setMaterialFlag(video::EMF_ANISOTROPIC_FILTER, true); // Increase view distance quality (similar to sharpness)
/// Textures:
for(u32 i=0; i<node1->getMaterialCount(); i++){
node1->getMaterial(i).setTexture(0, driver->getTexture("ball_texture.jpg"));
node1->getMaterial(i).getTextureMatrix(0).setTextureScale(1.0f,1.0f); /// Tile the texture
node1->getMaterial(i).EmissiveColor = video::SColor(255,150,150,150);
};
/// -----------------------------------------------------------------------------------------------------
/// Initialize the world of physics:
world = new b2World(b2Vec2(0.0f, -10.0f));
/// -----------------------------------------------------------------------------------------------------
/// Add physics for the ball node: (This one will have a cirle shape)
b2BodyDef def1;
def1.type = b2_dynamicBody; /// b2_dynamicBody ==> ball | b2_kinematicBody ==> ground
def1.position = b2Vec2( -100*IRRTOBOX_SCALE, 1000*IRRTOBOX_SCALE);
def1.angle = 0.0f;
def1.linearVelocity.Set(0.0f, 0.0f);
def1.angularVelocity = 0.0f;
def1.linearDamping = 0.0f;
def1.angularDamping = 0.0f;
def1.allowSleep = true;
def1.awake = true;
def1.fixedRotation = false;
def1.bullet = false;
def1.active = true;
def1.userData = (void*)"ball_def";
b2CircleShape shape1;
shape1.m_p.Set(0,0); /// Set origin relative to body
core::vector3df nodesize(node1->getTransformedBoundingBox().getExtent()); /// Get height from irrlicht node, then send it to box2d:
shape1.m_radius = nodesize.Y*IRRTOBOX_SCALE;
b2FixtureDef fix1;
fix1.shape = &shape1;
fix1.density = 60;
fix1.restitution = 0.65f;
fix1.friction = 1.0f;
fix1.userData = (void*)"ball_fix";
b2Body* body1;
body1 = world->CreateBody(&def1);
body1->CreateFixture(&fix1);
/// -----------------------------------------------------------------------------------------------------
/// Add physics for the ground: (No related node, yet... This one will have a rectangle shape)
b2BodyDef def2;
def2.type = b2_kinematicBody; /// b2_dynamicBody ==> ball | b2_kinematicBody ==> ground
def2.position = b2Vec2( -(100*IRRTOBOX_SCALE), (100*IRRTOBOX_SCALE) );
def2.angle = 0.05f; /// Add just a small angle to the ground
def2.linearVelocity.Set(0.0f, 0.0f);
def2.angularVelocity = 0.0f;
def2.linearDamping = 0.0f;
def2.angularDamping = 0.0f;
def2.allowSleep = true;
def2.awake = true;
def2.fixedRotation = true;
def2.bullet = false;
def2.active = true;
def2.userData = (void*)"ground_def";
b2PolygonShape shape2;
shape2.SetAsBox(2000.0f, 5.0f);
b2FixtureDef fix2;
fix2.shape = &shape2;
fix2.density = 0;
fix2.restitution = 0.0f;
fix2.friction = 1.0f;
fix2.userData = (void*)"ground_fix";
b2Body* body2;
body2 = world->CreateBody(&def2);
body2->CreateFixture(&fix2);
/// -----------------------------------------------------------------------------------------------------
/// Initializing Timers:
f32 deltatime = 0.0;
f32 lastFPS = -1;
u32 then = device->getTimer()->getTime();
float32 timestep = 1.0f/250.0f;
int32 velocityiterations = 6;
int32 positioniterations = 2;
/// Main Loop:
while(device->run()){
/// Clear:
driver->beginScene(true, true, video::SColor(0,0,0,0));
/// Calculate frame delta time:
const u32 now = device->getTimer()->getTime();
deltatime = (f32)(now - then);
then = now;
/// Physics time:
world->Step(deltatime*timestep, velocityiterations, positioniterations);
/// Reset all physics forces:
world->ClearForces();
/// 1) Calculate ball NODE position according its related BODY physics position:
b2Vec2 physpos = body1->GetPosition();
core::vector3df irrpos = node1->getPosition();
irrpos.X = physpos.x*BOXTOIRR_SCALE;
irrpos.Y = physpos.y*BOXTOIRR_SCALE;
/// Apply position to the node:
node1->setPosition(irrpos);
/// 2) Calculate ball NODE rotation according its related BODY physics rotation:
f32 irrrotZ = body1->GetAngle()*RADTODEG;
/// Apply rotation to the node:
node1->setRotation(core::vector3df(node1->getRotation().X, node1->getRotation().Y, irrrotZ));
/// Start render:
smgr->drawAll();
/// RESULT: All is set. Everything (graphics and physics) should be running fine now!...
/// BUT... For a visual physics debugger, we will need more code to be added in this place...
/// NEXT STEP: My tries to create a visual physics debugger are in the nexts posts...
/// Ends render:
driver->endScene();
};
/// Free and close Irrlicht:
if(device){ device->closeDevice(); };
if(device){ device->drop(); };
/// Free and close Box2D:
/// Later...
return 0;
/// Gone for a beer... But brb...
};