You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
189 lines
5.6 KiB
189 lines
5.6 KiB
/*
|
|
* Copyright (c) 2022-2023, NVIDIA CORPORATION. All rights reserved.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
* SPDX-FileCopyrightText: Copyright (c) 2014-2022 NVIDIA CORPORATION
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <vector>
|
|
#include <array>
|
|
|
|
#define _USE_MATH_DEFINES
|
|
#include <math.h>
|
|
|
|
#include "imgui_axis.hpp"
|
|
#include "nvmath/nvmath.h"
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// This IMGUI widget draw axis in red, green and blue at the position
|
|
// defined.
|
|
//
|
|
|
|
struct AxisGeom
|
|
{
|
|
AxisGeom()
|
|
{
|
|
const float asize = 1.0f; // length of arrow
|
|
const float aradius = 0.11f; // width of arrow tip
|
|
const float abase = 0.66f; // 1/3 of arrow length
|
|
const int asubdiv = 8;
|
|
|
|
// Cone
|
|
red.push_back({asize, 0, 0}); // 0 Tip
|
|
for(int i = 0; i <= asubdiv; ++i)
|
|
{
|
|
float a0 = 2.0F * float(M_PI) * (float(i)) / asubdiv; // Counter-clockwise
|
|
float y0 = cosf(a0) * aradius;
|
|
float z0 = sinf(a0) * aradius;
|
|
red.push_back({abase, y0, z0});
|
|
}
|
|
for(int i = 0; i <= asubdiv - 1; ++i) // Triangle fan
|
|
{
|
|
indices.push_back(0);
|
|
indices.push_back(i + 1);
|
|
indices.push_back(i + 2);
|
|
}
|
|
|
|
// Under Cap
|
|
int center = static_cast<int>(red.size());
|
|
red.push_back({abase, 0, 0}); // Center of cap
|
|
for(int i = 0; i <= asubdiv; ++i)
|
|
{
|
|
float a0 = -2.0F * float(M_PI) * (float(i)) / asubdiv; // Clockwise
|
|
float y0 = cosf(a0) * aradius;
|
|
float z0 = sinf(a0) * aradius;
|
|
red.push_back({abase, y0, z0});
|
|
}
|
|
for(int i = 0; i <= asubdiv - 1; ++i)
|
|
{
|
|
indices.push_back(center);
|
|
indices.push_back(center + i + 1);
|
|
indices.push_back(center + i + 2);
|
|
}
|
|
|
|
// Start of arrow
|
|
red.push_back({0, 0, 0});
|
|
|
|
// Other arrows are permutations of the Red arrow
|
|
for(const auto& v : red)
|
|
{
|
|
green.push_back({v.z, v.x, v.y});
|
|
blue.push_back({v.y, v.z, v.x});
|
|
}
|
|
}
|
|
|
|
std::vector<nvmath::vec3f> red;
|
|
std::vector<nvmath::vec3f> green;
|
|
std::vector<nvmath::vec3f> blue;
|
|
std::vector<int> indices;
|
|
|
|
// Return the transformed arrow
|
|
std::vector<nvmath::vec3f> transform(const std::vector<nvmath::vec3f>& in_vec, const ImVec2& pos, const nvmath::mat4f& modelView, float size)
|
|
{
|
|
std::vector<nvmath::vec3f> temp(in_vec.size());
|
|
|
|
for(size_t i = 0; i < in_vec.size(); ++i)
|
|
{
|
|
temp[i] = nvmath::vec3f(modelView * nvmath::vec4f(in_vec[i], 0.F)); // Rotate
|
|
temp[i].x *= size; // Scale
|
|
temp[i].y *= -size; // - invert Y
|
|
temp[i].x += pos.x; // Translate
|
|
temp[i].y += pos.y;
|
|
}
|
|
return temp;
|
|
}
|
|
|
|
void drawTriangle(ImVec2 v0, ImVec2 v1, ImVec2 v2, const ImVec2& uv, ImU32 col)
|
|
{
|
|
auto draw_list = ImGui::GetWindowDrawList();
|
|
|
|
ImVec2 d0 = ImVec2(v1.x - v0.x, v1.y - v0.y);
|
|
ImVec2 d1 = ImVec2(v2.x - v0.x, v2.y - v0.y);
|
|
float c = (d0.x * d1.y) - (d0.y * d1.x); // Cross
|
|
|
|
if(c > 0.0f) // Culling to avoid z-fighting
|
|
{
|
|
v1 = v0; // Culled triangles are degenerated to
|
|
v2 = v0; // avoid displaying them
|
|
}
|
|
|
|
draw_list->PrimVtx(v0, uv, col);
|
|
draw_list->PrimVtx(v1, uv, col);
|
|
draw_list->PrimVtx(v2, uv, col);
|
|
}
|
|
|
|
// Draw the arrow
|
|
void draw(const std::vector<nvmath::vec3f>& vertex, ImU32 col)
|
|
{
|
|
auto draw_list = ImGui::GetWindowDrawList();
|
|
const ImVec2 uv = ImGui::GetFontTexUvWhitePixel();
|
|
|
|
int num_indices = static_cast<int>(indices.size());
|
|
draw_list->PrimReserve(num_indices, num_indices); // num vert/indices
|
|
|
|
// Draw all triangles
|
|
for(int i = 0; i < num_indices; i += 3)
|
|
{
|
|
int i0 = indices[i];
|
|
int i1 = indices[i + 1];
|
|
int i2 = indices[i + 2];
|
|
ImVec2 v0 = {vertex[i0].x, vertex[i0].y};
|
|
ImVec2 v1 = {vertex[i1].x, vertex[i1].y};
|
|
ImVec2 v2 = {vertex[i2].x, vertex[i2].y};
|
|
drawTriangle(v0, v1, v2, uv, col);
|
|
}
|
|
|
|
// Draw the line
|
|
draw_list->AddLine(ImVec2(vertex[0].x, vertex[0].y), ImVec2(vertex.back().x, vertex.back().y), col,
|
|
1.0F * ImGui::GetWindowDpiScale());
|
|
}
|
|
};
|
|
|
|
|
|
void ImGuiH::Axis(ImVec2 pos, const nvmath::mat4f& modelView, float size /*= 20.f*/)
|
|
{
|
|
static AxisGeom a;
|
|
|
|
struct Arrow
|
|
{
|
|
std::vector<nvmath::vec3f> v;
|
|
ImU32 c{0};
|
|
};
|
|
|
|
size *= ImGui::GetWindowDpiScale();
|
|
|
|
std::array<Arrow, 3> arrow;
|
|
arrow[0].v = a.transform(a.red, pos, modelView, size);
|
|
arrow[0].c = IM_COL32(200, 0, 0, 255);
|
|
arrow[1].v = a.transform(a.green, pos, modelView, size);
|
|
arrow[1].c = IM_COL32(0, 200, 0, 255);
|
|
arrow[2].v = a.transform(a.blue, pos, modelView, size);
|
|
arrow[2].c = IM_COL32(0, 0, 200, 255);
|
|
|
|
// Sort from smallest Z to nearest (Painter algorithm)
|
|
if(arrow[1].v[0].z < arrow[0].v[0].z)
|
|
std::swap(arrow[0], arrow[1]);
|
|
if(arrow[2].v[0].z < arrow[1].v[0].z)
|
|
{
|
|
std::swap(arrow[1], arrow[2]);
|
|
if(arrow[1].v[0].z < arrow[0].v[0].z)
|
|
std::swap(arrow[1], arrow[0]);
|
|
}
|
|
|
|
// Draw all axis
|
|
a.draw(arrow[0].v, arrow[0].c);
|
|
a.draw(arrow[1].v, arrow[1].c);
|
|
a.draw(arrow[2].v, arrow[2].c);
|
|
}
|
|
|