秋梦无痕

一场秋雨无梦痕,春夜清风冻煞人。冬来冷水寒似铁,夏至京北蟑满城。

Avatar

OGRE初学者引导

from: 86vr.com
by: antking@gmail.cn

·1:初学者如何开始OGRE
·2:何时需要STLPORT ,为什么?
·3:Visual Studio.NET (VC7)
·4:GCC 3.3/3.4
·5:GCC 3.3/3.4 Dev C++
·6:GCC 3.3 Cygwin/MinGW
·7:Anjuta IDE
·8:你的第一个程序
·9:Frame Listeners
·10:总结

1 初学者如何开始OGRE

  欢迎进入OGRE的世界,你在看这篇文章说明你在开始学习OGRE了,希望这篇文件对你有用。
  这篇文件是假设你有下面的知识的情况下,如C++编程技巧,基本的操作系统使用的知识和一些关于3D方面的知识。我在这篇文章中,只是描述我知道的东西,对于其他的东西,请在OGRE论坛中讨论。对于高级用户,这篇文件对你也许不适合,因为,这是我第一次使用OGRE的一些想法。那时,我的C++不是很好,对VS也不是很了解,甚至不知道3D编程。(注意:这篇文章是关于VC7)

  首先,我们需要到OGRE下载页面下载“stable releases(完整版)”,下载后,将他解压到你建立的目录下(如:F:/OGRE)。文件将自动生成到OGRENEW目录下。这是必须的,如果你乱改了目录,也许会发生一些错误。
  如果你是使用WINDOWS,请到OGRE 下载页面下载"extras"版本。将他解压到你建立的目录下,如:F:/OGRE/OGRENEW。这些文件适合LINUX平台,并不包括对WINDOWS的支持。
  如果你在WINDOWS ,LINUX下使用GCC 2.9X,你将需要下载更多的东西,如STLPORT。如果你使用的是GCC 3.0,你将不需要做什么。

2 何时需要STLPORT ,为什么?

  如果你使用的是VC 6/7,你将需要STLPORT。因为STL在VC6/7中执行很慢,并有许多错误。OGRE是使用STL通过DLL使用MS STL;这将引起程序崩溃。OGRE是非常面向DLL的,因此MS STL不适合。而STLPORT很适合,他运行也比MS STL快。
  注意,在VS 2003,2005中,不需要STLPORT。
  如果你使用的是GCC 2.9X,你将需要STL;但在GCC 3.0中,不需要,他的STL得到了更新。
  STLPORT是标准模版函数库的“beefed up"版本,包含许多你所需要的基本的函数。关于STLPORT的使用和安装在下面介绍。

2.1 如何安装STLPORT?

* 从www.stlport.org下载最新的STLPORT(4.6.2),并解压他。
* 打开一个 命令行程序(注意:在WINDOWS NT/2000/XP中,是cmd.exe 而不是commamd.com),并改变他的路径STLPORT-4.6.2/SRC
* 如果你使用VC,请确定‘VCVARS32。BAT’是否运行在devstudio/vc6/bin or visualstudio.net/vc7/bin目录下。这些操作用于设置你的环境参数,并确定你的‘NMAKE’文件的位置。

  注意:这些命令必须在在同一行执行。VCVARS32。BAT只设置运行中的SHELL的环境,因此,如果你得到关于NMAKE的错误,请确定VCVARS32。BAT的版本是否和SHELL的版本相同。

* 如果你使用VC 6
* 键入‘nmake -f vc6.mak clean all'
* 键入 ’nmake -f vc6.mak install'
* 如果你使用的是VC NET
* 键入 ‘nmake -f vc7.mak clean all'
* 键入 ’nmake -f vc7.mak install'

  注意:如果你觉得麻烦的话,你可以添加NMAKE。EXE的路径到你的路径变量中。如果你这样做了,返回了”NOTE:“的错误。比如,如下的错误:"..\\stlport\ctime(25) : fatal error C1083: Cannot open include file:'../include/ctime': No such file or directory". 发生了这样的错误,你可以把VCVARS32。BAT拷贝到你的命令行程序相同的路径下,然后执行。如果你有其他的问题,请到OGRE的论坛中讨论。

