protot/src/modules/CharacterModule.cc

260 lines
6.6 KiB
C++

#include <map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <sstream>
#include "3rdparty/ocornut-imgui/imgui.h"
#include "imgui/imgui.h"
#include <bx/fpumath.h>
#include "RuntimeModule.h"
#include "Globals.h"
#include "modules/RenderModule.h"
#include "Serializer.h"
#include "CharacterModule.h"
#include "rbdl/addons/luamodel/luatables.h"
// forward declaration of a function that is in the LuaModel addon
// of RBDL. We make it visible here to extract more information
// from the Lua file.
namespace RigidBodyDynamics {
namespace Addons {
bool LuaModelReadFromTable (LuaTable &model_table, Model *model, bool verbose);
}
}
using namespace std;
using namespace RigidBodyDynamics;
using namespace RigidBodyDynamics::Addons;
const float cJumpVelocity = 4.0f;
const float cVelocityDamping = 4.0f;
const float cGravity = 9.81f;
const float cGroundAcceleration = 30.0f;
const float cCharacterHeight = 1.8f;
const float cCharacterWidth = 1.f;
const char* cRigModelFile = "data/models/model.lua";
CharacterEntity::CharacterEntity() {
entity = gRenderer->createEntity();
mPosition = Vector3f (0.f, 0.0f, 0.0f);
mRigModel = new Model();
bool load_result = LoadRig (cRigModelFile);
assert (load_result);
cout << "Creating render entity mesh ..." << endl;
// Mesh* base_mesh = Mesh::sCreateUVSphere(45, 45, 0.9);
// Transform sub_transform =
// Transform::fromTransRot(
// Vector3f (4.f, 3.3f, 0.12f),
// Quaternion::fromEulerYXZ (Vector3f(1.f, 2.f, 0.f))
// );
// Mesh* quad = Mesh::sCreateCuboid(1.05, 0.1, 2.05);
//
// base_mesh->Merge (*quad, sub_transform.toMatrix());
// base_mesh->Update();
// delete quad;
// Build the snowman
entity->mesh.addMesh(
- 1,
Transform::fromTrans(
Vector3f (0.0f, 0.9 * 0.5f, 0.0f)
),
// base_mesh
Mesh::sCreateUVSphere(45, 45, 0.9)
);
entity->mesh.addMesh(
0,
Transform::fromTrans(
Vector3f (0.0f, 0.55f, 0.0f)
),
Mesh::sCreateUVSphere (45, 45, 0.7)
);
entity->mesh.addMesh(
1,
Transform::fromTrans(
Vector3f (0.0f, 0.4f, 0.0f)
),
Mesh::sCreateUVSphere (45, 45, 0.5)
);
// mState->character->entity->mesh = bgfxutils::createCuboid (1.f, 1.f, 1.f);
// mState->character->entity->mesh = bgfxutils::createCylinder (20);
cout << "Creating render entity mesh ... success!" << endl;
}
CharacterEntity::~CharacterEntity() {
gRenderer->destroyEntity(entity);
entity = nullptr;
delete mRigModel;
mRigModel = nullptr;
}
bool CharacterEntity::LoadRig(const char* filename) {
gLog ("Creating rig model from %s ... ", filename);
LuaTable model_table = LuaTable::fromFile (filename);
bool load_result = LuaModelReadFromTable (model_table, mRigModel, false);
gLog ("Creating rig model from %s ... %s", filename, load_result ? "success" : "failed!");
gLog ("Rig model has %d degrees of freedom", mRigModel->qdot_size);
return load_result;
}
static float cur_time = 0.0f;
void CharacterEntity::Update(float dt) {
Vector3f mController_acceleration (
mController.mDirection[0] * cGroundAcceleration,
mController.mDirection[1] * cGroundAcceleration,
mController.mDirection[2] * cGroundAcceleration
);
Vector3f gravity (0.0f, -cGravity, 0.0f);
Vector3f damping (
-mVelocity[0] * cVelocityDamping,
0.0f,
-mVelocity[2] * cVelocityDamping
);
Vector3f acceleration = mController_acceleration + gravity + damping;
mVelocity = mVelocity + acceleration * dt;
if (mPosition[1] == 0.0f
&& mController.mState[CharacterController::ControlStateJump]) {
mVelocity[1] = cJumpVelocity;
}
// integrate mPosition
mPosition += mVelocity * dt;
if (mPosition[1] < 0.f) {
mPosition[1] = 0.f;
mVelocity[1] = 0.0f;
}
// apply transformation
entity->transform.translation.set(
mPosition[0],
mPosition[1],
mPosition[2]);
gRenderer->drawDebugSphere (Vector3f (0.f, 1.3 + sin(cur_time * 2.f), 0.f), 2.2f);
Quaternion quat (-cos(cur_time), 0.0f, 0.0f * sin(cur_time), 1.0f);
quat.normalize();
entity->mesh.localTransforms[0].rotation = quat;
// update matrices
entity->mesh.updateMatrices(entity->transform.toMatrix());
cur_time += dt;
}
void ShowCharacterPropertiesWindow (CharacterEntity* character) {
assert (character != nullptr);
ImGui::SetNextWindowSize (ImVec2(600.f, 300.0f), ImGuiSetCond_Once);
ImGui::SetNextWindowPos (ImVec2(400.f, 16.0f), ImGuiSetCond_Once);
ImGui::Begin("Character");
if (ImGui::Button ("Reset")) {
character->Reset();
}
ImGui::DragFloat3 ("Position", character->mPosition.data(), 0.01, -10.0f, 10.0f);
ImGui::DragFloat3 ("Velocity", character->mVelocity.data(), 0.01, -10.0f, 10.0f);
for (int i = 0; i < character->entity->mesh.meshes.size(); ++i) {
char buf[32];
snprintf (buf, 32, "Mesh %d", i);
ImGuiTreeNodeFlags node_flags = 0;
bool node_open = ImGui::TreeNodeEx(
buf,
node_flags);
if (node_open) {
Transform &transform = character->entity->mesh.localTransforms[i];
ImGui::DragFloat3 ("Position", transform.translation.data(), 0.01, -10.0f, 10.0f);
if (ImGui::Protot::DragFloat4Normalized ("Rotation", transform.rotation.data(), 0.001, -1.0f, 1.0f)) {
if (isnan(transform.rotation.squaredNorm())) {
std::cout << "nan! " << transform.rotation.transpose() << std::endl;
abort();
}
}
ImGui::DragFloat3 ("Scale", transform.scale.data(), 0.01, 0.001f, 10.0f);
ImGui::TreePop();
}
}
ImGui::End();
}
struct module_state {
};
static struct module_state *module_init() {
std::cout << "Module init called" << std::endl;
module_state *state = (module_state*) malloc(sizeof(*state));
return state;
}
template <typename Serializer>
static void module_serialize (
struct module_state *state,
Serializer* serializer) {
// SerializeVec3(*serializer, "protot.TestModule.entity.mPosition", state->character->mPosition);
}
static void module_finalize(struct module_state *state) {
std::cout << "Module finalize called" << std::endl;
free(state);
}
static void module_reload(struct module_state *state, void* read_serializer) {
std::cout << "Module reload called. State: " << state << std::endl;
// load the state of the entity
if (read_serializer != nullptr) {
module_serialize(state, static_cast<ReadSerializer*>(read_serializer));
}
}
static void module_unload(struct module_state *state, void* write_serializer) {
// serialize the state of the entity
if (write_serializer != nullptr) {
module_serialize(state, static_cast<WriteSerializer*>(write_serializer));
}
}
static bool module_step(struct module_state *state, float dt) {
return true;
}
extern "C" {
const struct module_api MODULE_API = {
.init = module_init,
.reload = module_reload,
.step = module_step,
.unload = module_unload,
.finalize = module_finalize
};
}