XSI Vertex Animation and OGRE Facial Animation

目前OGRE只有XSI 5.x、Maya的导出器及oFusion Pro for 3ds max(收费)支持顶点动画的导出,而在众多建模软件中XSI(http://www.softimage.com/)以其对变形动画的支持最为突出,OGRE提供的Facial Demo中使用的Dr. Bunsen的头就是XSI中提供的一个示例动画,该模型就是使用对顶点簇(cluster)的位置改变来产生动画。

XSI变形动画(顶点动画)的制作
1、 将Mode改为Shape Modeling Mode;
2、将关键帧移至期望的动画开始处存储并应用物体或顶点簇(cluster)的shape key,该key记录了物体的初始形状;
3、将关键帧移至所期望的变形动画结束处,利用Animation中的Deform对物体或顶点簇产生变形;
4、存储并应用shape key,该key记录了物体变形后的状态;
5、你可以在Animation中的Shape菜单的Shape Manager…改变物体变形的程度。
在OGRE中播放顶点动画
我们需要从 ogre 官方网站 上下载XSI模型导出器    安装后(安装过程中需要  XSI 5.x  的目录)在 XSI    Export  中就会出现  OGRE mesh/Skeleton  菜单项,你需要按照下列步骤来导出顶点动画模型: SoftImage XSI 5.0 Exporter v1.2.3
1、 选中需要导出的模型;
2、在ogre export的Basic页中输入导出mesh的路径及文件名,在Materials页中填入导出材质的路径及文件名(需要说明的是在该导出器中材质导出有BUG,不一定能正确导出材质),在Animation页中选中Export Vertex Animation复选框(其实,如果选中物体中有Vertex Animation或Export Skeleton,那么复选框会自动选上),如果模型包含动画,则在Animation栏目会出现动画的信息,包括:名字、开始帧、结束帧、采样频率;
3、按ok导出。
我们可以在ogre提供的Facial Demo基础上修改代码以适合导出的模型,同时,你可以利用 OgreCommandLineTools 中的OgreXmlConverter来将.mesh文件逆向转换为.xml文件便于研究模型及动画数据的格式,下面给出了一个简单球体顶点动画模型及其xml数据:
XSI Vertex Animation and OGRE Facial Animation_第1张图片
<mesh>
    <submeshes>
        <submesh material="Scene_Material" usesharedvertices="false" use32bitindexes="false" operationtype="triangle_list">
            <faces count="288">
                <face v1="0" v2="1" v3="2" />
                                                                 :(省略)
                                                                 :
                <face v1="145" v2="16" v3="17" />
            </faces>
            <geometry vertexcount="146">
                <vertexbuffer positions="true"> [1] 
                    <vertex>
                        <position x="-3.21394" y="-9.39693" z="1.16978" />
                    </vertex>
                                                                                             :
                                                                                             :
                    <vertex>
                        <position x="-3.21394" y="9.39693" z="-1.16978" />
                    </vertex>
                </vertexbuffer>
                <vertexbuffer normals="true"> [2] 
                    <vertex>
                        <normal x="-0.321129" y="-0.939795" z="0.116881" />
                    </vertex>
                                                                                             :
                                                                                             :
                    <vertex>
                        <normal x="-0.321129" y="0.939795" z="-0.116881" />
                    </vertex>
                </vertexbuffer>
            </geometry>
        </submesh>
    </submeshes>
    <submeshnames>
        <submeshname name="sphere" index [3]  ="0" />
    </submeshnames>
    <poses> [4] 
        <pose target="submesh" index="0" name="s1" /> [5] 
        <pose target="submesh" index="0" name="s2"> [6] 
            <poseoffset index [7]  ="0" x="0" y="-0.457566" z="0.0569602" />
                                                                                             :
                                                                                             :
            <poseoffset index="145" x="0" y="0.457566" z="-0.0569602" />
        </pose>
    </poses>
    <animations> [8] 
        <animation name="ss" length="1.72414"> [9] 
            <tracks> [10] 
                <track target="submesh" index="0" type="pose"> [11] 
                    <keyframes> [12] 
                        <keyframe time="0">
                            <poseref poseindex="0" influence="1" /> [13] 
                        </keyframe>
                        <keyframe time="0.0344828">
                            <poseref poseindex="0" influence="1" /> [14] 
                        </keyframe>
                        <keyframe time="1.68966">
                            <poseref poseindex="0" influence="0.00123248" /> [15] 
                            <poseref poseindex="1" influence="0.998767" /> [16] 
                        </keyframe>
                        <keyframe time="1.72414" />
                    </keyframes>
                </track>
            </tracks>
        </animation>
    </animations>
</mesh> 

OGRE程序实现分下面步骤:

1、  由于OGRE中采用了CEGUI(Crazy Eddie's GUI System)作为GUI,所以我们可以通过其提供的CELayoutEditor来编辑出想要的GUI。下图是该程序的一个简单的GUI,右边空白区域作为场景渲染区;

2、 将其保存成一个layout文件,如aaa.layout,并拷贝至OGRESDK/media/gui下。

下面我着重对程序代码进行说明:
000001     #include <CEGUI/CEGUIImageset.h> 
000002     #include <CEGUI/CEGUISystem.h> 
000003     #include <CEGUI/CEGUILogger.h> 
000004     #include <CEGUI/CEGUISchemeManager.h> 
000005     #include <CEGUI/CEGUIWindowManager.h> 
000006     #include <CEGUI/CEGUIWindow.h> 
000007     #include <CEGUI/elements/CEGUICombobox.h> 
000008     #include <CEGUI/elements/CEGUIListbox.h> 
000009     #include <CEGUI/elements/CEGUIListboxTextItem.h> 
000010     #include <CEGUI/elements/CEGUIPushButton.h> 
000011     #include <CEGUI/elements/CEGUIScrollbar.h> 
000012     #include <CEGUI/elements/CEGUIStaticImage.h> 
000013     #include <CEGUI/elements/CEGUIRadioButton.h> 
000014     #include "OgreCEGUIRenderer.h" 
000015     #include "OgreCEGUIResourceProvider.h" 
000016     #include "ExampleApplication.h" 
000017     
000018     // 将OGRE中的鼠标按键映射成CEGUI的按键 
000019    CEGUI::MouseButton convertOgreButtonToCegui( int buttonID) 
000020    { 
000021        switch (buttonID) 
000022        { 
000023        case MouseEvent::BUTTON0_MASK: 
000024             return CEGUI::LeftButton; 
000025        case MouseEvent::BUTTON1_MASK: 
000026             return CEGUI::RightButton; 
000027        case MouseEvent::BUTTON2_MASK: 
000028             return CEGUI::MiddleButton; 
000029        case MouseEvent::BUTTON3_MASK: 
000030             return CEGUI::X1Button; 
000031        default: 
000032             return CEGUI::LeftButton; 
000033        } 
000034    } 
000035     
000036    AnimationState* morphAnimState;     // 定义用于自动播放的变形动画的指针 
000037    AnimationState* manualAnimState; // 定义用于手动播放的变形动画的指针 
 000038    VertexPoseKeyFrame* manualKeyFrame; // 定义用于手动播放VertexPose关键帧指针 
000039     
 000040    String scrollbarNames = "aaa/Morph_Scroll";     // 用于产生横向滚动条状态变化时,确定是哪个滚动条(当然这是针对有多个滚动条的情况) 
000041     
000042    CEGUI::Scrollbar* scrollbars;     // 滚动条指针,通过后面的代码从layout文件中获取 
000043     
000044     // 定义GUI事件监听器类 
 000045     class GuiFrameListener : public ExampleFrameListener, public MouseMotionListener, public MouseListener 
000046    { 
000047     private: 
000048        CEGUI::Renderer* mGUIRenderer; 
000049         bool mShutdownRequested; 
000050     
000051     public: 
 000052        GuiFrameListener(RenderWindow* win, Camera* cam, CEGUI::Renderer* renderer) 
000053            : ExampleFrameListener(win, cam, true, true), 
000054            mGUIRenderer(renderer), 
000055            mShutdownRequested(false) 
000056        { 
000057            mEventProcessor->addMouseMotionListener(this); // 添加鼠标动作监听器 
000058            mEventProcessor->addMouseListener(this);     // 添加鼠标监听器 
000059            mEventProcessor->addKeyListener(this);         // 添加键盘按键监听器 
000060        } 
000061     
000062         // 设置退出标志 
000063         void requestShutdown( void) 
000064        { 
000065            mShutdownRequested = true; 
000066        } 
000067     
000068         bool frameEnded( const FrameEvent& evt) 
000069        { 
000070             if (mShutdownRequested) 
000071                 return false; 
000072             else 
000073                 return ExampleFrameListener::frameEnded(evt); 
000074        } 
000075     
000076         void mouseMoved (MouseEvent *e) 
000077        { 
000078             // CEGUI类方法,将鼠标移动事件及其参数“注入”GUI系统以便处理 
000079            CEGUI::System::getSingleton().injectMouseMove( 
000080                e->getRelX() * mGUIRenderer->getWidth(), 
000081                e->getRelY() * mGUIRenderer->getHeight()); 
000082             // OGRE类方法,销毁该事件消息,以使其不被它的产生者以默认的方式来处理 
000083            e->consume(); 
000084        } 
000085     
000086         void mouseDragged (MouseEvent *e) 
000087        { 
000088            mouseMoved(e); 
000089        } 
000090     
000091         void mousePressed (MouseEvent *e) 
000092        { 
000093            CEGUI::System::getSingleton().injectMouseButtonDown( 
000094                convertOgreButtonToCegui(e->getButtonID())); 
000095            e->consume(); 
000096        } 
000097     
000098         void mouseReleased (MouseEvent *e) 
000099        { 
000100            CEGUI::System::getSingleton().injectMouseButtonUp( 
000101                convertOgreButtonToCegui(e->getButtonID())); 
000102            e->consume(); 
000103        } 
000104     
000105         void mouseClicked(MouseEvent* e) {} 
000106         void mouseEntered(MouseEvent* e) {} 
000107         void mouseExited(MouseEvent* e) {} 
000108     
000109         void keyPressed(KeyEvent* e) 
000110        { 
000111             if(e->getKey() == KC_ESCAPE) 
000112            { 
000113                mShutdownRequested = true; 
000114                e->consume(); 
000115                 return; 
000116            } 
000117     
000118             if (e->getKey() == KC_SYSRQ) 
000119            { 
000120                mWindow->writeContentsToTimestampedFile("screenshot", ".png"); 
000121            } 
000122     
000123            CEGUI::System::getSingleton().injectKeyDown(e->getKey()); 
000124            CEGUI::System::getSingleton().injectChar(e->getKeyChar()); 
000125            e->consume(); 
000126        } 
000127     
000128         void keyReleased(KeyEvent* e) 
000129        { 
000130            CEGUI::System::getSingleton().injectKeyUp(e->getKey()); 
000131            e->consume(); 
000132        } 
000133         void keyClicked(KeyEvent* e) 
000134        { 
000135             // 什么事都不做 
000136            e->consume(); 
000137        } 
000138     
000139         bool frameStarted( const FrameEvent& evt) 
000140        { 
000141            morphAnimState->addTime(evt.timeSinceLastFrame); 
000142             return ExampleFrameListener::frameStarted(evt); 
000143     
000144        } 
000145    }; 
000146     
000147     // 定义变形动画的应用程序类主类 
000148     class MorphApplication : public ExampleApplication 
000149    { 
000150     private: 
 000151        CEGUI::OgreCEGUIRenderer* mGUIRenderer; // 定义OGRE中CEGUI的渲染器指针 
000152        CEGUI::System* mGUISystem; // 定义GUI系统指针 
000153        CEGUI::Listbox* mList;     // 列表框指针 
000154     
000155     public: 
000156        FacialApplication() 
000157            : mGUIRenderer(0), 
000158            mGUISystem(0) 
000159        { 
000160     
000161        } 
000162     
000163        ~FacialApplication() 
000164        { 
000165             if(mGUISystem) 
000166            { 
000167                delete mGUISystem; 
000168                mGUISystem = 0; 
000169            } 
000170             if(mGUIRenderer) 
000171            { 
000172                delete mGUIRenderer; 
000173                mGUIRenderer = 0; 
000174            } 
000175        } 
000176     
000177     protected: 
000178     
000179         bool mPlayAnimation; // 自动/手动控制Radio Button对应变量 
000180     
000181         // 滚动条状态改变事件相应函数 
000182         bool handleScrollChanged( const CEGUI::EventArgs& e) 
000183        { 
000184             if (!mPlayAnimation) 
000185            { 
 000186                 const CEGUI::WindowEventArgs& args = static_cast< const CEGUI::WindowEventArgs&>(e); 
000187                 // 得到Scroll的名字 
000188                String name = args.window->getName().c_str(); 
000189                 // 判断是否是我想要改变的那一个(在多个scrollbar时) 
000190                 if(scrollbarNames == name) 
000191                { 
000192                     // 调试信息:显示scrollbar当前位置(用于调试) 
 000193                    mWindow->setDebugText(StringConverter::toString(scrollbars->getScrollPosition())); 
000194                     // 根据滚动条的位置更新顶点变形百分比 
000195                    manualKeyFrame->updatePoseReference( 
000196                        1, scrollbars->getScrollPosition()); 
000197                     // 得到 AnimationStateSet(动画状态集)指针, 
000198                     // 并通知当前动画状态已经改变 
000199                    manualAnimState->getParent()->_notifyDirty(); 
000200                } 
000201            } 
000202             return true; 
000203     
000204        } 
000205     
000206         // Radio Button状态改变响应函数 
000207         bool handleRadioChanged( const CEGUI::EventArgs& e) 
000208        { 
000209            mPlayAnimation = !mPlayAnimation; 
000210            morphAnimState->setEnabled(mPlayAnimation); 
000211            manualAnimState->setEnabled(!mPlayAnimation); 
000212             // 允许/禁止scrollbar 
000213            scrollbars->setEnabled(!mPlayAnimation); 
000214     
000215             return true; 
000216     
000217        } 
000218     
000219         // List状态改变响应函数 
000220         bool handleListBoxChanged( const CEGUI::EventArgs& e) 
000221        { 
000222             // 根据选择项,改变多边形模式 
 000223             if(mList->getFirstSelectedItem()->getText() == CEGUI::String("Solid Mode")) 
000224                mCamera->setPolygonMode(PM_SOLID); 
 000225             else if(mList->getFirstSelectedItem()->getText() == CEGUI::String("Wireframe Mode")) 
000226                mCamera->setPolygonMode(PM_WIREFRAME); 
000227             else 
000228                mCamera->setPolygonMode(PM_POINTS); 
000229             return true; 
000230        } 
000231     
000232         // 创建场景函数,重写ExampleApplication::createScene() 
000233         void createScene( void) 
000234        { 
000235             // 设置环境光 
000236            mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5)); 
000237     
000238             // 创建一个点光源 
000239            Light* l = mSceneMgr->createLight("MainLight"); 
000240             // 设置光源位置 
000241            l->setPosition(20,80,50); 
000242             // 设置表面反射的漫射光颜色 
000243            l->setDiffuseColour(0.5, 0.0, 0.5); 
000244     
000245             // 创建一个点光源 
000246            l = mSceneMgr->createLight("MainLight2"); 
000247             // 设置光源位置 
000248            l->setPosition(-120,-80,-50); 
000249             // 设置表面反射的漫射光颜色 
000250            l->setDiffuseColour(0.7, 0.7, 0.6); 
000251     
000252             // 载入mesh 
 000253            MeshPtr mesh = MeshManager::getSingleton().load("ss.mesh", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); 
000254            Animation* anim = mesh->createAnimation("smile", 0); 
000255             // 创建顶点动画轨迹,参数说明请参考OGRE中的人脸动画一文 
000256            VertexAnimationTrack* track = anim->createVertexTrack(1, VAT_POSE); 
000257             // 创建时间位置为0的关键帧并将其添加到动画中 
000258            manualKeyFrame = track->createVertexPoseKeyFrame(0); 
 000259             // 添加一个新的pose参考,第一个参数为poseindex,第二个参数为效果值(这里是0%) 
000260            manualKeyFrame->addPoseReference(1, 0.0f); 
000261     
000262             // 创建GUI渲染器对象和GUI系统对象 
000263            mGUIRenderer = new CEGUI::OgreCEGUIRenderer(mWindow, 
000264                Ogre::RENDER_QUEUE_OVERLAY, false, 3000, mSceneMgr); 
000265     
000266            mGUISystem = new CEGUI::System(mGUIRenderer); 
000267             // 开启GUI系统日志 
000268            CEGUI::Logger::getSingleton().setLoggingLevel(CEGUI::Informative); 
000269             // 创建实体,命名为Head1 
000270            Entity* head = mSceneMgr->createEntity("Head1", "ss.mesh"); 
000271             // 从mesh中取得名字为ss的自动动画(请参考xml中的tag<animations>) 
000272            morphAnimState = head->getAnimationState("ss"); 
000273            morphAnimState->setEnabled(true); 
 000274             // 得到前面mesh->createAnimation("smile", 0)创建的手动动画smile,并将其时间位置置为0 
000275            manualAnimState = head->getAnimationState("smile"); 
000276            manualAnimState->setTimePosition(0); 
000277             // 创建场景子节点,并将实体head加入到其中 
 000278            SceneNode* headNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); 
000279            headNode->attachObject(head); 
000280             // 设置摄像机参数 
000281            mCamera->setPosition(0, 0, 50); 
000282            mCamera->lookAt(0,0,0); 
000283     
000284             // 载入GUI皮肤元素,并将layout文件作为一个sheet(页)添加进GUI系统对象中 
000285            CEGUI::SchemeManager::getSingleton().loadScheme( 
000286                (CEGUI::utf8*)"TaharezLookSkin.scheme"); 
000287            mGUISystem->setDefaultMouseCursor( 
000288                (CEGUI::utf8*)"TaharezLook", (CEGUI::utf8*)"MouseArrow"); 
000289            mGUISystem->setDefaultFont((CEGUI::utf8*)"BlueHighway-12"); 
000290     
000291            CEGUI::Window* sheet = 
000292                CEGUI::WindowManager::getSingleton().loadWindowLayout( 
000293                (CEGUI::utf8*)"aaa.layout"); 
000294            mGUISystem->setGUISheet(sheet); 
000295             // 得到窗口管理器 
 000296            CEGUI::WindowManager& wmgr = CEGUI::WindowManager::getSingleton(); 
000297             // 从窗口管理器中得到滚动条对象 
000298            scrollbars = static_cast<CEGUI::Scrollbar*>( 
000299                wmgr.getWindow(scrollbarNames)); 
000300             // 注册滚动条事件处理函数 
000301            scrollbars->subscribeEvent( 
000302                CEGUI::Scrollbar::EventScrollPositionChanged, 
000303                CEGUI::Event::Subscriber(&FacialApplication::handleScrollChanged, this)); 
000304             // 缺省禁止使用滚动条 
000305            scrollbars->setEnabled(false); 
000306             // 得到Animation Radio按钮对象 
000307            CEGUI::RadioButton* btn = static_cast<CEGUI::RadioButton*>( 
000308                wmgr.getWindow((CEGUI::utf8*)"aaa/Radio/Play")); 
000309             // 允许使用Radio按钮 
000310            btn->setSelected(true); 
000311             // 注册该Radio按钮事件处理函数 
000312            btn->subscribeEvent(CEGUI::RadioButton::EventSelectStateChanged, 
 000313                CEGUI::Event::Subscriber(&FacialApplication::handleRadioChanged, this)); 
000314     
000315            mPlayAnimation = true; 
 000316             // 得到List对象,并向其中加入Solid Mode/Wireframe Mode/Point Mode三个选项 
000317            mList = static_cast<CEGUI::Listbox*>( 
000318                wmgr.getWindow((CEGUI::utf8*)"aaa/ListBox/PolygonMode")); 
000319            CEGUI::ListboxTextItem *listboxitem = 
000320                new CEGUI::ListboxTextItem ("Solid Mode"); 
 000321            listboxitem->setSelectionBrushImage("TaharezLook", "ListboxSelectionBrush"); 
000322            listboxitem->setSelected(mList->getItemCount() == 0); 
000323            mList->addItem(listboxitem); 
000324            listboxitem = new CEGUI::ListboxTextItem("Wireframe Mode"); 
 000325            listboxitem->setSelectionBrushImage("TaharezLook", "ListboxSelectionBrush"); 
000326            mList->addItem(listboxitem); 
000327            listboxitem = new CEGUI::ListboxTextItem("Point Mode"); 
 000328            listboxitem->setSelectionBrushImage("TaharezLook", "ListboxSelectionBrush"); 
000329            mList->addItem(listboxitem); 
000330             // 注册List选择事件处理函数 
000331            mList->subscribeEvent(CEGUI::Listbox::EventSelectionChanged , 
 000332                CEGUI::Event::Subscriber(&FacialApplication::handleListBoxChanged , this)); 
000333            mCamera->setPolygonMode(PM_SOLID); 
000334        } 
000335     
000336         // 创建帧(事件)监听器 
000337         void createFrameListener( void) 
000338        { 
 000339            mFrameListener= new GuiFrameListener(mWindow, mCamera, mGUIRenderer); 
000340            mRoot->addFrameListener(mFrameListener); 
000341        } 
000342     
000343         void setupEventHandlers( void) 
000344        { 
000345        } 
000346     
000347     
000348         void setupLoadedLayoutHandlers( void) 
000349        { 
000350        } 
000351     
000352         bool handleQuit( const CEGUI::EventArgs& e) 
000353        { 
000354             static_cast<GuiFrameListener*>(mFrameListener)->requestShutdown(); 
000355             return true; 
000356        } 
000357     
000358     
000359    }; 
000360     
000361     #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 
000362     #define WIN32_LEAN_AND_MEAN 
000363     #include "windows.h" 
000364     
000365    INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT ) 
000366     #else 
000367     int main( int argc, char *argv[]) 
000368     #endif 
000369    { 
000370     
000371         // 创建应用程序对象 
000372        FacialApplication app; 
000373     
000374        try { 
000375            app.go();     // 运行 
000376        } catch( Ogre::Exception& e ) { 
000377     #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 
 000378            MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL); 
000379     #else 
000380            std::cerr << "An exception has occured: " << 
000381                e.getFullDescription().c_str() << std::endl; 
000382     #endif 
000383        } 
000384     
000385     
000386         return 0; 
000387    } 

