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

Refactored rendering and frames

This commit is contained in:
Daniel Evans 2014-02-09 03:14:43 +00:00
parent 326fe4eeb3
commit 0773829dfc
9 changed files with 139 additions and 191 deletions

View File

@ -24,16 +24,12 @@ class Animator
glm::vec3 lastRootPosition;
glm::quat lastRootRotation;
std::vector<glm::mat4> matrices;
std::map<int32_t, AnimationBone*> frameToBone;
float time;
float serverTime;
float lastServerTime;
bool repeat;
void updateFrameMapping();
void reset();
public:

View File

@ -290,7 +290,7 @@ namespace RW
return *reinterpret_cast<T*>(data+offset+sizeof(BSSectionHeader)*2);
}
template<class T> T readSubStructure(size_t internalOffset)
template<class T> T& readSubStructure(size_t internalOffset)
{
return *reinterpret_cast<T*>(data+offset+sizeof(BSSectionHeader)+internalOffset);
}

View File

@ -9,6 +9,7 @@
#include <render/ViewCamera.hpp>
class Model;
class ModelFrame;
class GameWorld;
class GTAObject;
class Animator;
@ -25,6 +26,8 @@ class GTARenderer
GTAObject* object;
};
bool renderFrame(Model* m, ModelFrame* f, const glm::mat4& matrix, GTAObject* object, bool queueTransparent = true);
// Internal method for processing sub-geometry
bool renderSubgeometry(Model* model, size_t g, size_t sg, const glm::mat4& matrix, GTAObject* object, bool queueTransparent = true);

View File

@ -1,14 +1,65 @@
#pragma once
#ifndef _MODEL_HPP_
#define _MODEL_HPP_
#include <glm/glm.hpp>
#include <vector>
#include <string>
#include <memory>
#include <glm/glm.hpp>
#include <GL/glew.h>
#include <loaders/rwbinarystream.h>
/**
* Frame
* => Atomic
* => Geometry
* - defaultRotation
* - defaultTranslation
*
* + setTransform(mat)
* + resetTransform()
*/
class ModelFrame {
glm::mat3 defaultRotation;
glm::vec3 defaultTranslation;
glm::mat4 matrix;
ModelFrame* parentFrame;
std::string name;
std::vector<size_t> geometries;
std::vector<ModelFrame*> childs;
public:
ModelFrame(ModelFrame* parent, glm::mat3 dR, glm::vec3 dT);
~ModelFrame();
void reset();
void setTransform(const glm::mat4& m);
void setName(const std::string& fname)
{ name = fname; }
void addGeometry(size_t idx);
glm::vec3 getDefaultTranslation() const
{ return defaultTranslation; }
glm::mat3 getDefaultRotation() const
{ return defaultRotation; }
glm::mat4 getMatrix() const
{ return (parentFrame? parentFrame->getMatrix() : glm::mat4()) * matrix; }
const std::vector<ModelFrame*>& getChildren() const
{ return childs; }
const std::string& getName() const
{ return name; }
const std::vector<size_t>& getGeometries() const
{ return geometries; }
};
class Model
{
public:
@ -88,32 +139,15 @@ public:
uint32_t frame;
uint32_t geometry;
};
struct Frame {
glm::mat4 matrix;
glm::mat3 defaultRotation;
glm::vec3 defaultTranslation;
int32_t parentFrameIndex;
};
std::vector<ModelFrame*> frames;
std::vector<std::string> frameNames;
std::vector<std::shared_ptr<Geometry>> geometries;
std::vector<Atomic> atomics;
std::vector<Frame> frames;
int32_t rootFrameIdx;
glm::mat4 getFrameMatrix(int32_t frameIndex)
{
Frame& frame = frames[frameIndex];
if( frame.parentFrameIndex != -1 ) {
return frame.matrix * getFrameMatrix(frame.parentFrameIndex);
}
else {
return frame.matrix;
}
}
};
#endif

View File