* 如果你使用VS 2003
* 你将不需要做任何事情
* 如果你使用的是GCC 2.9X
* 键入 ‘./configure'
* 键入 ’make'
* 键入 ‘make install'
* 打开VC++,然后选择Tools/options...,将弹出一个对话框
* 在VC6中电击'Directories' 选行,在.NET中,是在Project/vc++下面。
* 确定STLPORT的路径在路径列表的最上面,他必须在最上面。
*(比如,他的头文件的路径可以如下:\STLport-4.6.2\stlport\)
*(比如,他的库文件的路径可以如下:\STLport-4.6.2\lib\)
* 保存并关闭
* 恭喜,STLPORT已经设置好了。

3 Visual Studio.NET (VC7)

  我们现在可以用OGRE开发了,在开发之前,请安装DX SDK,然后建立OGRE引擎和例子。他在OGRENEW/OGRE。DSW(VC6)或OGRENEW/OGRE。SLN(VC7)下,电击“BUILD ALL”。等待大约10-15分钟后,引擎,plugins,工具和例子将建立。
  如果你想运行这些例子,切换到ogrenew\Samples\Common\bin\Debug (在这里,我们使用的是DEBUG模式,如果你是RELEASE模式,就切换到RELEASE)。先将OGREMAIN。DLL(ogrenew/ogremain/lib/{debug|release})和其他的支持函数拷贝到ogremain/samples/common/bin/debug 下,然后就可以运行例子了。
  OGRE实际上是一个应用程序类库,他允许你很快速的开发你需要的应用程序。因为,他提供了你开发程序的3D基础,特别适合建立应用程序。
  我们首先建立一个"Empty Project",然后进行下面的设置:

* 右击项目名,选择”Properties".
* 添加the ogrenew\OgreMain\include 和ogrenew\Samples\Common\include 的路径到"additional includes"
* 添加ogrenew\OgreMain\lib\(Debug|Release) 到"library search paths"
* 添加OgreMain.lib 到"Additional Dependencies"
* 在C++/Code Generation模式下,选择"Runtime Library" to "Multi-threaded Debug DLL" (for debug-mode apps) 和 "Multi-threaded DLL" (For release-mode apps).

  你也可以把"Output Directory" 和"Working Directory" (under Debugging) 选上。他将把文件放到和已经运行的OGRE DLL相同目录下。如果你不这样做,你将拷贝许多OGRE DLL到output directory下。
  设置好后,我们就开始了一个main.cpp的文件。

4 GCC 3.3/3.4

  如果你使用LINUX或MingW for windows,那么下面的内容对你有用,先到OGRE下载LINUX版本。然后解压:

* tar xjf ./ogre*
* ./bootstrap (I've found not doing this in 1.0.0 RC1 causes later errors)
* ./configure && make
* make install (you may have to be root to do this)

  设置好后,你能通过./ogrenew/Samples/Common/bin 访问。

设置Anjuta IDE

  你可能想用IDE来便于你开发OGRE程序。这些还在讨论中,重点如下:

* 建立一个新的 Generic / Terminal
* change your Project->Project Options Configuration tab and Libraries sub-tab and add:

PKG_CHECK_MODULES(ogre, [OGRE >= 1.0.0])
AC_SUBST(ogre_CFLAGS)
AC_SUBST(ogre_LIBS)

* 然后进入Settings -> Compiler ,将连接选行添加${ogre_CFLAGS} to CFLAGS and ${ogre_LIBS}
* 最后,到Build->Autogenerate ,这将自动更新你的make and config文件。

5 GCC 3.3/3.4 Dev C++

如果你想在DC中使用OGRE,请按照下面的步骤:

1) 得到DC
2) 得到 DEVPAK (http://the-agency.sourceforge.net/xoops/modules/mydownloads/visit.php?cid=20&;;lid=64)
3) 得到OGRE 相关 DEVPAK (http://the-agency.sourceforge.net/xoops/modules/mydownloads/visit.php?cid=18&;;lid=65)
4) 安装DC
5) 安装Ogre DevPak
6) 安装Ogre Dependencies
7) 到例程目录。例如:C:\Development\Dev-Cpp\MyProjects\ogrenew\the-agency\Samples\ParticleFX
  然后打开。DEV文件,如:Sample_ParticleFX.dev
  将有一个警告出现,ignore 他。
  如果你得到另一个警告,说明你的文件在“build" 目录下。
