zoukankan      html  css  js  c++  java
  • Havok Physics物理引擎的学习入门

        

    这几天在看Intel公司刚刚收购开放下载的havok物理引擎,有几点感受。为了研究havok,多么猥琐阴险狡诈的招都被我使了出来,在google上搜过n个正则关键字,去过专业的物理研究论坛,去了havok的官方网站,去了Interhavok论坛。最后没找到多少资料,没找到一个小例子。所以只得再havok SDKsDocDemo下面逛,看英文,猜代码意图。浑浑噩噩的过了两天。

    Havokdemo看过的肯定知道,框架做得相当复杂和诡异,其实并不适合去学习。The framework of the demos is very complex and esoteric. I do not want to understand these complex framework, Because I have a practical application in my framework, companies have the framework of the company, no one will want to make their own framework replaced for a physical engine.这是我发在havok论坛上的帖子。

    这也难怪,havok引擎刚刚开放下载,国内应用的都少,教程更是别提。我这几天算是过得比较痛苦,写个简单的入门文档,希望抛砖引玉,帮大家简单入入门,完全没有误人子弟的意思,大家别拍我~ ~我做的主要是havok的刚体碰撞。简单的20 * 20 的正方体自由下落在一平面上。

    首先,关于Havok的几个简单的物理概念:

    hkpWorld havok的物理世界场景 场景有其自己的属性,如万有引力等,每个havok的仿真场景可以有一个或者多个hkpWorld的实例。

    hkpRigidBody havok的刚体,刚体可以有自己的运动属性,并能通过setMotionType来设置修改。

    hkVisualDebugger 关于havok的一个很好的调试工具

    下面是整个程序的简单代码,没有用图形库输出图形,可以通过havok自带的工具VisualDebugger工具来查看刚体。省略了部分内存方面的代码,我也不是很明白。

    int main(int argc, const char** argv)
    {
           {
                  // 创建physics world 通过填充hkpWorldCinfo
                  hkpWorld* physicsWorld;
                  {
                         // 创建物理世界:
                         hkpWorldCinfo worldInfo;
                         worldInfo.m_simulationType = hkpWorldCinfo::SIMULATION_TYPE_MULTITHREADED;
                         worldInfo.m_gravity.set(0.0f, -9.8f, 0.0f);
                         physicsWorld = new hkpWorld(worldInfo);
                  }
                  physicsWorld->markForWrite();
                  {
                         hkpAgentRegisterUtil::registerAllAgents( physicsWorld->getCollisionDispatcher() );
                  }
                  // 在这里创建我们的刚体模拟
                  setupPhysics( physicsWorld );
                  // 初始化VisualDebugger工具
                  hkVisualDebugger* vdb = setupVisualDebugger(context);

             hkReal timestep = 1.f / 60.f;
            int numSteps = int(60.f / timestep);
            for ( int i = 0; i < numSteps; ++i )
            {
                // 可以得到刚体的一些实时信息,借助图形库进行渲染
                hkVector4 pos = g_ball->getPosition();
                 printf("[%f,%f,%f]"n", pos(0), pos(1), pos(2));
            }  
           hkBaseSystem::quit();
           return 0;
    }

    void setupPhysics(hkpWorld* physicsWorld)
    {
           // 创建地面的 静态刚体
           {
                  hkpRigidBodyCinfo boxInfo;
                  hkVector4 boxSize(5.0f, 0.5f , 5.0f);
                  hkpBoxShape* boxShape = new hkpBoxShape(boxSize);
                  boxInfo.m_shape = boxShape;
                  boxInfo.m_motionType = hkpMotion::MOTION_FIXED;
                  boxInfo.m_position.set(0.0f, 0.0f, 0.0f);
                  boxInfo.m_restitution = 0.9f;

                  hkpRigidBody* floor = new hkpRigidBody(boxInfo);
                  boxShape->removeReference();
                  g_ball = floor;
                  physicsWorld->addEntity(floor);
                  floor->removeReference();
           }
    // 创建 20 * 20 的盒子
           const hkReal boxDim    = 0.2f;        // This is the size of the cube side of the box
           const hkReal boxRadius = boxDim * 0.01f; // 盒子的角度 这个有问题 原来这个是大小
           const hkReal gapx    = boxDim * 0.05f;           // This is the gap betwen boxes 间距是盒子大小的多少比率
           const hkReal gapy    = boxRadius;
           const hkReal heightOffGround = 10.0f;       // This is the height of the pyramid off the gound
           int    pyramidSize = 20;     // This is the number of boxes along the base (also vertically)
           // 长方体的长宽
           hkReal extendedBoxDimX = boxDim + gapx;
           //hkReal extendedBoxDimY = boxDim + gapy;
           hkReal extendedBoxDimZ = boxDim + gapx;
           hkVector4 startPos( 0.0f , heightOffGround + gapy + boxDim * 0.5f, 0.0f);
           // Build pyramid 构建
           {
                  hkVector4 boxRadii(boxDim *.5f, boxDim *.5f, boxDim *.5f);
                  hkpShape* boxShape = new hkpBoxShape( boxRadii , boxRadius );
                  // 变成横向的一块下来 20 * 20的盒子
                  for(int i=0; i<pyramidSize; i++)
                  {
                         // This constructs a row, from left to right 从左到右
                         hkVector4 start(0, 0, extendedBoxDimZ * i);
                         for(int j=0; j< pyramidSize; j++)
                         {
                                hkVector4 boxPos(start);
                                hkVector4 shift(j * extendedBoxDimX, 0.0f, 0.0f);
                                boxPos.setAdd4(boxPos, shift);
                                boxPos.setAdd4(boxPos, startPos);

                                hkpRigidBodyCinfo boxInfo;
                                //盒子的质量
                                boxInfo.m_mass = 100.0f;
                                // calculate the correct inertia 惯性与质量有关
                                hkReal d = boxInfo.m_mass * boxDim * boxDim / 6.0f;

                                // for small boxes increase inertia slightly
                                if ( boxRadius < 0.1f )
                                {
                                       d *= 2.0f;
                                       if ( boxRadius < 0.03f )
                                       {
                                              d *= 2.0f;
                                       }
                                }
                                boxInfo.m_inertiaTensor.setDiagonal(d,d,d);
                                boxInfo.m_shape = boxShape;
                                boxInfo.m_motionType = hkpMotion::MOTION_DYNAMIC;
                                boxInfo.m_position = boxPos;
                                boxInfo.m_restitution = 0.5f;                                   // 表面的弹力
                                boxInfo.m_friction = 0.6f;                                       // 表面的摩擦      
                                boxInfo.m_solverDeactivation = hkpRigidBodyCinfo::SOLVER_DEACTIVATION_MAX;
                                hkpRigidBody* boxRigidBody = new hkpRigidBody(boxInfo);
                                //将所有的刚体添加到世界中
                                physicsWorld->addEntity( boxRigidBody );
                                boxRigidBody->removeReference();                        
    }
                  }
                  boxShape->removeReference();
           }
    }

    我们只要在自己的代码中调用Havok API构建抽象的物理世界,抽象的物体,即给出物理世界的数据,就能直接通过hkVisualDebugger接口的socket连接发送世界数据到HavokVisualDebugger宿主程序,并在其可视化物理场景视图中显示出来。以下是在工具下的两张截图:

     

    demo框架中:

    程序的可运行代码:

    https://files.cnblogs.com/hellohuan/ConsoleMain.rar

  • 相关阅读:
    Azure 虚拟机安全加固整理
    AzureARM 使用 powershell 扩容系统磁盘大小
    Azure Linux 云主机使用Root超级用户登录
    Open edX 配置 O365 SMTP
    powershell 根据错误GUID查寻错误详情
    azure 创建redhat镜像帮助
    Azure Powershell blob中指定的vhd创建虚拟机
    Azure Powershell 获取可用镜像 PublisherName,Offer,Skus,Version
    Power BI 连接到 Azure 账单,自动生成报表,可刷新
    Azure powershell 获取 vmSize 可用列表的命令
  • 原文地址:https://www.cnblogs.com/hellohuan/p/1283410.html
Copyright © 2011-2022 走看看