Refactored character into separate module
parent
a942ff9ea9
commit
dc6bc60dd9
|
@ -80,6 +80,9 @@ int main(void)
|
|||
int width, height;
|
||||
glfwGetWindowSize(gWindow, &width, &height);
|
||||
|
||||
std::cout << "OpenGL Version: " << glGetString(GL_VERSION) << endl;
|
||||
std::cout << "GLSL Version : " << glGetString(GL_SHADING_LANGUAGE_VERSION) << endl;
|
||||
|
||||
// Initialize Renderer
|
||||
bgfx::glfwSetWindow(gWindow);
|
||||
bgfx::renderFrame();
|
||||
|
@ -99,6 +102,7 @@ int main(void)
|
|||
printf("Initializing ModuleManager...\n");
|
||||
RuntimeModuleManager module_manager;
|
||||
module_manager.RegisterModule("src/modules/libRenderModule.so");
|
||||
module_manager.RegisterModule("src/modules/libCharacterModule.so");
|
||||
module_manager.RegisterModule("src/modules/libTestModule.so");
|
||||
|
||||
// Setup global variables
|
||||
|
|
|
@ -11,6 +11,15 @@ ADD_LIBRARY (TestModule SHARED
|
|||
TestModule.cc
|
||||
)
|
||||
|
||||
TARGET_LINK_LIBRARIES ( TestModule
|
||||
ADD_LIBRARY (CharacterModule SHARED
|
||||
CharacterModule.cc
|
||||
)
|
||||
|
||||
TARGET_LINK_LIBRARIES ( CharacterModule
|
||||
RenderModule
|
||||
)
|
||||
|
||||
TARGET_LINK_LIBRARIES ( TestModule
|
||||
CharacterModule
|
||||
RenderModule
|
||||
)
|
||||
|
|
|
@ -0,0 +1,203 @@
|
|||
#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"
|
||||
|
||||
using namespace std;
|
||||
|
||||
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;
|
||||
|
||||
CharacterEntity::CharacterEntity() {
|
||||
entity = gRenderer->createEntity();
|
||||
position = Vector3f (0.f, 0.0f, 0.0f);
|
||||
cout << "Creating render entity ... success!" << endl;
|
||||
|
||||
cout << "Creating render entity mesh ..." << endl;
|
||||
|
||||
// Build the snowman
|
||||
entity->mesh.addMesh(
|
||||
- 1,
|
||||
Transform::fromTrans(
|
||||
Vector3f (0.0f, 0.9 * 0.5f, 0.0f)
|
||||
),
|
||||
bgfxutils::createUVSphere (45, 45, 0.9)
|
||||
);
|
||||
|
||||
entity->mesh.addMesh(
|
||||
0,
|
||||
Transform::fromTrans(
|
||||
Vector3f (0.0f, 0.55f, 0.0f)
|
||||
),
|
||||
bgfxutils::createUVSphere (45, 45, 0.7)
|
||||
);
|
||||
|
||||
entity->mesh.addMesh(
|
||||
1,
|
||||
Transform::fromTrans(
|
||||
Vector3f (0.0f, 0.4f, 0.0f)
|
||||
),
|
||||
bgfxutils::createUVSphere (45, 45, 0.5)
|
||||
);
|
||||
|
||||
// state->character->entity->mesh = bgfxutils::createCuboid (1.f, 1.f, 1.f);
|
||||
// state->character->entity->mesh = bgfxutils::createCylinder (20);
|
||||
cout << "Creating render entity mesh ... success!" << endl;
|
||||
}
|
||||
|
||||
CharacterEntity::~CharacterEntity() {
|
||||
gRenderer->destroyEntity(entity);
|
||||
entity = nullptr;
|
||||
}
|
||||
|
||||
void CharacterEntity::update(float dt) {
|
||||
Vector3f controller_acceleration (
|
||||
controller.direction[0] * cGroundAcceleration,
|
||||
controller.direction[1] * cGroundAcceleration,
|
||||
controller.direction[2] * cGroundAcceleration
|
||||
);
|
||||
|
||||
Vector3f gravity (0.0f, -cGravity, 0.0f);
|
||||
Vector3f damping (
|
||||
-velocity[0] * cVelocityDamping,
|
||||
0.0f,
|
||||
-velocity[2] * cVelocityDamping
|
||||
);
|
||||
|
||||
Vector3f acceleration = controller_acceleration + gravity + damping;
|
||||
|
||||
velocity = velocity + acceleration * dt;
|
||||
|
||||
if (position[1] == 0.0f
|
||||
&& controller.state[CharacterController::ControlStateJump]) {
|
||||
velocity[1] = cJumpVelocity;
|
||||
}
|
||||
|
||||
// integrate position
|
||||
position += velocity * dt;
|
||||
|
||||
if (position[1] < 0.f) {
|
||||
position[1] = 0.f;
|
||||
velocity[1] = 0.0f;
|
||||
}
|
||||
|
||||
// apply transformation
|
||||
entity->transform.translation.set(
|
||||
position[0],
|
||||
position[1],
|
||||
position[2]);
|
||||
|
||||
entity->mesh.updateMatrices(entity->transform.toMatrix());
|
||||
}
|
||||
|
||||
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->position.data(), 0.01, -10.0f, 10.0f);
|
||||
ImGui::DragFloat3 ("Velocity", character->velocity.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.position", state->character->position);
|
||||
}
|
||||
|
||||
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) {
|
||||
glfwSetScrollCallback (gWindow, nullptr);
|
||||
|
||||
// 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
|
||||
};
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "math_types.h"
|
||||
|
||||
#include "Globals.h"
|
||||
|
||||
#include "imgui_protot_ext.h"
|
||||
|
||||
struct CharacterController {
|
||||
enum ControllerState {
|
||||
ControlStateJump,
|
||||
ControlStateLast
|
||||
};
|
||||
|
||||
bool state[ControlStateLast];
|
||||
|
||||
Vector3f direction = Vector3f::Zero();
|
||||
|
||||
void reset() {
|
||||
for (int i = 0; i < ControlStateLast; i++) {
|
||||
state[i] = false;
|
||||
}
|
||||
|
||||
direction.setZero();
|
||||
}
|
||||
|
||||
CharacterController() {
|
||||
reset();
|
||||
};
|
||||
};
|
||||
|
||||
struct CharacterEntity {
|
||||
/// Render entity
|
||||
Entity *entity = nullptr;
|
||||
Vector3f position;
|
||||
Vector3f velocity;
|
||||
CharacterController controller;
|
||||
|
||||
CharacterEntity ();
|
||||
~CharacterEntity ();
|
||||
|
||||
void reset() {
|
||||
position.setZero();
|
||||
velocity.setZero();
|
||||
controller.reset();
|
||||
}
|
||||
|
||||
void update(float dt);
|
||||
};
|
||||
|
||||
void ShowCharacterPropertiesWindow (CharacterEntity* character);
|
|
@ -1,6 +1,5 @@
|
|||
#include "RuntimeModule.h"
|
||||
#include "Globals.h"
|
||||
#include "modules/RenderModule.h"
|
||||
#include "3rdparty/ocornut-imgui/imgui.h"
|
||||
#include "imgui/imgui.h"
|
||||
#include <bx/fpumath.h>
|
||||
|
@ -12,6 +11,9 @@
|
|||
#include "RuntimeModuleManager.h"
|
||||
#include "Serializer.h"
|
||||
|
||||
#include "modules/RenderModule.h"
|
||||
#include "modules/CharacterModule.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
|
@ -23,90 +25,6 @@ bool fps_camera = true;
|
|||
|
||||
// Boilerplate for the module reload stuff
|
||||
|
||||
struct CharacterController {
|
||||
enum ControllerState {
|
||||
ControlJump,
|
||||
ControlStateLast
|
||||
};
|
||||
|
||||
bool state[ControlStateLast];
|
||||
|
||||
Vector3f direction = Vector3f::Zero();
|
||||
|
||||
void reset() {
|
||||
for (int i = 0; i < ControlStateLast; i++) {
|
||||
state[i] = false;
|
||||
}
|
||||
|
||||
direction.setZero();
|
||||
}
|
||||
|
||||
CharacterController() {
|
||||
reset();
|
||||
};
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
struct CharacterEntity {
|
||||
/// Render entity
|
||||
Entity *entity;
|
||||
Vector3f position;
|
||||
Vector3f velocity;
|
||||
CharacterController controller;
|
||||
|
||||
void reset() {
|
||||
position.setZero();
|
||||
velocity.setZero();
|
||||
controller.reset();
|
||||
}
|
||||
|
||||
void update(float dt) {
|
||||
Vector3f controller_acceleration (
|
||||
controller.direction[0] * cGroundAcceleration,
|
||||
controller.direction[1] * cGroundAcceleration,
|
||||
controller.direction[2] * cGroundAcceleration
|
||||
);
|
||||
|
||||
Vector3f gravity (0.0f, -cGravity, 0.0f);
|
||||
Vector3f damping (
|
||||
-velocity[0] * cVelocityDamping,
|
||||
0.0f,
|
||||
-velocity[2] * cVelocityDamping
|
||||
);
|
||||
|
||||
Vector3f acceleration = controller_acceleration + gravity + damping;
|
||||
|
||||
velocity = velocity + acceleration * dt;
|
||||
|
||||
if (position[1] == 0.0f
|
||||
&& controller.state[CharacterController::ControlJump]) {
|
||||
velocity[1] = cJumpVelocity;
|
||||
}
|
||||
|
||||
// integrate position
|
||||
position += velocity * dt;
|
||||
|
||||
if (position[1] < 0.f) {
|
||||
position[1] = 0.f;
|
||||
velocity[1] = 0.0f;
|
||||
}
|
||||
|
||||
// apply transformation
|
||||
entity->transform.translation.set(
|
||||
position[0],
|
||||
position[1],
|
||||
position[2]);
|
||||
|
||||
entity->mesh.updateMatrices(entity->transform.toMatrix());
|
||||
}
|
||||
};
|
||||
|
||||
struct module_state {
|
||||
bool fps_camera;
|
||||
float camera_theta;
|
||||
|
@ -257,7 +175,7 @@ void handle_keyboard (struct module_state *state, float dt) {
|
|||
}
|
||||
|
||||
if (glfwGetKey(gWindow, GLFW_KEY_SPACE) == GLFW_PRESS) {
|
||||
controller.state[CharacterController::ControlJump] = true;
|
||||
controller.state[CharacterController::ControlStateJump] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -288,6 +206,7 @@ static void module_serialize (
|
|||
SerializeVec3(*serializer, "protot.TestModule.entity.velocity", state->character->velocity);
|
||||
SerializeBool(*serializer, "protot.TestModule.character_window.visible", state->character_properties_window_visible);
|
||||
SerializeBool(*serializer, "protot.TestModule.modules_window.visible", state->modules_window_visible);
|
||||
SerializeBool(*serializer, "protot.TestModule.imgui_demo_window_visible", state->imgui_demo_window_visible);
|
||||
SerializeInt(*serializer, "protot.TestModule.modules_window.selection_index", state->modules_window_selected_index);
|
||||
}
|
||||
|
||||
|
@ -304,41 +223,6 @@ static void module_reload(struct module_state *state, void* read_serializer) {
|
|||
mouse_scroll_y = 0;
|
||||
|
||||
cout << "Creating render entity ..." << endl;
|
||||
state->character->entity = gRenderer->createEntity();
|
||||
state->character->position = Vector3f (0.f, 0.0f, 0.0f);
|
||||
cout << "Creating render entity ... success!" << endl;
|
||||
|
||||
cout << "Creating render entity mesh ..." << endl;
|
||||
|
||||
// Build the snowman
|
||||
state->character->entity->mesh.addMesh(
|
||||
- 1,
|
||||
Transform::fromTrans(
|
||||
Vector3f (0.0f, 0.9 * 0.5f, 0.0f)
|
||||
),
|
||||
bgfxutils::createUVSphere (45, 45, 0.9)
|
||||
);
|
||||
|
||||
state->character->entity->mesh.addMesh(
|
||||
0,
|
||||
Transform::fromTrans(
|
||||
Vector3f (0.0f, 0.55f, 0.0f)
|
||||
),
|
||||
bgfxutils::createUVSphere (45, 45, 0.7)
|
||||
);
|
||||
|
||||
state->character->entity->mesh.addMesh(
|
||||
1,
|
||||
Transform::fromTrans(
|
||||
Vector3f (0.0f, 0.4f, 0.0f)
|
||||
),
|
||||
bgfxutils::createUVSphere (45, 45, 0.5)
|
||||
);
|
||||
|
||||
// state->character->entity->mesh = bgfxutils::createCuboid (1.f, 1.f, 1.f);
|
||||
// state->character->entity->mesh = bgfxutils::createCylinder (20);
|
||||
cout << "Creating render entity mesh ... success!" << endl;
|
||||
|
||||
// load the state of the entity
|
||||
if (read_serializer != nullptr) {
|
||||
module_serialize(state, static_cast<ReadSerializer*>(read_serializer));
|
||||
|
@ -365,8 +249,6 @@ static void module_unload(struct module_state *state, void* write_serializer) {
|
|||
}
|
||||
state->character->entity = nullptr;
|
||||
|
||||
Vector3f bla (1.2f, 1.3f, 1.6f);
|
||||
|
||||
std::cout << "TestModule unloaded. State: " << state << std::endl;
|
||||
}
|
||||
|
||||
|
@ -426,100 +308,6 @@ void ShowModulesWindow(struct module_state *state) {
|
|||
ImGui::End();
|
||||
}
|
||||
|
||||
// Returns a normalized vector where the value at the modified index
|
||||
// is kept and only the other values are being modified so that the
|
||||
// resulting vector is normalized.
|
||||
bool DragFloat4Normalized(const char* label, float v[4], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", float power = 1.0f)
|
||||
{
|
||||
float old_values[4];
|
||||
memcpy (old_values, v, sizeof(float) * 4);
|
||||
|
||||
bool modified = ImGui::DragFloat4(label, v, v_speed, v_min, v_max, display_format, power);
|
||||
if (modified) {
|
||||
int mod_index = -1;
|
||||
Vector3f other_values;
|
||||
int other_index = 0;
|
||||
|
||||
// determine the modified index and copy the unmodified values to
|
||||
// other_values
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (old_values[i] != v[i]) {
|
||||
mod_index = i;
|
||||
} else {
|
||||
other_values[other_index] = v[i];
|
||||
other_index++;
|
||||
}
|
||||
}
|
||||
|
||||
// normalize, but take zero length of other values into account and
|
||||
// also modification of vectors with a single 1.
|
||||
float other_length = other_values.norm();
|
||||
if (fabs(v[mod_index]) >= 1.0f - 1.0e-6f || other_length == 0.0f) {
|
||||
other_values.setZero();
|
||||
v[mod_index] = 1.0f * v[mod_index] < 0.0f ? -1.0f : 1.0f;
|
||||
} else {
|
||||
// normalize other_values to have the remaining length
|
||||
other_values = other_values * (1.f / other_length) * (sqrt(1.0f - v[mod_index] * v[mod_index]));
|
||||
}
|
||||
|
||||
// construct the new vector
|
||||
other_index = 0;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (i != mod_index) {
|
||||
v[i] = other_values[other_index];
|
||||
other_index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return modified;
|
||||
}
|
||||
|
||||
|
||||
|
||||
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->position.data(), 0.01, -10.0f, 10.0f);
|
||||
ImGui::DragFloat3 ("Velocity", character->velocity.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 (DragFloat4Normalized ("Rotation", transform.rotation.data(), 0.001, -1.0f, 1.0f)) {
|
||||
if (isnan(transform.rotation.squaredNorm())) {
|
||||
cout << "nan! " << transform.rotation.transpose() << endl;
|
||||
abort();
|
||||
}
|
||||
}
|
||||
ImGui::DragFloat3 ("Scale", transform.scale.data(), 0.01, 0.001f, 10.0f);
|
||||
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
static bool module_step(struct module_state *state, float dt) {
|
||||
if (gRenderer == nullptr)
|
||||
return false;
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
#pragma once
|
||||
|
||||
#include "math_types.h"
|
||||
|
||||
namespace ImGui {
|
||||
|
||||
namespace Protot {
|
||||
|
||||
// Returns a normalized vector where the value at the modified index
|
||||
// is kept and only the other values are being modified so that the
|
||||
// resulting vector is normalized.
|
||||
bool DragFloat4Normalized(const char* label, float v[4], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", float power = 1.0f)
|
||||
{
|
||||
float old_values[4];
|
||||
memcpy (old_values, v, sizeof(float) * 4);
|
||||
|
||||
bool modified = ImGui::DragFloat4(label, v, v_speed, v_min, v_max, display_format, power);
|
||||
if (modified) {
|
||||
int mod_index = -1;
|
||||
Vector3f other_values;
|
||||
int other_index = 0;
|
||||
|
||||
// determine the modified index and copy the unmodified values to
|
||||
// other_values
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (old_values[i] != v[i]) {
|
||||
mod_index = i;
|
||||
} else {
|
||||
other_values[other_index] = v[i];
|
||||
other_index++;
|
||||
}
|
||||
}
|
||||
|
||||
// normalize, but take zero length of other values into account and
|
||||
// also modification of vectors with a single 1.
|
||||
float other_length = other_values.norm();
|
||||
if (fabs(v[mod_index]) >= 1.0f - 1.0e-6f || other_length == 0.0f) {
|
||||
other_values.setZero();
|
||||
v[mod_index] = 1.0f * v[mod_index] < 0.0f ? -1.0f : 1.0f;
|
||||
} else {
|
||||
// normalize other_values to have the remaining length
|
||||
other_values = other_values * (1.f / other_length) * (sqrt(1.0f - v[mod_index] * v[mod_index]));
|
||||
}
|
||||
|
||||
// construct the new vector
|
||||
other_index = 0;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (i != mod_index) {
|
||||
v[i] = other_values[other_index];
|
||||
other_index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return modified;
|
||||
}
|
||||
|
||||
} // Protot
|
||||
|
||||
} // ImGui
|
Loading…
Reference in New Issue