8) 电击Project -> Project Options -> Directories ,然后设置:
  在"Libraries" 行,设置:

..\..\OgreMain\build
..\..\..\Dependencies\build

在"Include" tab,如下:
  
..\..\..\OgreMain\include
..\..\..\dependencies\devil\include
..\..\..\dependencies\freetype\include
..\..\..\dependencies\zlib\include
..\..\..\Samples\Common\include
..\..\..\Samples\ParticleFX\include

9) Hit Rebuild All (Ctrl + F11) -这将让Sample_ParticleFX.e xe 去建立一个目录,拷贝文件到C:\Development\Dev-Cpp\MyProje cts\ogrenew\Samples\Common\bin\Debug
10) 将dependencies\build 所有的DLL和C:\Development\Dev-Cpp\MyProjects\ogrenew\the-agency (use the Windows Search function) 下的文件拷贝到C:\Development\Dev-Cpp\MyProje cts\ogrenew\Samples\Common\bin\Debug
11) Rename PlatformManager_SDL.dll to OgrePlatform.dll
12) 通过下面的设置修改the Plugins.cfg 文件:
  1。Plugin=RenderSystem_Direct3D7
  1。Plugin=RenderSystem_Direct3D9
13) 完成后,运行Sample_ParticleFX.exe

6 GCC 3.3 Cygwin/MinGW

  Use the following if you don't want to have to setup the whole Dev-C++, but would like to have just a pure Cygwin/MinGW environment. Cygwin is used for it's building system, and since it can nicely cross-compile for MinGW, you will have a build that doesn't depend on Cygwin anymore.
  Note: This information is ripped from this thread (http://www.ogre3d.org/phpBB2/viewtopic.php?t=6964) in the the Ogre forums. (thx Lt.CYX & wumpus !)

1) Full cygwin install. Might need to add correct path to /etc/profile - it wasn't created on my first install.
2) get OGRE head from CVS (there is a tutorial on how to do it in the CVS Access section (http://www.ogre3d.org/modules.php?op=modload&;;amp;name=Sections&file=index&req=viewarticle&page=1&arttitle=Getting+Ogre+from+CVS) of OGRE Homepage). I put this on /usr/dev/ogre. This should also work with release version 1.0.0 or later - actually it worked with 1.0.0RC1, I used the linux/OSX version. Didn't try the win32, but it must be not that different.
3) get the MingW/Cygwin OGRE dependencies from the OGRE website. Either extract it to the root (thus creating /mingw) or to another directory and create a symlink /mingw pointing to the correct location (that's what I did).
4) download and install libtool 1.5.12 (or newer). Version 1.5.10 (the one that came with cygwin) generates a few errors we want to avoid.
4.1) download stable version from the libtool website (http://www.gnu.org/software/libtool/libtool.html)
4.2) configure, make and make install it.
4.3) cygwin has a libtool wrapper that automatically selects 1.5.10 or 1.4.3 - we need to make it use our 1.5.12 (or newer) version instead. For that, first we copy the libtool files from /usr/local/bin to /usr/autotool/1.5.x/bin (you'll have to create it), then edit /usr/bin/libtool to use that directory instead of the devel dir. It's just a quick, nasty hack - if someone knows of a better way to get the same results, please feel free to inform. This shouldn't break anything though.
4.4) (optional) go to a directory without configure.ac or configure.in files and do a 'libtool --version' to see if the first version number changed. If so, we can go to the next step.
5) follow the instructions on the beginning of this post (thanks to wumpus), which I modified slightly and reproduce here. This is to be done in the ogrenew directory:
5.1) export PATH="$PATH:/mingw/bin"
5.2) export ACLOCAL_FLAGS="-I /mingw/share/aclocal"
5.3) export PKG_CONFIG_PATH=/mingw/lib/pkgconfig
5.4) ./bootstrap
5.5) CC="gcc -mno-cygwin" CXX="g++ -mno-cygwin" CXXFLAGS="-O2 -I/mingw/include" LDFLAGS="-L/mingw/lib -L/lib/w32api" ./configure --with-ft-prefix=/mingw --with-platform=Win32 --with-gl-support=Win32 --disable-static --build="i686-pc-mingw32" --enable-direct3d
5.6) make
5.7) make install
6) set up your development tools.
6.1) passing the arguments "-lOgreMain -Wl,--enable-runtime-pseudo-reloc" to the linker will work.
6.2) as far as library directories go, you can link to cygwin/usr/local/lib and be happy about it.
6.3) include directories: cygwin/usr/local/include, cygwin/usr/local/include/OGRE and ogrenew/Samples/Common/include (if you are using the ExampleApplication class). Where I say cygwin/ I actually mean the cygwin path (such as c:/cygwin), and the same goes for ogrenew/ (c:/cygwin/usr/local/ogre/ogrenew, for example)
6.4) this is not required, but I tend to copy all required DLLs to my build directory: the one where MingW puts my compiled binary on. This way I keep my environment clean, and you can just copy that directory to another computer and run it with its own dlls. This avoids mess.

  There you go. You should be able to safely build any post-1.0.0 with this, unless there are some big changes that break the process.

