void PlatformDemoState::addPlayer() { auto body = xy::Component::create<xy::Physics::RigidBody>(m_messageBus, xy::Physics::BodyType::Dynamic); xy::Physics::CollisionRectangleShape cs({ 120.f, 240.f }); cs.setFriction(0.6f); cs.setDensity(0.9f); body->fixedRotation(true); body->addCollisionShape(cs); auto controller = xy::Component::create<Plat::PlayerController>(m_messageBus); auto camera = xy::Component::create<xy::Camera>(m_messageBus, getContext().defaultView); camera->lockTransform(xy::Camera::TransformLock::AxisY); camera->lockBounds({ 0.f,0.f, 2816.f, 1080.f }); auto model = m_meshRenderer.createModel(MeshID::Batcat, m_messageBus); model->setBaseMaterial(m_meshRenderer.getMaterial(MatId::BatcatMat)); model->rotate(xy::Model::Axis::X, 90.f); model->rotate(xy::Model::Axis::Z, -90.f); model->setPosition({ 60.f, 240.f, 0.f }); model->playAnimation(1, 0.2f); auto entity = xy::Entity::create(m_messageBus); entity->setPosition(960.f, 540.f); entity->addComponent(body); entity->addComponent(model); playerController = entity->addComponent(controller); playerCamera = entity->addComponent(camera); m_scene.setActiveCamera(playerCamera); m_scene.addEntity(entity, xy::Scene::Layer::FrontMiddle); body = xy::Component::create<xy::Physics::RigidBody>(m_messageBus, xy::Physics::BodyType::Dynamic); body->fixedRotation(true); cs.setRect({ 200.f, 300.f }); body->addCollisionShape(cs); cs.setRect({ 80.f, 80.f }, { 60.f, -80.f }); body->addCollisionShape(cs); model = m_meshRenderer.createModel(MeshID::Fixit, m_messageBus); model->setSubMaterial(m_meshRenderer.getMaterial(MatId::MrFixitBody), 0); model->setSubMaterial(m_meshRenderer.getMaterial(MatId::MrFixitHead), 1); model->rotate(xy::Model::Axis::X, 90.f); model->rotate(xy::Model::Axis::Z, 90.f); model->setScale({ 50.f, 50.f, 50.f }); model->setPosition({ 100.f, 300.f, 0.f }); entity = xy::Entity::create(m_messageBus); entity->setPosition(1320.f, 40.f); entity->addComponent(model); entity->addComponent(body); m_scene.addEntity(entity, xy::Scene::Layer::FrontMiddle); }
void PlatformDemoState::addItems() { std::function<void(const sf::Vector2f&)> createBox = [this](const sf::Vector2f& position) { auto body = xy::Component::create<xy::Physics::RigidBody>(m_messageBus, xy::Physics::BodyType::Dynamic); xy::Physics::CollisionRectangleShape cs({ 100.f, 100.f }, { -50.f, -50.f }); cs.setDensity(11.f); cs.setFriction(0.7f); body->addCollisionShape(cs); auto model = m_meshRenderer.createModel(MeshID::Cube, m_messageBus); model->setBaseMaterial(m_meshRenderer.getMaterial(MatId::Demo)); auto ent = xy::Entity::create(m_messageBus); ent->setPosition(position); ent->addComponent(body); ent->addComponent(model); m_scene.addEntity(ent, xy::Scene::BackFront); }; std::function<void(const sf::Vector2f&)> createBall = [this](const sf::Vector2f& position) { auto body = xy::Component::create<xy::Physics::RigidBody>(m_messageBus, xy::Physics::BodyType::Dynamic); xy::Physics::CollisionCircleShape cs(34.f); cs.setDensity(4.f); cs.setFriction(0.2f); cs.setRestitution(0.8f); body->addCollisionShape(cs); auto model = m_meshRenderer.createModel(MeshID::Sphere, m_messageBus); model->setBaseMaterial(m_meshRenderer.getMaterial(MatId::SphereTest)); auto ent = xy::Entity::create(m_messageBus); ent->setPosition(position); ent->addComponent(body); ent->addComponent(model); m_scene.addEntity(ent, xy::Scene::BackFront); }; for (auto i = 0u; i < 5u; ++i) { createBox({ xy::Util::Random::value(20.f, 2500.f), 20.f }); createBall({ xy::Util::Random::value(20.f, 2500.f), 20.f }); } }
void PlatformDemoState::buildPhysics() { auto groundBody = xy::Component::create<xy::Physics::RigidBody>(m_messageBus, xy::Physics::BodyType::Static); xy::Physics::CollisionRectangleShape rectShape({ 128.f, 1080.f }); groundBody->addCollisionShape(rectShape); rectShape.setRect({ 128.f, 1080.f - 128.f, 2560.f, 128.f }); groundBody->addCollisionShape(rectShape); rectShape.setRect({ 2688.f, 0.f, 128.f, 1080.f }); groundBody->addCollisionShape(rectShape); rectShape.setRect({ 128.f, -20.f, 2560.f, 20.f }); groundBody->addCollisionShape(rectShape); //add platforms std::vector<sf::Vector2f> points = { {420.f, 800.f}, {400.f, 765.f}, {784.f, 765.f}, {768.f, 800.f} }; xy::Physics::CollisionEdgeShape ce(points); groundBody->addCollisionShape(ce); points = { { 2020.f, 639.f }, { 2000.f, 604.f }, { 2384.f, 604.f }, { 2364.f, 639.f } }; ce.setPoints(points); groundBody->addCollisionShape(ce); points = { { 1690.f, 533.f }, { 1670.f, 497.f }, { 2054.f, 497.f }, { 2034.f, 533.f } }; ce.setPoints(points); groundBody->addCollisionShape(ce); points = { { 1230.f, 700.f }, { 1210.f, 665.f }, { 1584.f, 665.f }, { 1564.f, 700.f } }; ce.setPoints(points); groundBody->addCollisionShape(ce); auto entity = xy::Entity::create(m_messageBus); entity->addComponent(groundBody); m_scene.addEntity(entity, xy::Scene::Layer::BackFront); }
//private void TilemapDemoState::buildScene() { if (m_tilemap.load("assets/maps/platform.tmx")) { auto entity = xy::Entity::create(m_messageBus); const auto& layers = m_tilemap.getLayers(); for (const auto& l : layers) { if (l->getType() == xy::tmx::Layer::Type::Object) { xy::Logger::log("found object layer - attempting to create physics components", xy::Logger::Type::Info); auto rb = m_tilemap.createRigidBody(m_messageBus, *l); entity->addComponent(rb); } else { auto drawable = m_tilemap.getDrawable(m_messageBus, *l, m_textureResource, m_shaderResource); if (drawable) { xy::Logger::log("created layer drawable, adding to scene..."); entity->addComponent(drawable); } } } m_scene.addEntity(entity, xy::Scene::Layer::BackFront); static const float radius = 30.f; auto body = xy::Component::create<xy::Physics::RigidBody>(m_messageBus, xy::Physics::BodyType::Dynamic); auto cs = xy::Physics::CollisionCircleShape(radius); cs.setDensity(0.9f); cs.setRestitution(1.f); body->addCollisionShape(cs); auto drawable = xy::Component::create<xy::SfDrawableComponent<sf::CircleShape>>(m_messageBus); drawable->getDrawable().setRadius(radius); drawable->getDrawable().setOrigin({ radius, radius }); drawable->getDrawable().setFillColor({ 255, 255, 255, 200 }); drawable->getDrawable().setOutlineThickness(2.f); auto cam = xy::Component::create<xy::Camera>(m_messageBus, getContext().defaultView); cam->lockTransform(xy::Camera::TransformLock::Rotation, true); cam->lockBounds(m_tilemap.getBounds()); entity = xy::Entity::create(m_messageBus); entity->setPosition(800.f, 400.f); entity->addComponent(body); entity->addComponent(drawable); auto camPtr = entity->addComponent(cam); ent = m_scene.addEntity(entity, xy::Scene::Layer::FrontFront); m_scene.setActiveCamera(camPtr); } }
// 从一个Mesh创建碰撞模型 ICollisionShapePtr OpcodeCollisionSystem::createSubMeshCollisionShape(const String &meshName , const String &subMeshName , const Vector3& position, const Quaternion& orient, const Vector3 &scale) { //check if a shape with this name already exists ICollisionShapePtr shape = getCollisionShape(OpcodeCollisionSubMeshShape::SHAPE_TYPE , meshName + "_" + subMeshName); if(shape.isNull()) { shape.bind(new OpcodeCollisionSubMeshShape()); if(!static_cast<OpcodeCollisionSubMeshShape*>(shape.getPointer())->init(meshName , subMeshName , position , orient , scale)) { shape.setNull(); return ICollisionShapePtr(); } addCollisionShape(shape); } return shape; }
// 从一个顶点和索引缓冲区创建碰撞模型 ICollisionShapePtr OpcodeCollisionSystem::createVertexCollisionShape(const String &name , const Vector3 *vertexBuffer , size_t vertexCount , bool autoDeleteVertex , const uint16 *indexBuffer , size_t indexCount , bool autoDeleteIndex) { //check if a shape with this name already exists ICollisionShapePtr shape = getCollisionShape(OpcodeCollisionVertexShape::SHAPE_TYPE , name); if(shape.isNull()) { shape.bind(new OpcodeCollisionVertexShape()); if(!static_cast<OpcodeCollisionVertexShape*>(shape.getPointer())->init(name , vertexBuffer , vertexCount , autoDeleteVertex , indexBuffer , indexCount , autoDeleteVertex)) { shape.setNull(); return ICollisionShapePtr(); } addCollisionShape(shape); } return shape; }
BulletDS::BulletDS(SP::BulletWeightedShape weightedShape, SP::SiconosVector position, SP::SiconosVector velocity, SP::SiconosVector relative_position, SP::SiconosVector relative_orientation, int group) : NewtonEulerDS(position, velocity, weightedShape->mass(), weightedShape->inertia()), _weightedShape(weightedShape), _collisionObjects(new CollisionObjects()) { SiconosVector& q = *_q; /* with 32bits input ... 1e-7 */ if (fabs(sqrt(pow(q(3), 2) + pow(q(4), 2) + pow(q(5), 2) + pow(q(6), 2)) - 1.) >= 1e-7) { RuntimeException::selfThrow( "BulletDS: quaternion in position parameter is not a unit quaternion " ); } /* initialisation is done with the weighted shape as the only one * collision object */ if (! relative_position) { relative_position.reset(new SiconosVector(3)); relative_position->zero(); } if (! relative_orientation) { relative_orientation.reset(new SiconosVector(4)); relative_orientation->zero(); (*relative_orientation)(1) = 1; } addCollisionShape(weightedShape->collisionShape(), relative_position, relative_orientation, group); }
xy::Entity::Ptr TrackSection::create(xy::MessageBus& mb, float height) { XY_ASSERT(!m_uids.empty(), "parts not yet cached!"); auto body = xy::Component::create<xy::Physics::RigidBody>(mb, xy::Physics::BodyType::Kinematic); xy::Physics::CollisionFilter cf; cf.categoryFlags |= PhysCat::Wall; cf.maskFlags |= PhysCat::SmallBody; auto uid = m_uids[m_index].id; //top two points of centre part sf::Vector2f tl(sectionSize, connectionHeight); sf::Vector2f tr(0.f, connectionHeight); //upper half of ID represents top 3 connections auto bits = uid & 0xf; XY_ASSERT(bits != 0 && bits != 0x8, "can't have empty segments"); if (bits & 0x4) { //top left xy::Physics::CollisionEdgeShape es(connections[0].first); es.setFilter(cf); body->addCollisionShape(es); es.setPoints(connections[0].second); body->addCollisionShape(es); if (tl.x > 0.f) tl.x = 0.f; if (tr.x < connectionWidth + connectionGap) tr.x = connectionWidth + connectionGap; } if (bits & 0x2) { //top middle xy::Physics::CollisionEdgeShape es(connections[1].first); es.setFilter(cf); body->addCollisionShape(es); es.setPoints(connections[1].second); body->addCollisionShape(es); if (tl.x > connectionWidth + connectionGap) tl.x = connectionWidth + connectionGap; if (tr.x < (connectionWidth * 2.f) + connectionGap) tr.x = (connectionWidth * 2.f) + connectionGap; } if (bits & 0x1) { //top right xy::Physics::CollisionEdgeShape es(connections[2].first); es.setFilter(cf); body->addCollisionShape(es); es.setPoints(connections[2].second); body->addCollisionShape(es); if (tl.x >(connectionWidth * 2.f) + connectionGap) tl.x = (connectionWidth * 2.f) + connectionGap; if (tr.x < sectionSize) tr.x = sectionSize; } if (bits == (0x4 | 0x1)) { //we have left and right but no middle xy::Physics::CollisionEdgeShape es( { sf::Vector2f(connectionWidth + connectionGap, connectionHeight), sf::Vector2f(sectionSize / 2.f, connectionHeight + 30.f), //just enough to prevent squashed balls sf::Vector2f((connectionWidth * 2.f) + connectionGap, connectionHeight) }); es.setFilter(cf); body->addCollisionShape(es); } //bottom two points of centre part sf::Vector2f bl(sectionSize, connectionHeight * 3.f); sf::Vector2f br(0.f, connectionHeight * 3.f); //else bottom 3 bits = (uid & 0xf0) >> 4; XY_ASSERT(bits != 0 && bits != 0x8, "can't have empty segments"); if (bits & 0x4) { //bottom left xy::Physics::CollisionEdgeShape es(connections[3].first); es.setFilter(cf); body->addCollisionShape(es); es.setPoints(connections[3].second); body->addCollisionShape(es); if (bl.x > 0.f) bl.x = 0.f; if (br.x < connectionWidth + connectionGap) br.x = connectionWidth + connectionGap; } if (bits & 0x2) { //bottom middle xy::Physics::CollisionEdgeShape es(connections[4].first); es.setFilter(cf); body->addCollisionShape(es); es.setPoints(connections[4].second); body->addCollisionShape(es); if (bl.x > connectionWidth + connectionGap) bl.x = connectionWidth + connectionGap; if (br.x < (connectionWidth * 2.f) + connectionGap) br.x = (connectionWidth * 2.f) + connectionGap; } if (bits & 0x1) { //bottom right xy::Physics::CollisionEdgeShape es(connections[5].first); es.setFilter(cf); body->addCollisionShape(es); es.setPoints(connections[5].second); body->addCollisionShape(es); if (bl.x >(connectionWidth * 2.f) + connectionGap) bl.x = (connectionWidth * 2.f) + connectionGap; if (br.x < sectionSize) br.x = sectionSize; } if (bits == (0x4 | 0x1)) { //we have left and right but no middle xy::Physics::CollisionEdgeShape es({ sf::Vector2f(connectionWidth + connectionGap, sectionSize - connectionHeight), sf::Vector2f((connectionWidth * 2.f) + connectionGap, sectionSize - connectionHeight) }); es.setFilter(cf); body->addCollisionShape(es); } //create centre part xy::Physics::CollisionEdgeShape es({ tl, bl }); es.setFilter(cf); body->addCollisionShape(es); es.setPoints({ tr, br }); body->addCollisionShape(es); body->setLinearVelocity({ 0.f, m_initialVelocity }); auto controller = xy::Component::create<SectionController>(mb, *this); auto model = m_meshRenderer.createModel(uid, mb); if (m_trackMaterial) { for (auto i = 0u; i < m_uids[m_index].barrierOffset; ++i) { model->setSubMaterial(*m_trackMaterial, i); } } if (m_barrierMaterial) { for (auto i = m_uids[m_index].barrierOffset; i < model->getMesh().getSubMeshCount(); ++i) { model->setSubMaterial(*m_barrierMaterial, i); } } auto entity = xy::Entity::create(mb); entity->setPosition((xy::DefaultSceneSize.x - sectionSize) / 2.f, height); entity->addComponent(body); entity->addComponent(controller); entity->addComponent(model); m_index = (m_index + 1) % m_uids.size(); //remember to do this as late as possible return std::move(entity); }