@ -9,40 +9,13 @@ Animator::Animator()
}
void Animator::updateFrameMapping()
{
if(! (animation && model) ) {
return;
}
frameToBone.clear();
for( size_t f = 0; f < model->frames.size(); ++f ) {
AnimationBone* bone = animation->bones[model->frameNames[f]];
if(bone) {
frameToBone.insert({f, bone});
}
}
}
void Animator::reset()
{
time = 0.f;
lastServerTime= 0.f;
if(model && animation) {
if(model->rootFrameIdx != -1) {
auto it = frameToBone.find(model->rootFrameIdx);
if( it != frameToBone.end() )
{
AnimationBone* b = it->second;
AnimationKeyframe& KF = b->frames[0];
if(b->type == AnimationBone::RT0 || b->type == AnimationBone::RTS) {
lastRootPosition = KF.position;
}
lastRootRotation = KF.rotation;
}
}
}
}
@ -54,8 +27,7 @@ void Animator::setAnimation(Animation *animation, bool repeat)
this->animation = animation;
this->repeat = repeat;
updateFrameMapping();
reset();
}
@ -65,13 +37,8 @@ void Animator::setModel(Model *model)
return;
}
this->model = model;
this->model = model;
if(model != nullptr) {
matrices.resize(model->frames.size());
}
updateFrameMapping();
reset();
}
@ -81,64 +48,9 @@ void Animator::tick(float dt)
return;
}
// Calculate the root node movement.
if( model->rootFrameIdx != -1 ) {
auto it = frameToBone.find(model->rootFrameIdx);
if( it != frameToBone.end() )
{
AnimationBone* boneanim = frameToBone[model->rootFrameIdx];
if( boneanim->type != AnimationBone::R00 ) {
auto keyframe = boneanim->getInterpolatedKeyframe(serverTime);
lastRootPosition = keyframe.position;
}
}
}
lastServerTime = serverTime;
serverTime += dt;
for( size_t fi = 0; fi < model->frames.size(); ++fi ) {
glm::mat4 fmat = glm::mat4(model->frames[fi].defaultRotation);
fmat[3] = glm::vec4(model->frames[fi].defaultTranslation, 1.f);
if( animation && fi < model->frameNames.size() ) {
if(repeat) {
serverTime = fmod(serverTime, animation->duration);
}
else {
serverTime = std::min(serverTime, animation->duration);
}
if( lastServerTime > serverTime ) {
lastRootPosition = glm::vec3(0.f);
}
auto it = frameToBone.find(fi);
if( it == frameToBone.end() ) continue;
AnimationBone* boneanim = it->second;
if( boneanim && boneanim->frames.size() > 0 ) {
auto keyframe = boneanim->getInterpolatedKeyframe(serverTime);
fmat = glm::mat4(1.0f) * glm::mat4_cast(keyframe.rotation);
// Only add the translation back if is is not present.
if( boneanim->type == AnimationBone::R00 ) {
fmat[3] = glm::vec4(model->frames[fi].defaultTranslation, 1.f);
}
else {
if( fi == model->rootFrameIdx ) {
// Ignore root translation.
fmat[3] = glm::vec4(model->frames[fi].defaultTranslation, 1.f);
}
else {
fmat[3] = glm::vec4(keyframe.position, 1.f);
}
}
}
}
matrices[fi] = fmat;
}
}
void Animator::render(float dt)
@ -149,16 +61,6 @@ void Animator::render(float dt)
glm::vec3 Animator::getRootTranslation() const
{
if( model && model->rootFrameIdx != -1 ) {
auto it = frameToBone.find(model->rootFrameIdx);
if( it != frameToBone.end() )
{
AnimationBone* boneanim = it->second;
if( boneanim->type != AnimationBone::R00 ) {
auto keyframe = boneanim->getInterpolatedKeyframe(serverTime);
return keyframe.position - lastRootPosition;
}
}
}
return glm::vec3();
@ -171,15 +73,6 @@ glm::quat Animator::getRootRotation() const
glm::mat4 Animator::getFrameMatrix(size_t frame) const
{
if( model ) {
Model::Frame& f = model->frames[frame];
if( f.parentFrameIndex == -1 ) {
return matrices.at(frame);
}
else {
return getFrameMatrix(f.parentFrameIndex) * matrices.at(frame);
}
}
return glm::mat4();
}

View File

@ -245,11 +245,11 @@ GTAVehicle *GameWorld::createVehicle(const uint16_t id, const glm::vec3& pos, co
std::string& name = model->frameNames[f];
if( name.substr(0, 5) == "wheel" ) {
auto frameTrans = model->getFrameMatrix(f);
auto frameTrans = model->frames[f]->getMatrix();
info->second.wheels.push_back({glm::vec3(frameTrans[3])});
}
if(name.substr(0, 3) == "ped" && name.substr(name.size()-4) == "seat") {
auto p = model->frames[f].defaultTranslation;
auto p = model->frames[f]->getDefaultTranslation();
p.x = p.x * -1.f;
info->second.seats.push_back({p});
p.x = p.x * -1.f;

View File

@ -7,8 +7,6 @@
#include <set>
#include <cstring>
#include <glm/gtc/matrix_transform.hpp>
Model* LoaderDFF::loadFromMemory(char *data, GameData *gameData)
{
auto model = new Model;
@ -25,19 +23,21 @@ Model* LoaderDFF::loadFromMemory(char *data, GameData *gameData)
auto list = sec.readStructure<RW::BSFrameList>();
size_t fdataI = sizeof(RW::BSFrameList) + sizeof(RW::BSSectionHeader);
model->frames.reserve(list.numframes);
for(size_t f = 0; f < list.numframes; ++f) {
auto rawframe = sec.readSubStructure<RW::BSFrameListFrame>(fdataI);
RW::BSFrameListFrame& rawframe = sec.readSubStructure<RW::BSFrameListFrame>(fdataI);
fdataI += sizeof(RW::BSFrameListFrame);
Model::Frame frame;
frame.defaultRotation = rawframe.rotation;
frame.defaultTranslation = rawframe.position;
frame.parentFrameIndex = rawframe.index;
// Initilize the matrix with the correct values.
frame.matrix = glm::translate(glm::mat4(frame.defaultRotation), frame.defaultTranslation);
model->frames.push_back(frame);
ModelFrame* parent = nullptr;
if(rawframe.index != -1) {
parent = model->frames[rawframe.index];
}
else {
model->rootFrameIdx = 0;
}
model->frames.push_back(
new ModelFrame(parent, rawframe.rotation, rawframe.position)
);
}
size_t fldataI = 0;
@ -47,6 +47,7 @@ Model* LoaderDFF::loadFromMemory(char *data, GameData *gameData)
size_t extI = 0;
while( listsec.hasMoreData(extI)) {
auto extSec = listsec.getNextChildSection(extI);
size_t fn = 0;
if( extSec.header.id == RW::SID_NodeName) {
std::string framename(extSec.raw(), extSec.header.size);
std::transform(framename.begin(), framename.end(), framename.begin(), ::tolower );
@ -55,8 +56,10 @@ Model* LoaderDFF::loadFromMemory(char *data, GameData *gameData)
if(framename == "swaist") {
model->rootFrameIdx = model->frameNames.size();
}
model->frameNames.push_back(framename);
if( fn < model->frames.size() ) {
model->frames[(fn++)]->setName(framename);
}
}
}
}
@ -267,7 +270,9 @@ Model* LoaderDFF::loadFromMemory(char *data, GameData *gameData)
break;
}
case RW::SID_Atomic: {
model->atomics.push_back(sec.readStructure<Model::Atomic>());
const Model::Atomic& at = sec.readStructure<Model::Atomic>();
model->frames[at.frame]->addGeometry(at.geometry);
model->atomics.push_back(at);
break;
}
}

View File

@ -447,6 +447,37 @@ void GTARenderer::renderGeometry(Model* model, size_t g, const glm::mat4& modelM
}
}
bool GTARenderer::renderFrame(Model* m, ModelFrame* f, const glm::mat4& matrix, GTAObject* object, bool queueTransparent)
{
auto localmatrix = matrix * f->getMatrix();
for(size_t g : f->getGeometries()) {
RW::BSGeometryBounds& bounds = m->geometries[g]->geometryBounds;
if(! camera.frustum.intersects(bounds.center + glm::vec3(matrix[3]), bounds.radius)) {
continue;
}
if( object && object->type() == GTAObject::Vehicle ) {
auto& name = f->getName();
if( name.substr(name.size()-3) == "dam" || name.find("lo") != name.npos || name.find("dummy") != name.npos ) {
continue;
}
}
if( (m->geometries[g]->flags & RW::BSGeometry::ModuleMaterialColor) != RW::BSGeometry::ModuleMaterialColor) {
glUniform4f(uniCol, 1.f, 1.f, 1.f, 1.f);
}
renderGeometry(m,
g, localmatrix,
object);
}
for(ModelFrame* c : f->getChildren()) {
renderFrame(m, c, matrix, object, queueTransparent);
}
return true;
}
static GLuint currentVBO = 0;
bool GTARenderer::renderSubgeometry(Model* model, size_t g, size_t sg, const glm::mat4& matrix, GTAObject* object, bool queueTransparent)
@ -521,43 +552,7 @@ bool GTARenderer::renderSubgeometry(Model* model, size_t g, size_t sg, const glm
void GTARenderer::renderModel(Model* model, const glm::mat4& modelMatrix, GTAObject* object, Animator *animator)
{
for (size_t a = 0; a < model->atomics.size(); a++)
{
size_t g = model->atomics[a].geometry;
RW::BSGeometryBounds& bounds = model->geometries[g]->geometryBounds;
if(! camera.frustum.intersects(bounds.center + glm::vec3(modelMatrix[3]), bounds.radius)) {
culled++;
continue;
}
int32_t fi = model->atomics[a].frame;
if( object && object->type() == GTAObject::Vehicle ) {
if(model->frameNames.size() > fi) {
std::string& name = model->frameNames[fi];
if( name.substr(name.size()-3) == "dam" || name.find("lo") != name.npos || name.find("dummy") != name.npos ) {
continue;
}
}
}
if( (model->geometries[g]->flags & RW::BSGeometry::ModuleMaterialColor) != RW::BSGeometry::ModuleMaterialColor) {
glUniform4f(uniCol, 1.f, 1.f, 1.f, 1.f);
}
// Determine which transformation to use (why is this neccasary)
glm::mat4 localMatrix;
if(animator) {
localMatrix = animator->getFrameMatrix(model->atomics[a].frame);
}
else if(object&& object->type() == GTAObject::Vehicle)
{
localMatrix = model->getFrameMatrix(model->atomics[a].frame);
}
renderGeometry(model,
g, modelMatrix * localMatrix,
object);
}
renderFrame(model, model->frames[model->rootFrameIdx], modelMatrix, object);
}
void GTARenderer::renderPaths()

View File

@ -1,5 +1,9 @@
#include "render/Model.hpp"
#include <GL/glew.h>
#include <iostream>
#include <glm/gtc/matrix_transform.hpp>
Model::Geometry::Geometry()
: VBO(0), EBO(0),
@ -22,7 +26,6 @@ void Model::Geometry::generateNormals()
{
}
#include <iostream>
void Model::Geometry::buildBuffers()
{
@ -120,3 +123,22 @@ void Model::Geometry::buildBuffers()
subgeom[i].indices);
}
}
ModelFrame::ModelFrame(ModelFrame* parent, glm::mat3 dR, glm::vec3 dT)
: defaultRotation(dR), defaultTranslation(dT), parentFrame(parent)
{
if(parent != nullptr) {
parent->childs.push_back(this);
}
reset();
}
void ModelFrame::reset()
{
matrix = glm::translate(glm::mat4(), defaultTranslation) * glm::mat4(defaultRotation);
}
void ModelFrame::addGeometry(size_t idx)
{
geometries.push_back(idx);
}