7 Anjuta IDE

1) 安装OGRE
2)运行Anjuta IDE 并建立一个新的Generic/Terminal APP项目。
3)选择C++
4)删除MAIN。CC中的内容,然后键入下面的内容

#include "Ogre.h"
#include "Dome.h"
int main(int argc, char *argv[]){
// Create application object
Dome app;
try {
app.go();
} catch( Ogre::Exception& e ) {
std::cerr << "An exception has occured: " << e.getFullDescription().c_str() << std::endl;
}
return 0;
}

5)Go to the Settings Menu and choose Compilier and Linker Settings
6) 按照下述的内容修改各个选行。

Include Paths:
(ogrenew)/Samples/Common/include
(ogrenew)/OgreMain/include
/usr/include/OGRE

Library paths:
/usr/local/lib
(ogrenew)/OgreMain/lib
(ogrenew)/OgreMain/src
(ogrenew)/Samples/Common/include

Libraries:
OgreMain

Options:
In the Compilier flags (CFLAGS) box add this:
-g -O2 -fPIC -DHAVE_CONFIG_H -D_THREAD_SAFE


7) 现在建立一个新类DOME并建立一个createScene方法。还需要建立另一个类,我称为INPUT。作用和缓冲器监视器(frame listener.)一样。那个类在一些键按下后退出。

// filename: DEME.H
#ifndef _DOME_H_
#define _DOME_H_
#include "ExampleApplication.h"

class Dome : public ExampleApplication {
public:
Dome();
~Dome();
void createScene(void);
void createFrameListener(void);
protected:
// Dome variables
};
#endif // _DOME_H_


//filename: Dome.cc
#include "Dome.h"

void Dome::createScene(void){
Colourvalue c = Colourvalue(0.5, 0.5, 0.5);
mSceneMgr->setAmbientLight(c);
Entity *e = mSceneMgr->createEntity("ogrehead", "ogrehead.mesh");
SceneNode *node = static_cast<SceneNode *>(mSceneMgr->getRootSceneNode()->createChild());
node->attachObject(e);
node->setPosition(0,0,0);
}

// Create new frame listener
void Dome::createFrameListener(void){
mFrameListener = new Input(mWindow, mCamera);
mRoot->addFrameListener(mFrameListener);
}


// filename: Input.h
#ifndef _INPUT_H_
#define _INPUT_H_

#include "ExampleApplication.h"

class Input : public ExampleFrameListener{
public:
Input(RenderWindow* win, Camera* cam) : ExampleFrameListener(win, cam) {}
~Input();
// Input interface
bool frameStarted(const FrameEvent& evt);
// TODO: add member function declarations...
protected:
};
#endif //_INPUT_H_


// filename: Input.cc
#include "Input.h"
bool Input::frameStarted(const FrameEvent& evt){
mInputDevice->capture();
if(mInputDevice->isKeyDown(Ogre::KC_ESCAPE))
return false;
return true;
}


按F11编译他,如果得到关于OgreSharedPtr.h 的警告,这是正常的。

