장면 의 데이터 구조: Node & Entity
15340 단어 entity
Node:
1. 구조
Node::Node(const String& name)
:
mParent(0), //
mNeedParentUpdate(false), // true,
mNeedChildUpdate(false), // true, ( )
mParentNotified(false), // true
mQueuedForUpdate(false), // true
mName(name),
mOrientation(Quaternion::IDENTITY), // ,
mPosition(Vector3::ZERO), //
mScale(Vector3::UNIT_SCALE), //
mInheritOrientation(true), // true
mInheritScale(true), //
mDerivedOrientation(Quaternion::IDENTITY), // Derived
mDerivedPosition(Vector3::ZERO), // ,
mDerivedScale(Vector3::UNIT_SCALE),
mInitialPosition(Vector3::ZERO), // Initial , 。
mInitialOrientation(Quaternion::IDENTITY),
mInitialScale(Vector3::UNIT_SCALE),
mCachedTransformOutOfDate(true), //
mListener(0),
mDebug(0)
{
needUpdate();
}
2. create Child: 아 이 를 만 들 었 습 니 다. 자신 이 아버지 이 고 부자 관계 도 맺 었 습 니 다.
Node* Node::createChild(const String& name, const Vector3& inTranslate, const Quaternion& inRotate)
{
Node* newNode = createChildImpl(name);
newNode->translate(inTranslate);
newNode->rotate(inRotate);
this->addChild(newNode);
return newNode;
}
create ChildImpl 은 가상 함수 로 하위 클래스 에서 연구 합 니 다.translate 라 는 이름 이 좀 아 프 네요. 위 치 를 정 했 는데.rotate 회전 과 크기 조정.
translate :
void Node::translate(const Vector3& d, TransformSpace relativeTo)
{
switch(relativeTo)
{
case TS_LOCAL:
// position is relative to parent so transform downwards
mPosition += mOrientation * d;
break;
case TS_WORLD:
// position is relative to parent so transform upwards
if (mParent)
{
mPosition += (mParent->_getDerivedOrientation().Inverse() * d)
/ mParent->_getDerivedScale();
}
else
{
mPosition += d;
}
break;
case TS_PARENT:
mPosition += d;
break;
}
needUpdate();
}
처음부터 끝까지 위치 가 바 뀌 는 것 만 봤 어 요. mPosition.
rotate:
rotate(Vector3::UNIT_Y, angle, relativeTo); //
void Node::rotate(const Vector3& axis, const Radian& angle, TransformSpace relativeTo)
{
Quaternion q;
q.FromAngleAxis(angle,axis);
rotate(q, relativeTo);
}
void Node::rotate(const Quaternion& q, TransformSpace relativeTo)
{
// Normalise quaternion to avoid drift
Quaternion qnorm = q;
qnorm.normalise();
switch(relativeTo)
{
case TS_PARENT:
// Rotations are normally relative to local axes, transform up
mOrientation = qnorm * mOrientation;
break;
case TS_WORLD:
// Rotations are normally relative to local axes, transform up
mOrientation = mOrientation * _getDerivedOrientation().Inverse()
* qnorm * _getDerivedOrientation();
break;
case TS_LOCAL:
// Note the order of the mult, i.e. q comes after
mOrientation = mOrientation * qnorm;
break;
}
needUpdate();
}
밑 에 있 는 본질 이 수학 적 계산 인지 4 원 수 를 통 해 축 을 정 하 는 것 입 니 다. 여기 에는 세 가지 유형의 선택 이 있 습 니 다. LOCAL (자신 에 게), PARENT (아버지 에 게), WORLD (상대 세계) 가 회전 합 니 다.Vector3::UNIT_Z 는 어떤 축 을 따라 가 는 지 지정 합 니 다.
3. Update: 여기까지 쓰 면 EMF 가 생각 납 니 다. 사실은 모든 인터페이스 요 소 는 비슷 한 표현 을 가지 고 있 습 니 다. 다른 것 은 바 텀 실현 에 사용 되 는 사람 이 누구 입 니까?
void Node::needUpdate(bool forceParentUpdate)
{
mNeedParentUpdate = true;
mNeedChildUpdate = true;
mCachedTransformOutOfDate = true;
// Make sure we're not root and parent hasn't been notified before
if (mParent && (!mParentNotified || forceParentUpdate))
{
mParent->requestUpdate(this, forceParentUpdate);
mParentNotified = true ;
}
// all children will be updated
mChildrenToUpdate.clear();
}
void Node::requestUpdate(Node* child, bool forceParentUpdate)
{
// If we're already going to update everything this doesn't matter
if (mNeedChildUpdate)
{
return;
}
mChildrenToUpdate.insert(child);
// Request selective update of me, if we didn't do it before
if (mParent && (!mParentNotified || forceParentUpdate))
{
mParent->requestUpdate(this, forceParentUpdate);
mParentNotified = true ;
}
}
여기에 붙 인 두 가지 방법 은 노드 에 업데이트 가 필요 하 다 는 것 을 알려 주 었 을 뿐 최종 적 으로 업데이트 해 야 할 노드 는 모두 mChildren ToUpdate 에 저장 되 어 있 습 니 다.
_update:
void Node::_update(bool updateChildren, bool parentHasChanged)
{
// always clear information about parent notification
mParentNotified = false;
// See if we should process everyone
if (mNeedParentUpdate || parentHasChanged)
{
// Update transforms from parent
_updateFromParent(); // ,
}
if(updateChildren)
{
if (mNeedChildUpdate || parentHasChanged)
{
ChildNodeMap::iterator it, itend;
itend = mChildren.end();
for (it = mChildren.begin(); it != itend; ++it)
{
Node* child = it->second;
child->_update(true, true);
}
}
else
{
// Just update selected children
ChildUpdateSet::iterator it, itend;
itend = mChildrenToUpdate.end();
for(it = mChildrenToUpdate.begin(); it != itend; ++it)
{
Node* child = *it;
child->_update(true, false);
}
}
mChildrenToUpdate.clear();
mNeedChildUpdate = false;
}
}
이런 재 귀적 인 방식 으로 업 데 이 트 를 하면 효율 이 높 지 않 을 것 이다. 특히 하나의 노드 만 있 는 상황 에서 다 중 스 레 드 도 할 수 없다.ogre 는 효율 을 생각해 야 합 니 다. 적어도 하나의 노드 가 아 닌 list 를 따라 가 봐 야 합 니 다.
updateFromParent:
void Node::updateFromParentImpl(void) const
{
if (mParent)
{
// Update orientation
const Quaternion& parentOrientation = mParent->_getDerivedOrientation();
if (mInheritOrientation)
{
// Combine orientation with that of parent
mDerivedOrientation = parentOrientation * mOrientation;
}
else
{
// No inheritance
mDerivedOrientation = mOrientation;
}
// Update scale
const Vector3& parentScale = mParent->_getDerivedScale();
if (mInheritScale)
{
// Scale own position by parent scale, NB just combine
// as equivalent axes, no shearing
mDerivedScale = parentScale * mScale;
}
else
{
// No inheritance
mDerivedScale = mScale;
}
// Change position vector based on parent's orientation & scale
mDerivedPosition = parentOrientation * (parentScale * mPosition);
// Add altered position vector to parents
mDerivedPosition += mParent->_getDerivedPosition();
}
else
{
// Root node, no parent
mDerivedOrientation = mOrientation;
mDerivedPosition = mPosition;
mDerivedScale = mScale;
}
mCachedTransformOutOfDate = true;
mNeedParentUpdate = false;
}
Derived 를 접두사 로 하 는 세 개의 노드 위 치 를 설명 하 는 필드 를 업데이트 합 니 다.
SceneNode:
Node 의 계승, 장면 의 진실 한 결점, 각종 Object 가 그 위 에 걸 립 니 다.
1. Axis Aligned Box: 노드 의 경계, 충돌 검 측 이 필요 하기 때문에 업데이트 할 때 업데이트 해 야 합 니 다.
void SceneNode::_updateBounds(void)
{
// Reset bounds first
mWorldAABB.setNull();
// Update bounds from own attached objects objects
ObjectMap::iterator i;
for (i = mObjectsByName.begin(); i != mObjectsByName.end(); ++i)
{
// Merge world bounds of each object
mWorldAABB.merge(i->second->getWorldBoundingBox(true));
}
// Merge with children
ChildNodeMap::iterator child;
for (child = mChildren.begin(); child != mChildren.end(); ++child)
{
SceneNode* sceneChild = static_cast<SceneNode*>(child->second);
mWorldAABB.merge(sceneChild->mWorldAABB);
}
}
여 기 는 주로 mWorldAABB 의 크기 를 계산 하고 모든 연결 을 통 해 objects + ChildNode 합병 이 가장 큰 범 위 를 얻 었 습 니 다.
2. WireBounding Box: 선 상자 디 스 플레이 모드 라 는 디 스 플레이 모드 가 있 습 니 다. 바로 이 아버 지 는 Simple Renderable 로 렌 더 링 대상 을 볼 수 있 습 니 다.스스로 계산 하지 않 고 Axis Aligned Box 를 통 해 테 두 리 를 가 져 옵 니 다.
void SceneNode::_addBoundingBoxToQueue(RenderQueue* queue) {
// Create a WireBoundingBox if needed.
if (mWireBoundingBox == NULL) {
mWireBoundingBox = OGRE_NEW WireBoundingBox();
}
mWireBoundingBox->setupBoundingBox(mWorldAABB);
queue->addRenderable(mWireBoundingBox);
}
3. autoTrack: 목 표를 자동 으로 추적 하고 모든 노드 에 SceneNode * mAutoTrackTarget 이 있 습 니 다.목표 노드 는 추적 할 수 있다. 이 능력 은 두 가지 효 과 를 실현 할 수 있다. 하 나 는 바로 캐릭터 이동 카메라 가 따라 움 직 이 는 것 이 고 또 하 나 는 캐릭터 가 아 기 를 데 리 고 다 니 는 것 이다.이 기능 은 주로 세 가지 방법 과 관련된다.autoTrack, lookAt, setDirection.
void SceneNode::setDirection(const Vector3& vec, TransformSpace relativeTo,
const Vector3& localDirectionVector)
{
// Do nothing if given a zero vector
if (vec == Vector3::ZERO) return;
// The direction we want the local direction point to
Vector3 targetDir = vec.normalisedCopy();
// Transform target direction to world space
switch (relativeTo)
{
case TS_PARENT:
if (mInheritOrientation)
{
if (mParent)
{
targetDir = mParent->_getDerivedOrientation() * targetDir;
}
}
break;
case TS_LOCAL:
targetDir = _getDerivedOrientation() * targetDir;
break;
case TS_WORLD:
// default orientation
break;
}
// Calculate target orientation relative to world space
Quaternion targetOrientation;
if( mYawFixed )
{
// Calculate the quaternion for rotate local Z to target direction
Vector3 xVec = mYawFixedAxis.crossProduct(targetDir);
xVec.normalise();
Vector3 yVec = targetDir.crossProduct(xVec);
yVec.normalise();
Quaternion unitZToTarget = Quaternion(xVec, yVec, targetDir);
if (localDirectionVector == Vector3::NEGATIVE_UNIT_Z)
{
// Specail case for avoid calculate 180 degree turn
targetOrientation =
Quaternion(-unitZToTarget.y, -unitZToTarget.z, unitZToTarget.w, unitZToTarget.x);
}
else
{
// Calculate the quaternion for rotate local direction to target direction
Quaternion localToUnitZ = localDirectionVector.getRotationTo(Vector3::UNIT_Z);
targetOrientation = unitZToTarget * localToUnitZ;
}
}
else
{
const Quaternion& currentOrient = _getDerivedOrientation();
// Get current local direction relative to world space
Vector3 currentDir = currentOrient * localDirectionVector;
if ((currentDir+targetDir).squaredLength() < 0.00005f)
{
// Oops, a 180 degree turn (infinite possible rotation axes)
// Default to yaw i.e. use current UP
targetOrientation =
Quaternion(-currentOrient.y, -currentOrient.z, currentOrient.w, currentOrient.x);
}
else
{
// Derive shortest arc to new direction
Quaternion rotQuat = currentDir.getRotationTo(targetDir);
targetOrientation = rotQuat * currentOrient;
}
}
// Set target orientation, transformed to parent space
if (mParent && mInheritOrientation)
setOrientation(mParent->_getDerivedOrientation().UnitInverse() * targetOrientation);
else
setOrientation(targetOrientation);
}
이것 은 setDirection 방법 으로 방향 을 바 꾸 는 것 입 니 다. 자동 추적 뿐만 아니 라 자신 이 방향 을 제어 하 는 데 도 이 방법 을 사용 합 니 다.
4. attachObject: 이것 은 반드시 말 해 야 합 니 다. 모든 Object 는 이 방법 을 통 해 노드 에 걸 려 있 습 니 다.최종 Object 는 ObjectMap mObjectsByName 에 저 장 됩 니 다.안 은 name 을 통 해 얻 을 수 있 습 니 다.
요약: 전체 장면 관리 에 있어 노드 는 그 중의 아주 작은 부분 일 뿐 노드 는 자원 과 관련 되 지 않 았 다.자원 과 관련 된 것 은 모두 Object 안에 있다.이 는 전체 장면 을 크 고 완전 하 게 묘 사 했 는데 실제 적 으로 렌 더 링 이 필요 한 대상 은 렌 더 링 대기 열 에 넣 을 것 이다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JPA 연관 관계 매핑1_일대일 단방향 매핑하기Entity들은 대부분 다른 Entity와 연관 관계를 맺고 있다. JPA에서는 Entity에 연관 관계를 매핑해두고 필요할 때 해당 Entity와 연관된 Entity를 사용해 조금 더 객체지향적인 프로그래밍(OOP...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.