Ogre中的攝像機

一個攝像機就像真實世界的模擬一樣:它從一個特定的方向為你場景的每一幀「照相」(就是說它有一個位置點和一個方向)。它不是一個典型的可渲染的物體,所以即使你在場景中已經有了一個攝像機,這個攝像機也不會被渲染。攝像機既可以被連接到場景的節點上也可以存在於自由的空間中(which means you get to move them around manually if you want their position and/or orientation changed each frame)。就像所提到的那樣,攝像機具有擁有一個近切片和一個遠切片的視域(field of view)。

我們假設你想要一個具有標準的4:3比例的區域,其近切片距離為5單位,原切片距離為1000單位,攝像機中心軸和上下界的角度皆為30度,下面的代碼就創建了這樣一個攝像機:

// sceneMgr is an existing instance of a SceneManager implementation. We are

// creating a camera named "MainCam" here.

Camera *camera = sceneMgr->createCamera("MainCam");

// normally you would calculate this from the size of the viewport

camera->setAspectRatio(1.33333f);

// 30 degrees will give more of a long, telescopic view

camera->setFOVy(30.0f);

camera->setNearClipDistance(5.0f);

camera->setFarClipDistance(1000.0f);

渲染模式

攝像機可以用三種不同模式中的一種來渲染場景:wireframe(線框圖),solid(實體圖),或者「points」(只有點被渲染)。

camera->setPolygonMode(PM_WIREFRAME);

camera->setPolygonMode(PM_POINTS);

camera->setPolygonMode(PM_SOLID);

PolygonMode mode = camera->getPolygonMode();

模式設定在以後的動畫中會繼續強制執行,直到它被另一個調用改變為止(也就是說這不是一個單幀的設定)。默認的模式是PM_SOLID。

位置和變換

一個攝像機是一個可以移動的物體,並享有MovableObject類中的所有的函數和方法。MovableObject最常見的功能是可以連接到場景中的一個節點並且伴隨著可渲染的物體移動(「piggyback」 the camera along with renderable objects)。你會有需要這麼做,比如各種攝像機追蹤鏡頭的技術。你會在後面的章節中看到各種第三人稱攝影技術。現在,我們只討論固定位置和方向的攝像機。

// assume camera is a pointer to an existing, valid instance of "Camera"

camera->setPosition(200, 10, 200);

// you can also use a Vector3 to position the camera, useful for using the

// position obtained from a scene node getter

// camera->setPosition(Vector3(200, 10, 200));

這段代碼會把攝像機放置在絕對坐標(200,10,200)處。這和move()與moveRelative()方法是不同的,後面所說的這些方法分別是在世界坐標和本地坐標中針對當前位置移動物體。

// camera is at world space 200, 10, 200 from before

camera->move(10, 0, 0); // camera moves to 210, 10, 200

camera->moveRelative(0, 0, 10); // camera moves to 210, 10, 210

我們必須注意moveRelative()。因為它發生在本地坐標系中,這種移動的實施和攝像機當時的方向有關。在前面所述的例子中,我們假定攝像機是和主軸線對齊的,指向正Z軸方向。如果攝像機向右轉了90度,例如,moveRelative(0,0,10)會把攝像機移到(220,10,200)的地方。

方向、指向和「面向」(Direction, Orientation, and 」Look-At」)

OGRE提供了一系列豐富的方法來放置你的攝像機:

void setDirection(Real x, Real y, Real z);

void setDirection(const Vector3& vec);

Vector3 getDirection(void) const;

Vector3 getUp(void) const;

Vector3 getRight(void) const;

void lookAt( const Vector3& targetPoint );

void lookAt(Real x, Real y, Real z);

void roll(const Radian& angle);

void roll(Real degrees) { roll ( Angle(degrees) ); }

void yaw(const Radian& angle);

void yaw(Real degrees) { yaw ( Angle(degrees) ); }

void pitch(const Radian& angle);

void pitch(Real degrees) { pitch ( Angle(degrees) ); }

void rotate(const Vector3& axis, const Radian& angle);

void rotate(const Vector3& axis, Real degrees) {

rotate ( axis, Angle(degrees) ); }

void rotate(const Quaternion& q);