8) Go to the Projects folder in your home directory and enter the folder for the Ogre project, which I called Dome.
9) Create a symlink in the MyApp folder to the Media files that came with ogre. ln -s (ogrenew)/Samples/Media
10) Go into the src folder and create a folder named bin.
11) copy all the .cfg files from the ogre Samples into the bin folder. cp (ogrenew)/Samples/Common/bin/*.cfg Myapp/src/bin
12) go into the bin folder and create a symlink to you executable in the src folder. ln -s ../Dome
13) Run it. You need to run it from the bin folder. That way the executable has access to all the .cfg files in the folder with it. It also will look for the Media folder in ../../Media, which is why we put the symlink there.

8 你的第一个程序

#include "Ogre.h"
#include "ExampleApplication.h"
#include <windows.h>

// First, we declare a subclass of the ExampleApplication class
class FirstApp : public ExampleApplication{
public:
FirstApp() { }
/** createScene is pure virtual in ExampleApplication, so we just override it to do nothing.
* What this means is that we'll be creating an empty scene at first.
**/
void createScene(void) { }
};

INT WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,INT) {
FirstApp myApp; // Instanciate our subclass
try { // This try-catch provides a nice way of popping up errors if they occur.
myApp.go(); // ExampleApplication provides a go method, which starts the rendering.
} catch (Ogre::Exception& e) {
MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!",
MB_OK | MB_IConERROR | MB_TASKMODAL);
}
}


8.1 编译 运行

  试着运行他,他将显示OGRE安装对话框,并开始一个包含OGRE LOGE和FPS的深黑的屏幕。我在这里没有添加任何东西,当按ESC键退出。
  ExampleApplication 非常重要,他用于初始,建立窗口,建立基本的场景,摄象机和缓冲器监视器(frame listener.),因此,你不得不在工作时加上他。
  这只是一个空的程序,如果你想知道更多的东西,请参考OGRE的教程。

8.2 添加第一个物体

  前面,我们建立了一个黑色的屏幕,下面,我们将添加一个ogrehead 的mesh到程序中,在createScene中,添加下面的代码:

Entity *e = mSceneMgr->createEntity("ogrehead", "ogrehead.mesh");
SceneNode *node = mSceneMgr->getRootSceneNode()->createChildSceneNode();
node->attachObject(e);
node->setPosition(0,0,0);


  ExampleApplication 为我们提供了一个“场景管理者”----mSceneMgr. mSceneMgr用于在OGRE管理我们的场景。SceneNodes是OGRE中的一个基本的结构。在场景中的大多东西都和SceneNodes有联系,你能通过控制这些节点控制场景。每个场景都建立了一个根场景节点。你将把子节点,光和网格的值联系到根节点。每个节点又能建立他自己的子节点。这样更新场景将会更容易。例如,你有一个角色在场景中,并且他检起一个小棍。角色和小棍将分别给予不可见的场景节点。要使角色检起小棍,你将使角色动画弯腰并检起小棍,这样你必须使小棍的场景节点成为角色场景节点的子节点。我们都知道3D世界是建立在3D坐标系统上,因此,你有一个角色在坐标(0.0.0),作为角色场景节点的子节点的小棍场景节点是坐标(10.10.10)。小棍节点将在父节点下保持这个偏移,这就意味着当你移动角色节点,小棍节点也将跟着移动。在这里并不是移动两个节点,而是移动其中一个,而他的子节点将跟着移动,这容易吗,我认为很难。
  在这个例子中的网格的值很简单。为了建立可见的物体,我们简单的用sceneManager建立了全部的值,然后,我们把他们给予场景节点。在你的计算机上,把一个值想象成一个窗口,把sceneManager看着标题栏。你能通过点击并拖动标题栏来移动窗口。如果窗口有子窗口,点击并移动主窗口将移动子窗口。
  现在你将添加这些东西到场景中,你将可能编译并运行他。没有看见任何东西吗?原因是我们没有建立灯光,因此我们的场景就是黑的。我们有两种方法解决这个问题。

8.3 添加灯光

  首先,我们可以在场景中假如一些环境灯光。这将使整个场景达到一定的亮度。我们可以建立一个灯光物体并设置一个灯光场景节点,并添加这个灯光到场景世界中。
让我们来建立一个环境灯光吧,他是很容易的。
  在你的场景管理者中添加下面的代码:

Colourvalue c = Colourvalue(0.5, 0.5, 0.5);mSceneMgr->setAmbientLight(c);


