From 84efe9b9aa6e15bc5db679ff1df213cdc26ccb5f Mon Sep 17 00:00:00 2001 From: Martin Felis Date: Sun, 8 Jan 2017 22:47:54 +0100 Subject: [PATCH] Drawing little snowman and smaller goodies - Character properties window - Normalized ImGui::DragFloat4 that can be used for Quaternions - Fixed issue of skymap movement The snowman has unfortunately some shadow mapping issues... --- src/modules/RenderModule.cc | 31 ++++++--- src/modules/RenderUtils.cc | 20 +++--- src/modules/TestModule.cc | 131 ++++++++++++++++++++++++++++++++---- 3 files changed, 149 insertions(+), 33 deletions(-) diff --git a/src/modules/RenderModule.cc b/src/modules/RenderModule.cc index 8aff43c..36b1dde 100644 --- a/src/modules/RenderModule.cc +++ b/src/modules/RenderModule.cc @@ -769,9 +769,9 @@ void Camera::updateMatrices() { bx::vec3Cross(tmp, dirNorm, right); bx::vec3Norm(up, tmp); - mtxEnv[ 0] = right[0]; - mtxEnv[ 1] = right[1]; - mtxEnv[ 2] = right[2]; + mtxEnv[ 0] = -right[0]; + mtxEnv[ 1] = -right[1]; + mtxEnv[ 2] = -right[2]; mtxEnv[ 3] = 0.0f; mtxEnv[ 4] = up[0]; mtxEnv[ 5] = up[1]; @@ -1276,13 +1276,16 @@ void Renderer::paintGL() { bx::mtxLookAtRh(lights[i].mtxView, eye, at); - lights[i].area = 20.0f; - lights[i].near = 0.f; - lights[i].far = 40.f; + lights[i].area = 10.0f; + lights[i].near = 10.f; + lights[i].far = 20.f; // bx::mtxProj(lightProj, 20.0f, 1., 5.f, 10.0f); - bx::mtxOrthoRh(lights[i].mtxProj, -lights[i].area, lights[i].area, -lights[i].area, lights[i].area, lights[i].near, lights[i].far); + bx::mtxOrthoRh(lights[i].mtxProj, + lights[i].area, -lights[i].area, + lights[i].area, -lights[i].area, + lights[i].near, lights[i].far); // lights: shadow matrix const float sy = flipV ? 0.5f : -0.5f; @@ -1323,6 +1326,11 @@ void Renderer::paintGL() { bgfx::setViewRect(RenderState::Debug, 0, 0, width, height); bgfx::setViewTransform(RenderState::Debug, cameras[activeCameraIndex].mtxView, cameras[activeCameraIndex].mtxProj); + + // + // Pass: floor + // + // setup floor float mtxFloor[16]; bx::mtxSRT(mtxFloor @@ -1356,6 +1364,10 @@ void Renderer::paintGL() { bgfx::touch(RenderState::Scene); bgfx::touch(RenderState::Skybox); + // + // Pass: skybox + // + if (drawSkybox) { // Skybox pass memcpy (IBL::uniforms.m_cameraPos, cameras[activeCameraIndex].eye.data(), 3 * sizeof(float)); @@ -1419,7 +1431,7 @@ void Renderer::paintGL() { } // - // Shadow map and scene pass + // Pass: shadow map and scene pass // // render entities @@ -1429,14 +1441,11 @@ void Renderer::paintGL() { // shadow map pass bx::mtxMul(lightMtx, entities[i]->transform.toMatrix().data(), lights[0].mtxShadow); bgfx::setUniform(lights[0].u_lightMtx, lightMtx); - bgfx::setUniform(lights[0].u_lightPos, lights[0].pos); - bgfx::setUniform(u_color, entities[i]->color, 4); entities[i]->mesh.submit (&s_renderStates[RenderState::ShadowMap]); // scene pass bx::mtxMul(lightMtx, entities[i]->transform.toMatrix().data(), lights[0].mtxShadow); bgfx::setUniform(lights[0].u_lightMtx, lightMtx); - bgfx::setUniform(lights[0].u_lightPos, lights[0].pos); bgfx::setUniform(u_color, entities[i]->color, 4); entities[i]->mesh.submit (&s_renderStates[RenderState::Scene]); } diff --git a/src/modules/RenderUtils.cc b/src/modules/RenderUtils.cc index 0dc4b80..9806d9a 100644 --- a/src/modules/RenderUtils.cc +++ b/src/modules/RenderUtils.cc @@ -1115,11 +1115,11 @@ Mesh *createUVSphere (int rows, int segments) { float alpha0 = j * row_d * M_PI; float alpha1 = (j + 1) * row_d * M_PI; - float r0 = sin (alpha0); - float r1 = sin (alpha1); + float r0 = sin (alpha0) * 0.5f; + float r1 = sin (alpha1) * 0.5f; - float h0 = cos (alpha0); - float h1 = cos (alpha1); + float h0 = cos (alpha0) * 0.5f; + float h1 = cos (alpha1) * 0.5f; for (unsigned int i = 0; i < segments; i++) { Vector3f v0, v1, v2, v3; @@ -1131,22 +1131,22 @@ Mesh *createUVSphere (int rows, int segments) { v2 = Vector3f (r0 * cos(a1), h0, r0 * sin (a1)); v3 = Vector3f (r0 * cos(a0), h0, r0 * sin (a0)); - vertices.push_back (Vector4f(v0[0], v0[1], v0[2], 0.f)); + vertices.push_back (Vector4f(v0[0], v0[1], v0[2], 1.f)); normals.push_back (v0 * 1.f/ v0.norm()); - vertices.push_back (Vector4f(v2[0], v2[1], v2[2], 0.f)); + vertices.push_back (Vector4f(v2[0], v2[1], v2[2], 1.f)); normals.push_back (v2 * 1.f/ v2.norm()); - vertices.push_back (Vector4f(v1[0], v1[1], v1[2], 0.f)); + vertices.push_back (Vector4f(v1[0], v1[1], v1[2], 1.f)); normals.push_back (v1 * 1.f/ v1.norm()); - vertices.push_back (Vector4f(v0[0], v0[1], v0[2], 0.f)); + vertices.push_back (Vector4f(v0[0], v0[1], v0[2], 1.f)); normals.push_back (v0 * 1.f/ v0.norm()); - vertices.push_back (Vector4f(v3[0], v3[1], v3[2], 0.f)); + vertices.push_back (Vector4f(v3[0], v3[1], v3[2], 1.f)); normals.push_back (v3 * 1.f/ v3.norm()); - vertices.push_back (Vector4f(v2[0], v2[1], v2[2], 0.f)); + vertices.push_back (Vector4f(v2[0], v2[1], v2[2], 1.f)); normals.push_back (v2 * 1.f/ v2.norm()); } } diff --git a/src/modules/TestModule.cc b/src/modules/TestModule.cc index ec2b4dc..b577af4 100644 --- a/src/modules/TestModule.cc +++ b/src/modules/TestModule.cc @@ -46,6 +46,13 @@ struct CharacterController { }; }; +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; @@ -53,10 +60,11 @@ struct CharacterEntity { Vector3f velocity; CharacterController controller; - float cJumpVelocity = 20.0f; - float cVelocityDamping = 2.0f; - float cGravity = 30.0f; - float cGroundAcceleration = 30.0f; + void reset() { + position.setZero(); + velocity.setZero(); + controller.reset(); + } void update(float dt) { Vector3f controller_acceleration ( @@ -78,7 +86,7 @@ struct CharacterEntity { if (position[1] == 0.0f && controller.state[CharacterController::ControlJump]) { - velocity[1] += cJumpVelocity; + velocity[1] = cJumpVelocity; } // integrate position @@ -86,12 +94,13 @@ struct CharacterEntity { if (position[1] < 0.f) { position[1] = 0.f; + velocity[1] = 0.0f; } // apply transformation entity->transform.translation.set( position[0], - position[1] + 1.0f, + position[1], position[2]); entity->mesh.updateMatrices(entity->transform.toMatrix()); @@ -285,15 +294,30 @@ static void module_reload(struct module_state *state) { cout << "Creating render entity ..." << endl; state->character->entity = gRenderer->createEntity(); - state->character->position = Vector3f (0.f, 0.74f, 0.0f); + state->character->position = Vector3f (0.f, 0.0f, 0.0f); cout << "Creating render entity ... success!" << endl; cout << "Creating render entity mesh ..." << endl; - state->character->entity->mesh.addMesh( - -1, - Transform(), - bgfxutils::createUVSphere (45, 45) - ); + + Vector3f snowman_offsets (0.45f, 0.35f, 0.25f); + float height_offset = 0.0f; + for (int i = 0; i < 3; i++) { + float radius = cCharacterHeight * snowman_offsets[i]; + Transform transform = Transform::fromTransRotScale( + Vector3f(0.f, height_offset + radius * 0.5f, 0.0f), + Quaternion(0.0f, 0.0f, 0.0f, 1.0f), + Vector3f(radius, radius, radius) + ); + + state->character->entity->mesh.addMesh( + -1, + transform, + bgfxutils::createUVSphere (45, 45) + ); + + height_offset += radius * 0.8; + } + // 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; @@ -385,13 +409,96 @@ 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(); }