程序运行的最终效果:

XSI Vertex Animation and OGRE Facial Animation_第2张图片

 [1]顶点坐标
 [2]顶点法线
 [3]Submesh的索引号,按照submeshs中submesh出现的先后顺序还确定。
 [4]该tag下pose的poseoffset用于标明index对应顶点产生变形后的偏移量,在手动动画中我们将根据横向滑块位置的百分比来确定顶点变化偏移量的百分之几。
 [5]索引号为0的顶点动画,在手动动画关键帧的 addPoseReference 与 updatePoseReference 函数的第一个参数中引用。
 [6]索引号为1的顶点动画。
 [7]顶点的索引号,按照vertexbuffer中vertex出现的先后次序来确定。
 [8]定义自动播放的动画。
 [9]定义一个名字为ss长度为1.72414(该值可作为横向滑块的长度,请参考layout说明)的动画。
 [10]定义动画轨迹。
 [11]针对索引号为0的submesh定义类型为pose的动画轨迹。
 [12]定义关键帧
 [13]在帧时间为0时,让索引号为0的顶点动画达到100%变形,因为0号pose没有poseoffset数据,因而表现为保持原来形态不变。
 [14]同上。
 [15]产生?%的变形,但是由于没有poseoffset数据,故实际上没有任何效果。
 [16]在帧时间为1.68966时,让索引号为1的顶点动画达到99%形变,也就是说从帧时间0到此时是一个渐变的效果,OGRE会根据时间间隔与端点时间的形变百分比自动计算中间的形变百分比。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++是一种广泛使用的编程语言,它是由Bjarne Stroustrup于1979年在新泽西州美利山贝尔实验室开始设计开发的。C++是C语言的扩展,旨在提供更强大的编程能力,包括面向对象编程和泛型编程的支持。C++支持数据封装、继承和多态等面向对象编程的特性和泛型编程的模板,以及丰富的标准库,提供了大量的数据结构和算法,极大地提高了开发效率。12 C++是一种静态类型的、编译式的、通用的、大小写敏感的编程语言,它综合了高级语言和低级语言的特点。C++的语法与C语言非常相似,但增加了许多面向对象编程的特性,如类、对象、封装、继承和多态等。这使得C++既保持了C语言的低级特性,如直接访问硬件的能力,又提供了高级语言的特性,如数据封装和代码重用。13 C++的应用领域非常广泛,包括但不限于教育、系统开发、游戏开发、嵌入式系统、工业和商业应用、科研和高性能计算等领域。在教育领域,C++因其结构化和面向对象的特性,常被选为计算机科学和工程专业的入门编程语言。在系统开发领域,C++因其高效性和灵活性,经常被作为开发语言。游戏开发领域中,C++由于其高效性和广泛应用,在开发高性能游戏和游戏引擎中扮演着重要角色。在嵌入式系统领域,C++的高效和灵活性使其成为理想选择。此外,C++还广泛应用于桌面应用、Web浏览器、操作系统、编译器、媒体应用程序、数据库引擎、医疗工程和机器人等领域。16 学习C++的关键是理解其核心概念和编程风格,而不是过于深入技术细节。C++支持多种编程风格,每种风格都能有效地保证运行时间效率和空间效率。因此,无论是初学者还是经验丰富的程序员,都可以通过C++来设计和实现新系统或维护旧系统。3

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值