美国读者的建议:
  sinbad,OGRE的创始者,是英国人,因此他的拼写方法和美国不同,比如"Colour" 替代了"Color" ,"Initialise" 替代了"Initialize". ,因此在编译时,有可能出现错误,请大家注意。
  mSceneMgr 用一个成员去设置环境灯光。主要是通过设置Colourvalue 的值来实现的,Colourvalue 有三个变量:red,green,blue.取值范围为0——1。在标准RGB下,0是0,1是255,因此,我在这个例子中建立了白光。我们建立Colourvalue对象,并把他添加到SceneManager的setAmbientLight 方法中。
  代码如下:

#include "Ogre.h"
#include "ExampleApplication.h"

// First, we declare a subclass of the ExampleApplication class
class FirstApp : public ExampleApplication{
public:
FirstApp() { }
/** createScene is pure virtual in ExampleApplication, so we just override
* to add what we just discussed.
* What this means is that we'll now can see the ogre head in the scene.
**/
void createScene(void) {
Colourvalue c = Colourvalue(0.5, 0.5, 0.5);
mSceneMgr->setAmbientLight(c);
Entity *e = mSceneMgr->createEntity("ogrehead", "ogrehead.mesh");
SceneNode *node = static_cast<SceneNode *>(mSceneMgr->getRootSceneNode()->createChild());
node->attachObject(e);
node->setPosition(0,0,0);
}
};

int main(int argc, char **argv){
FirstApp myApp; // Instanciate our subclass
try { // This try-catch provides a nice way of popping up errors if they occur.
myApp.go(); // ExampleApplication provides a go method, which starts the rendering.
} catch (Ogre::Exception& e) {
MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!",
MB_OK | MB_IConERROR | MB_TASKMODAL);
}
}

  编译并运行它,将产生一个OGRE的头。
  现在,让我们建立点光源。
  在createScene 方法中,添加下面的代码:

Light *l = mSceneMgr->createLight("aLight"); // Create a light and give it a name
SceneNode *lightNode = static_cast<SceneNode *>(mSceneMgr->getRootSceneNode()->createChild());
lightNode->attachObject(l);// We're going to create the light at the camera's position.
lightNode->setPosition(mCamera->getPosition());

  就如你所见到的,我们先建立了一个光,和一个用于光的场景节点,并把光联系到节点上,并设置节点的坐标。你可能注意到我用mCamera->getPosition() 设置坐标。
  ExampleApplication为我们提供了另一个定义指针,在这里我们用于设置摄象机。你将在复杂的程序中发现他很有用,但在这里,我们只是用他来取得摄象机的坐标,并设置灯光。
  Lights ,初始值为"point" 光,并是白光。你可以随意更改,但在这里,我们不需要。有三中类型的光:point, directional, and spotlight。point光是从一个点向四周发散,directional 光没有初始点,只是一个指向特定方向的光。spotlight有初始点和方向。
  现在,我们建立了物体,光和控制他们的节点。

9 Frame Listeners

  Frame Listeners 是什么?实际上是一个允许你更新你的世界的物体。他有两种方法来实现:frameStarted and frameEnded。frameStarted调用后,帧动画开始,frameEnded调用后,动画结束。你能用这些对象和方法更新你的世界。
  OGRE提供了一个基本的frame listener 叫ExampleFrameListener,他允许你在世界中自由移动。对于每个动画,他都接受鼠标输入和键盘输入,并允许你改变世界。这些都是通过移动摄象机实现的。你的鼠标的移动决定了你的摄象机的位置。当你按每个键,将决定按键后的动作。Frame listeners 不仅控制你的摄象机的移动,并是一个游戏循环,当游戏运行时,他将控制你的所有操作。如果你感兴趣,打开ExampleFrameListener (in ogrenew\Samples\Common\include) ,浏览他,如果你知道一些3D数学,你将知道他是如何工作的。在这里,我们只涉及到frameStarted and frameEnded 。

10 总结

  这只是关于OGRE的一篇引导。去玩例程并阅读其他教程。你将获得更多的知识。希望这篇文章对你有用,如果有任何问题,请写信给我,不要客气。
  译者注:经过两个星期六的时间,终于完成了这篇文章的翻译。对于其中6,7节,我没有翻译,主要是因为国内使用这两个工具的人很少(至少,我觉的是这样 :) )如有任何问题,写信给我。antking@gmail.cn 。还是那句话,希望这篇文章对你有用。

评论已关闭