1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-09-18 16:32:32 +02:00

Initial Instance Object Rendering via atomics

This commit is contained in:
Daniel Evans 2017-01-07 23:51:30 +00:00
parent 729085d08c
commit 80c9b73ac5
4 changed files with 72 additions and 72 deletions

View File

@ -235,7 +235,7 @@ public:
return lifetime;
}
void updateTransform(const glm::vec3& pos, const glm::quat& rot) {
virtual void updateTransform(const glm::vec3& pos, const glm::quat& rot) {
_lastPosition = position;
_lastRotation = rotation;
position = pos;

View File

@ -18,6 +18,8 @@ InstanceObject::InstanceObject(GameWorld* engine, const glm::vec3& pos,
, _enablePhysics(false) {
if (modelinfo) {
changeModel(modelinfo);
setPosition(pos);
setRotation(rot);
/// @todo store path information properly
if (modelinfo->type() == ModelDataType::SimpleInfo) {
@ -133,6 +135,17 @@ void InstanceObject::changeModel(BaseModelInfo* incoming) {
setModel(getModelInfo<SimpleModelInfo>()->getModel());
auto collision = getModelInfo<SimpleModelInfo>()->getCollision();
auto modelatomic = getModelInfo<SimpleModelInfo>()->getAtomic(0);
if (modelatomic) {
auto previousatomic = atomic_;
atomic_ = modelatomic->clone();
if (previousatomic) {
atomic_->setFrame(previousatomic->getFrame());
} else {
atomic_->setFrame(std::make_shared<ModelFrame>());
}
}
if (collision) {
body.reset(new CollisionInstance);
body->createPhysicsBody(this, collision, dynamics.get());
@ -141,11 +154,25 @@ void InstanceObject::changeModel(BaseModelInfo* incoming) {
}
}
void InstanceObject::setPosition(const glm::vec3& pos) {
if (body) {
auto& wtr = body->getBulletBody()->getWorldTransform();
wtr.setOrigin(btVector3(pos.x, pos.y, pos.z));
}
if (atomic_) {
atomic_->getFrame()->setTranslation(pos);
}
GameObject::setPosition(pos);
}
void InstanceObject::setRotation(const glm::quat& r) {
if (body) {
auto& wtr = body->getBulletBody()->getWorldTransform();
wtr.setRotation(btQuaternion(r.x, r.y, r.z, r.w));
}
if (atomic_) {
atomic_->getFrame()->setRotation(glm::mat3_cast(r));
}
GameObject::setRotation(r);
}
@ -181,3 +208,11 @@ void InstanceObject::setSolid(bool solid) {
}
body->getBulletBody()->setCollisionFlags(flags);
}
void InstanceObject::updateTransform(const glm::vec3& pos,
const glm::quat& rot) {
position = pos;
rotation = rot;
getAtomic()->getFrame()->setRotation(glm::mat3_cast(rot));
getAtomic()->getFrame()->setTranslation(pos);
}

View File

@ -14,6 +14,11 @@ class InstanceObject : public GameObject {
float health;
bool visible = true;
/**
* The Atomic instance for this object
*/
AtomicPtr atomic_;
public:
glm::vec3 scale;
std::unique_ptr<CollisionInstance> body;
@ -31,10 +36,15 @@ public:
return Instance;
}
const AtomicPtr& getAtomic() const {
return atomic_;
}
void tick(float dt);
void changeModel(BaseModelInfo* incoming);
virtual void setPosition(const glm::vec3 &pos);
virtual void setRotation(const glm::quat& r);
virtual bool takeDamage(const DamageInfo& damage);
@ -51,6 +61,8 @@ public:
float getHealth() const {
return health;
}
void updateTransform(const glm::vec3& pos, const glm::quat& rot) override;
};
#endif

View File

@ -23,6 +23,7 @@ constexpr float kWorldDrawDistanceFactor = kDrawDistanceFactor;
constexpr float kVehicleDrawDistanceFactor = kDrawDistanceFactor;
constexpr float kPedestrianDrawDistanceFactor = kDrawDistanceFactor;
#endif
constexpr float kMagicLODDistance = 330.f;
RenderKey createKey(bool transparent, float normalizedDepth,
Renderer::Textures& textures) {
@ -132,13 +133,15 @@ void ObjectRenderer::renderClump(Clump* model, const glm::mat4& worldtransform,
continue;
}
renderAtomic(atomic.get(), worldtransform, object, render);
const auto& framematrix = atomic->getFrame()->getMatrix();
renderAtomic(atomic.get(), worldtransform * framematrix, object, render);
}
}
void ObjectRenderer::renderInstance(InstanceObject* instance,
RenderList& outList) {
if (!instance->getModel()) {
const auto& atomic = instance->getAtomic();
if (!atomic) {
return;
}
@ -161,82 +164,32 @@ void ObjectRenderer::renderInstance(InstanceObject* instance,
return;
}
auto matrixModel = instance->getTimeAdjustedTransform(m_renderAlpha);
float mindist = glm::length(instance->getPosition() - m_camera.position);
float mindist = glm::length(instance->getPosition() - m_camera.position) -
instance->getModel()->getBoundingRadius();
mindist *= 1.f / kDrawDistanceFactor;
if (mindist < kMagicLODDistance && modelinfo->LOD) {
// @todo this should check if it might be best to render anyway
return;
}
Atomic* atomic = nullptr;
// These are used to gracefully fade out things that are just out of
// view
// distance.
Atomic* fadingAtomic = nullptr;
auto fadingMatrix = matrixModel;
float opacity = 0.f;
constexpr float fadeRange = 50.f;
/// @todo replace this block with the correct logic
if (modelinfo->getNumAtomics() == 1) {
// Is closest point greater than the *object* draw distance
float objectRange = modelinfo->getLodDistance(0);
float overlap = (mindist - objectRange);
if (mindist > objectRange) {
// Check for LOD instances
if (instance->LODinstance) {
// Is the closest point greater than the *LOD* draw distance
auto lodmodelinfo =
instance->LODinstance->getModelInfo<SimpleModelInfo>();
float LODrange = lodmodelinfo->getLodDistance(0);
if (mindist <= LODrange && instance->LODinstance->getModel()) {
// The model matrix needs to be for the LOD instead
matrixModel =
instance->LODinstance->getTimeAdjustedTransform(
m_renderAlpha);
atomic = lodmodelinfo->getAtomic(0);
// If the object is only just out of range, keep
// rendering it and screen-door the LOD.
if (overlap < fadeRange) {
fadingAtomic = modelinfo->getAtomic(0);
opacity = 1.f - (overlap / fadeRange);
}
}
}
// We don't have a LOD object, so fade out gracefully.
else if (overlap < fadeRange) {
fadingAtomic = modelinfo->getAtomic(0);
opacity = 1.f - (overlap / fadeRange);
}
}
// Otherwise, if we aren't marked as a LOD model, we can render
else if (!modelinfo->LOD) {
atomic = modelinfo->getAtomic(0);
}
} else {
auto root = instance->getModel()->getFrame();
matrixModel *= root->getTransform();
for (int i = 0; i < modelinfo->getNumAtomics() - 1; ++i) {
auto ind = (modelinfo->getNumAtomics() - 1) - i;
float lodDistance = modelinfo->getLodDistance(i);
if (mindist > lodDistance) {
fadingAtomic = modelinfo->getAtomic(ind);
opacity = 1.f - ((mindist - lodDistance) / fadeRange);
} else {
fadingAtomic = modelinfo->getAtomic(ind);
}
Atomic* distanceatomic = nullptr;
for (int i = 0; i < modelinfo->getNumAtomics(); i++) {
auto atomicdistance = modelinfo->getLodDistance(i);
if (mindist < atomicdistance * kDrawDistanceFactor) {
distanceatomic = modelinfo->getAtomic(i);
}
}
if (atomic) {
renderAtomic(atomic, matrixModel, instance, outList);
if (! distanceatomic) {
return;
}
if (fadingAtomic && opacity >= 0.01f) {
// @todo pass opacity
renderAtomic(fadingAtomic, fadingMatrix, instance, outList);
if (atomic->getGeometry() != distanceatomic->getGeometry()) {
atomic->setGeometry(distanceatomic->getGeometry());
}
const auto& frame = atomic->getFrame()->getTransform();
// Render the atomic the instance thinks it should be
renderAtomic(atomic.get(), frame, instance, outList);
}
void ObjectRenderer::renderCharacter(CharacterObject* pedestrian,