void setFixedYawAxis( bool useFixed, const Vector3& fixedAxis =

const Quaternion& getOrientation(void) const;

void setOrientation(const Quaternion& q);

void setAutoTracking(bool enabled, SceneNode* target = 0,

const Vector3& offset = Vector3::ZERO);

這些方法的功能大多數從名字來看是顯而易見(self-explanatory)的。roll(), yaw(), 和pitch()做的正好就是他們所描述的。setDirection()會讓攝像機指向該向量定義的方向。rotate()會使攝像機沿著給定的坐標軸旋轉一個角度。lookAt()是非常常用的,它可以使一個攝像機指向一個目標點或目標物體的中心,並且不需要用歐氏幾何的方法去計算該指向的四元矩陣。最後,setFixedYawAxis()允許你打破攝像機自有的偏移軸的約束(break the camera free from its own yaw (Y) axis)。在第一人稱射擊遊戲中,攝像機通常能夠檢視X-Z平面。正因如此,你希望的默認動作,是沿著攝像機本地坐標的Y軸偏移。但是,在飛行模擬遊戲中,你希望能打破這種約束來創造一個完全自由的攝像機。

setAutoTracking()是一個有趣的功能,如果你希望攝像機總是沿著場景中特定的一點。注意這和真正的第三人稱視點的攝像機不同,因為那種攝像機通常不是面向一個特定點的,而是總是面向你的角色所看的方向的。第一個參數指出是否採用追蹤,這在任何一幀開始渲染前都可以做,並且在被追蹤前必須先刪除這個節點。被追蹤的節點是第二個參數,這個節點必須存在於這個方法被調用之前。這個參數只能在第一個參數是false的情況下定為NULL。如果被追蹤的物體是巨大的並且不適合面向正中間來觀察,你可以用第三個參數(偏移offset)來協調一下實際的視點,該參數在本地坐標中操作被追蹤的節點。

以下的方法可以用來獲得攝像機實際方向的信息,注意把旋轉操作和平移操作對被連接的節點的影響考慮在內:

const Quaternion& getDerivedOrientation(void) const;

const Vector3& getDerivedPosition(void) const;

Vector3 getDerivedDirection(void) const;

Vector3 getDerivedUp(void) const;

Vector3 getDerivedRight(void) const;

const Quaternion& getRealOrientation(void) const;

const Vector3& getRealPosition(void) const;

Vector3 getRealDirection(void) const;

Vector3 getRealUp(void) const;

Vector3 getRealRight(void) const;

Real的方法返回的是世界坐標中的值,但是Derived返回的是在本地坐標中的值。

進階攝像機功能

OGRE通過setFrustumOffset()和setFocalLength()方法支持真實的渲染。例如,你可以通過水平地適配一個攝像機來模擬眼睛間的距離。這會在適配的攝像機中渲染出一個有微小角度區別的畫面,以此產生真實的輸出。當然,這種技術是高度專業化和細節很多的,但是它確被提供給這種需要的人。

OGRE也允許你直接操作視點和法線的矩陣。這當然是更高級的話題了,回到我們先前所說的「只有在你確信知道你所做並且為何這麼做的時候才做」上來,因為這些矩陣在你設定攝像機的時候就已經為你計算好了。下面的方法是用來操作view/projection的矩陣的:

const Matrix4& getProjectionMatrixRS(void) const;

const Matrix4& getProjectionMatrixWithRSDepth(void) const;

const Matrix4& getProjectionMatrix(void) const;

const Matrix4& getViewMatrix(void) const;

void setCustomViewMatrix(bool enable,

const Matrix4& viewMatrix = Matrix4::IDENTITY);

bool isCustomViewMatrixEnabled(void) const;

void setCustomProjectionMatrix(bool enable,

const Matrix4& projectionMatrix = Matrix4::IDENTITY);

bool isCustomProjectionMatrixEnabled(void) const;

列出的前兩行代碼返回渲染系統設定的法線矩陣。getProjectionMatrixRS()會返回渲染系統得本地坐標,而getProjectionMatrixWithRSDepth()會以OGRE本身的格式(右手坐標系的方式)返回矩陣。區別是深度值(depth value)會根據所用的渲染系統而覆蓋[0,1]或[-1,1]的範圍。你可以用調用getProjectionMatrix()來避免這些使其總是返回[-1,1]間的一個值。

推薦閱讀:

TAG:攝像機 | Ogre | 攝像 |