git.s-ol.nu forks/DiligentTools / 6634520
Added ImGuiUtils and imGuIZMO widget Egor Yusov 3 years ago
6 changed file(s) with 1344 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
22 project(Diligent-Imgui CXX)
33
44 set(DEAR_IMGUI_PATH ../ThirdParty/imgui)
5 set(IMGUIZMO_QUAT_PATH ../ThirdParty/imGuIZMO.quat)
6
57 set(DEAR_IMGUI_INCLUDE
68 ${DEAR_IMGUI_PATH}/imconfig.h
79 ${DEAR_IMGUI_PATH}/imgui_internal.h
3032 src/ImGuiImplWin32.cpp
3133 )
3234
35 set(IMGUIZMO_QUAT_SOURCE
36 ${IMGUIZMO_QUAT_PATH}/imGuIZMO.cpp
37 ${IMGUIZMO_QUAT_PATH}/imGuIZMO.h
38 )
39
3340 set(INTERFACE
3441 interface/ImGuiImplDiligent.h
3542 interface/ImGuiImplWin32.h
43 interface/ImGuiUtils.h
3644 )
3745
38 add_library(Diligent-Imgui STATIC ${SOURCE} ${INCLUDE} ${INTERFACE} ${DEAR_IMGUI_SOURCE} ${DEAR_IMGUI_INCLUDE} ${DEAR_IMGUI_INTERFACE})
46 add_library(Diligent-Imgui STATIC ${SOURCE} ${INCLUDE} ${INTERFACE} ${DEAR_IMGUI_SOURCE} ${DEAR_IMGUI_INCLUDE} ${DEAR_IMGUI_INTERFACE} ${IMGUIZMO_QUAT_SOURCE})
3947 set_common_target_properties(Diligent-Imgui)
4048
4149 target_include_directories(Diligent-Imgui
4250 PUBLIC
4351 interface
52 ${IMGUIZMO_QUAT_PATH}
4453 ${DEAR_IMGUI_PATH}
4554 PRIVATE
4655 include
5059 source_group("src" FILES ${SOURCE})
5160 source_group("include" FILES ${INCLUDE})
5261 source_group("interface" FILES ${INTERFACE})
62 source_group("imGuIZMO.quat" FILES ${IMGUIZMO_QUAT_SOURCE})
5363
5464 target_link_libraries(Diligent-Imgui
5565 PRIVATE
0 /* Copyright 2019 Diligent Graphics LLC
1 *
2 * Licensed under the Apache License, Version 2.0 (the "License");
3 * you may not use this file except in compliance with the License.
4 * You may obtain a copy of the License at
5 *
6 * http://www.apache.org/licenses/LICENSE-2.0
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
9 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
10 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
11 *
12 * In no event and under no legal theory, whether in tort (including negligence),
13 * contract, or otherwise, unless required by applicable law (such as deliberate
14 * and grossly negligent acts) or agreed to in writing, shall any Contributor be
15 * liable for any damages, including any direct, indirect, special, incidental,
16 * or consequential damages of any character arising as a result of this License or
17 * out of the use or inability to use the software (including but not limited to damages
18 * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
19 * all other commercial damages or losses), even if such Contributor has been advised
20 * of the possibility of such damages.
21 */
22
23 #pragma once
24
25 #include "imgui.h"
26 #include "imgui_internal.h"
27
28 namespace Diligent
29 {
30
31 class ImGuiScopedDisabler
32 {
33 public:
34 ImGuiScopedDisabler(bool Disable, float AlphaScale = 0.25f) :
35 m_IsDisabled(Disable)
36 {
37 if (m_IsDisabled)
38 {
39 ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
40 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * AlphaScale);
41 }
42 }
43
44 ~ImGuiScopedDisabler()
45 {
46 if (m_IsDisabled)
47 {
48 ImGui::PopItemFlag();
49 ImGui::PopStyleVar();
50 }
51 }
52
53 private:
54 const bool m_IsDisabled;
55 };
56
57 }
1515 install(FILES tinygltf/LICENSE DESTINATION ${LICENSE_INSTALL_PATH} RENAME tinygltf-license.txt)
1616 install(FILES zlib-1.2.8/README DESTINATION ${LICENSE_INSTALL_PATH} RENAME zlib-readme.txt)
1717 install(FILES imgui/LICENSE.txt DESTINATION ${LICENSE_INSTALL_PATH} RENAME imgui-license.txt)
18 install(FILES imGuIZMO.quat/license.txt DESTINATION ${LICENSE_INSTALL_PATH} RENAME imGuIZMO.quat-license.txt)
0 //------------------------------------------------------------------------------
1 // Copyright (c) 2018-2019 Michele Morrone
2 // All rights reserved.
3 //
4 // https://michelemorrone.eu - https://BrutPitt.com
5 //
6 // twitter: https://twitter.com/BrutPitt - github: https://github.com/BrutPitt
7 //
8 // mailto:brutpitt@gmail.com - mailto:me@michelemorrone.eu
9 //
10 // This software is distributed under the terms of the BSD 2-Clause license
11 //------------------------------------------------------------------------------
12 //
13 // Modified by Egor Yusov, Diligent Graphics LLC
14
15
16 #include "BasicMath.h"
17 #include "imGuIZMO.h"
18
19
20 ImVector<Diligent::float3> imguiGizmo::sphereVtx;
21 ImVector<int> imguiGizmo::sphereTess;
22 ImVector<Diligent::float3> imguiGizmo::arrowVtx[4];
23 ImVector<Diligent::float3> imguiGizmo::arrowNorm[4];
24 ImVector<Diligent::float3> imguiGizmo::cubeVtx;
25 ImVector<Diligent::float3> imguiGizmo::cubeNorm;
26 ImVector<Diligent::float3> imguiGizmo::planeVtx;
27 ImVector<Diligent::float3> imguiGizmo::planeNorm;
28 bool imguiGizmo::solidAreBuilded = false;
29 bool imguiGizmo::dragActivate = false;
30
31 using tbT = float;
32
33 //
34 // Settings
35 //
36 // axes/arrow are composed of cone (or pyramid) and cylinder
37 // (or parallelepiped): this solid are builded at first instance
38 // and will have same slices/radius/length for all controls in your
39 // applications but can be resized proportionally with a reductin
40 // factor: solidResizeFactor and axesResizeFactor.
41 // Same thing for the colors of sphere tessellation, while color
42 // of axes and cube are fixed
43 //
44 // Solid/axes settings can be set one only one time before your widget
45 // while solidResizeFactor and axesResizeFactor settings must
46 // be call before and always of your widget, every redraw... and
47 // restored after use... like push/pop
48 // ... I avoided creating a push/pop mechanism
49 ////////////////////////////////////////////////////////////////////////////
50
51 // arrow/axes components
52 ///////////////////////////////////////
53 int imguiGizmo::coneSlices = 4;
54 float imguiGizmo::coneRadius = 0.07f;
55 float imguiGizmo::coneLength = 0.37f;
56
57
58 int imguiGizmo::cylSlices = 7;
59 float imguiGizmo::cylRadius = 0.02f; // sizeCylLength = defined in base to control size
60
61
62 // Sphere components
63 ///////////////////////////////////////
64 float imguiGizmo::sphereRadius = .27f;
65 int imguiGizmo::sphereTessFactor = imguiGizmo::sphereTess4;
66
67 // Cube components
68 ///////////////////////////////////////
69 float imguiGizmo::cubeSize = .05f;
70
71 // Plane components
72 ///////////////////////////////////////
73 float imguiGizmo::planeSize = .33f;
74 float imguiGizmo::planeThickness = .015f;
75
76 // Axes resize
77 ///////////////////////////////////////
78 Diligent::float3 imguiGizmo::axesResizeFactor(.95f, 1.f , 1.f);
79 Diligent::float3 imguiGizmo::savedAxesResizeFactor = imguiGizmo::axesResizeFactor;
80
81 // Solid resize
82 ///////////////////////////////////////
83 float imguiGizmo::solidResizeFactor = 1.0;
84 float imguiGizmo::savedSolidResizeFactor = imguiGizmo::solidResizeFactor;
85
86 // Direction arrow color
87 ///////////////////////////////////////
88 ImVec4 imguiGizmo::directionColor(1.0f, 1.0f, 0.0, 1.0f);
89 ImVec4 imguiGizmo::savedDirectionColor = imguiGizmo::directionColor;
90
91 // Plane color
92 ///////////////////////////////////////
93 ImVec4 imguiGizmo::planeColor(0.0f, 0.5f, 1.0, STARTING_ALPHA_PLANE);
94 ImVec4 imguiGizmo::savedPlaneColor = imguiGizmo::planeColor;
95
96 // Sphere Colors
97 ///////////////////////////////////////
98 ImU32 imguiGizmo::sphereColors[2] = { 0xff401010, 0xffc0a0a0 }; // Tessellation colors
99 ImU32 imguiGizmo::savedSphereColors[2] = { 0xff401010, 0xffc0a0a0 };
100 //ImU32 spherecolorA=0xff005cc0, spherecolorB=0xffc05c00;
101
102 //
103 // for all gizmo3D
104 //
105 // input:
106 // size: dimension of the control
107 // mode: visualization mode: axis starting from origin, fullAxis
108 // (whit or w/o solid at 0,0,0) or only one arrow for direction
109 //
110 // other settings (to call before and always of your control):
111 // dimesion solid, axes, and arrow, slice of poligons end over: view
112 // section "settings of class declaration", these these values are valid for
113 // ALL controls in your application, because the lists of triangles/quads,
114 // which compose the solids, are builded one time with the first
115 // instance ... and NOT every redraw
116 //
117 // solidResizeFactor - axesResizeFactor
118 // can resize axes or solid, respectively (helper func)
119 ////////////////////////////////////////////////////////////////////////////
120
121 namespace ImGui
122 {
123 //
124 // Quaternion control
125 //
126 // input/output: Diligent::Quaternion (quaternion) for full control
127 ////////////////////////////////////////////////////////////////////////////
128 bool gizmo3D(const char* label, Diligent::Quaternion& quat, float size, const int mode)
129 {
130 imguiGizmo g;
131 g.modeSettings(mode & ~g.modeDual);
132
133 g.qtV = quat;
134
135 bool ret = g.drawFunc(label, size);
136 if(ret) quat = g.qtV;
137
138 return ret;
139 }
140
141
142 //
143 // Angle/Axes control
144 //
145 // input/output:
146 // Diligent::float4 - X Y Z vector/axes components - W angle of rotation
147 ////////////////////////////////////////////////////////////////////////////
148 bool gizmo3D(const char* label, Diligent::float4& axis_angle, float size, const int mode)
149 {
150 imguiGizmo g;
151 g.modeSettings(mode & ~g.modeDual);
152
153 return g.getTransforms(g.qtV, label, axis_angle, size);
154 }
155
156 //
157 // Direction control :
158 // only in directional mode! ... for obvious reasons ;-)
159 //
160 // input/output: Diligent::float3 - X Y Z vector/axes components
161 ////////////////////////////////////////////////////////////////////////////
162
163 bool gizmo3D(const char* label, Diligent::float3& dir, float size, const int mode)
164 {
165 imguiGizmo g;
166 g.modeSettings(mode & (imguiGizmo::modeDirection | imguiGizmo::modeDirPlane) ? mode : imguiGizmo::modeDirection);
167
168 return g.getTransforms(g.qtV, label, dir, size);
169
170 }
171
172 //
173 // 2 Manipulators -> 2 Quaternions
174 //
175 // input/output: glm::axes (quaternion) for full control - LeftClick
176 // glm::spot (quaternion) for full control - RightClick
177 //
178 // both pressed buttons... rotate together
179 // ctrl-Shift-Alt mods, for X-Y-Z rotations (respectivally)
180 // are abilitated on both ... also together!
181 ////////////////////////////////////////////////////////////////////////////
182 bool gizmo3D(const char* label, Diligent::Quaternion& axes, Diligent::Quaternion& spot, float size, const int mode)
183 {
184 imguiGizmo g;
185 g.setDualMode(mode);
186
187 g.qtV = axes; g.qtV2 = spot;
188
189 bool ret = g.drawFunc(label, size);
190 if(ret) { axes = g.qtV; spot = g.qtV2; }
191
192 return ret;
193 }
194
195 //
196 // 2 Manipulators -> Quaternions and Vec3
197 //
198 // input/output: glm::axes (quaternion) for full control - LeftClick
199 // glm::spot (vec3) for full control - RightClick
200 //
201 // read above...
202 ////////////////////////////////////////////////////////////////////////////
203 bool gizmo3D(const char* label, Diligent::Quaternion& axes, Diligent::float3& spotDir, float size, const int mode)
204 {
205 imguiGizmo g;
206 g.setDualMode(mode);
207
208 g.qtV = axes;
209
210 bool ret = g.getTransforms(g.qtV2, label, spotDir, size);
211 if(ret) axes = g.qtV;
212 return ret;
213 }
214
215 //
216 // 2 Manipulators -> Quaternions and Vec4
217 //
218 // input/output: glm::axes (quaternion) for full control - LeftClick
219 // glm::spot (vec4 -> xyz axes, q angle) - RightClick
220 //
221 // read above...
222 ////////////////////////////////////////////////////////////////////////////
223 bool gizmo3D(const char* label, Diligent::Quaternion& axes, Diligent::float4& axesAngle, float size, const int mode)
224 {
225 imguiGizmo g;
226 g.setDualMode(mode);
227
228 g.qtV = axes;
229
230 bool ret = g.getTransforms(g.qtV2, label, axesAngle, size);
231 if(ret) axes = g.qtV;
232 return ret;
233
234 }
235
236 } // namespace ImGui
237
238 static inline int clamp(int v, int mn, int mx)
239 {
240 return (v < mn) ? mn : (v > mx) ? mx : v;
241 }
242
243 //
244 // LightEffect
245 // faster but minus cute/precise.. ok for sphere
246 ////////////////////////////////////////////////////////////////////////////
247 inline ImU32 addLightEffect(ImU32 color, float light)
248 {
249 float l = ((light < 0.6f) ? 0.6f : light) * 0.8f;
250 float lc = light * 80.f; // ambient component
251 return clamp(ImU32((( color & 0xff)*l + lc)),0,255) |
252 (clamp(ImU32((((color>>8) & 0xff)*l + lc)),0,255) << 8) |
253 (clamp(ImU32((((color>>16) & 0xff)*l + lc)),0,255) << 16) |
254 (ImU32(ImGui::GetStyle().Alpha * (color>>24)) << 24);
255 }
256 //
257 // LightEffect
258 // with distance attenuatin
259 ////////////////////////////////////////////////////////////////////////////
260 inline ImU32 addLightEffect(const Diligent::float4 &color, float light, float atten)
261 {
262 Diligent::float3 l = Diligent::float3(1, 1, 1) * ((light < .5f) ? .5f : light);
263 Diligent::float3 a = Diligent::float3(1, 1, 1) * ((atten > .25f) ? .25f : atten);
264 Diligent::float3 c(((Diligent::float3(color) + l*.5f) * l) *.75f + a*Diligent::float3(color)*.45f +a*.25f);
265
266 const float alpha = color.a * ImGui::GetStyle().Alpha; //ImGui::GetCo(ImGuiCol_FrameBg).w;
267 return ImGui::ColorConvertFloat4ToU32(ImVec4(c.x, c.y, c.z, alpha));
268 }
269
270
271 inline ImU32 addLightEffect(ImU32 color, float light, float atten)
272 {
273 Diligent::float4 c(float(color & 0xff)/255.f,float((color>>8) & 0xff)/255.f,float((color>>16) & 0xff)/255.f, 1.0);
274 return addLightEffect(c, light, atten);
275 }
276
277 // inline helper drawing functions
278 ////////////////////////////////////////////////////////////////////////////
279 typedef Diligent::float3 & (*ptrFunc)(Diligent::float3 &);
280
281
282 inline Diligent::float3 &adjustPlane(Diligent::float3 &coord)
283 {
284 coord.x = (coord.x > 0) ? ( 2.5f * coord.x - 1.6f) : coord.x ;
285 coord.x = (coord.x) * 0.5f + 0.5f + (coord.x > 0.f ? -imguiGizmo::planeThickness : imguiGizmo::planeThickness) * imguiGizmo::solidResizeFactor;
286 coord *= Diligent::float3(1.f, 2.f, 2.f);
287 return coord;
288 }
289
290 inline Diligent::float3 &adjustDir(Diligent::float3 &coord)
291 {
292 coord.x = (coord.x > 0) ? ( 2.5f * coord.x - 1.6f) : coord.x + 0.1f;
293 coord *= Diligent::float3(1.f, 3.f, 3.f);
294 return coord;
295 }
296
297 inline Diligent::float3 &adjustSpotCyl(Diligent::float3 &coord)
298 {
299 const float halfCylMinusCone = 1.f - imguiGizmo::coneLength;
300 coord.x = (coord.x * 0.075f - 2.f + (halfCylMinusCone - halfCylMinusCone * 0.075f)); //cyl begin where cone end
301 return coord;
302
303 }
304 inline Diligent::float3 &adjustSpotCone(Diligent::float3 &coord)
305 {
306 coord.x-= 2.00f;
307 return coord;
308 }
309
310 inline Diligent::float3 fastRotate (int axis, Diligent::float3 &v)
311 {
312 return ((axis == imguiGizmo::axisIsY) ? Diligent::float3(-v.y, v.x, v.z) : // rotation Z 90'
313 ((axis == imguiGizmo::axisIsZ) ? Diligent::float3(-v.z, v.y, v.x) : // rotation Y 90'
314 v));
315 }
316 ////////////////////////////////////////////////////////////////////////////
317 //
318 // Draw imguiGizmo
319 //
320 ////////////////////////////////////////////////////////////////////////////
321 bool imguiGizmo::drawFunc(const char* label, float size)
322 {
323
324 ImGuiIO& io = ImGui::GetIO();
325 ImGuiStyle& style = ImGui::GetStyle();
326 ImDrawList* draw_list = ImGui::GetWindowDrawList();
327
328 const float arrowStartingPoint = (axesOriginType & imguiGizmo::sphereAtOrigin) ? sphereRadius * solidResizeFactor:
329 ((axesOriginType & imguiGizmo::cubeAtOrigin ) ? cubeSize * solidResizeFactor:
330 cylRadius * .5f);
331 // if modeDual... leave space for draw light arrow
332 Diligent::float3 resizeAxes( ((drawMode&modeDual) && (axesResizeFactor.x > 0.75f)) ? Diligent::float3(0.75f, axesResizeFactor.y, axesResizeFactor.z) : axesResizeFactor);
333
334 // build solids... once!
335 ///////////////////////////////////////
336 if (!solidAreBuilded) {
337 const float arrowBgn = -1.0f, arrowEnd = 1.0f;
338
339 buildCone (arrowEnd - coneLength, arrowEnd, coneRadius, coneSlices);
340 buildCylinder(arrowBgn, arrowEnd - coneLength, cylRadius , cylSlices );
341 buildSphere(sphereRadius, sphereTessFactor);
342 buildCube(cubeSize);
343 buildPlane(planeSize);
344 solidAreBuilded = true;
345 }
346
347 ImGui::PushID(label);
348 ImGui::BeginGroup();
349
350 bool value_changed = false;
351
352 if(label[0]!='#' && label[1]!='#') ImGui::Text("%s", label);
353
354 ImVec2 controlPos = ImGui::GetCursorScreenPos();
355
356 const float innerSquareSize = size; //std::min(ImGui::CalcItemWidth(), size);
357 const float halfSquareSize = innerSquareSize * 0.5f;
358 const ImVec2 innerSize(innerSquareSize,innerSquareSize);
359
360 bool highlighted = false;
361 ImGui::InvisibleButton("imguiGizmo", innerSize);
362
363 // getTrackball
364 // in : q -> quaternion to which applay rotations
365 // out: q -> quaternion with rotations
366 ////////////////////////////////////////////////////////////////////////////
367 auto getTrackball = [&] (Diligent::Quaternion &q) {
368 auto width = size;
369 auto height = size;
370 auto minVal = width < height ? width * 0.5f : height * 0.5f;
371 auto offset = Diligent::float3(0.5f * width, 0.5f * height, 0.0);
372
373 ImVec2 mouse = ImGui::GetMousePos() - controlPos;
374
375 Diligent::float2 delta = {io.MouseDelta.x, -io.MouseDelta.y};
376 Diligent::float2 pos = {mouse.x, mouse.y};
377 Diligent::float3 rotationVector(1, 1, 1);
378 if(io.KeyShift) { rotationVector = Diligent::float3(1, 0, 0); }
379 else if(io.KeyCtrl) { rotationVector = Diligent::float3(0, 1, 0); }
380 else if(io.KeyAlt || io.KeySuper) { rotationVector = Diligent::float3(0, 0, 1); }
381
382
383 Diligent::Quaternion qtStep = {0, 0, 0, 1};
384 if(!delta.x && !delta.y)
385 {
386 qtStep = Diligent::Quaternion(0, 0, 0, 1); //no rotation
387 return;
388 }
389
390 Diligent::float3 a(pos.x - delta.x, height - (pos.y+delta.y), 0);
391 Diligent::float3 b(pos.x, height - pos.y, 0);
392
393 auto vecFromPos = [&] (Diligent::float3& v)
394 {
395 v -= offset;
396 v /= minVal;
397 const auto len = Diligent::length(v);
398 v.z = len > 0 ? std::pow(2.f, -0.5f * len) : 1;
399 v = normalize(v);
400 };
401
402 vecFromPos(a);
403 vecFromPos(b);
404
405 auto axis = cross(a, b);
406 axis = normalize(axis);
407
408 auto AdotB = dot(a, b);
409 auto angle = std::acos( AdotB > 1 ? 1 : AdotB < -1 ? -1 : AdotB); // clamp need!!! corss float is approximate to FLT_EPSILON
410
411 const auto tbScale = 1; //base scale sensibility
412 const auto fpsRatio = 1; //auto adjust by FPS (call idle with current FPS)
413
414 qtStep = normalize(Diligent::Quaternion::RotationFromAxisAngle(axis * rotationVector, angle * tbScale * fpsRatio));
415 q = qtStep*q;
416
417 value_changed = true;
418 };
419
420 //LeftClick
421 if (ImGui::IsItemActive()) {
422 highlighted = true;
423 if(ImGui::IsMouseDragging(0)) getTrackball(qtV);
424 if(drawMode==modeDual && ImGui::IsMouseDragging(1)) getTrackball(qtV2); // if dual mode... move together
425 if(drawMode==modeDual && ImGui::IsMouseDragging(2)) { getTrackball(qtV); getTrackball(qtV2); } // middle if dual mode... move together
426
427 ImColor col(style.Colors[ImGuiCol_FrameBgActive]);
428 col.Value.w*=ImGui::GetStyle().Alpha;
429 draw_list->AddRectFilled(controlPos, controlPos + innerSize, col, style.FrameRounding);
430 } else { // eventual right click... only dualmode
431 highlighted = ImGui::IsItemHovered();
432 if(highlighted && (drawMode==modeDual) && ImGui::IsMouseDragging(1)) getTrackball(qtV2);
433
434 ImColor col(highlighted ? style.Colors[ImGuiCol_FrameBgHovered]: style.Colors[ImGuiCol_FrameBg]);
435 col.Value.w*=ImGui::GetStyle().Alpha;
436 draw_list->AddRectFilled(controlPos, controlPos + innerSize, col, style.FrameRounding);
437 }
438
439 const ImVec2 wpUV = ImGui::GetFontTexUvWhitePixel(); //culling versus
440 ImVec2 uv[4]; ImU32 col[4]; //buffers to storetransformed vtx & col for PrimVtx & PrimQuadUV
441
442 Diligent::Quaternion quat(Diligent::normalize(qtV));
443
444 ////////////////////////////////////////////////////////////////////////////
445 // Just a "few" lambdas...
446
447 //////////////////////////////////////////////////////////////////
448 auto normalizeToControlSize = [&] (float x, float y) {
449 return controlPos + ImVec2(x,-y) * halfSquareSize + ImVec2(halfSquareSize,halfSquareSize); //drawing from 0,0 .. no borders
450 };
451
452 //////////////////////////////////////////////////////////////////
453 auto addTriangle = [&] ()
454 { // test cull dir
455 if(Diligent::cross(Diligent::float3(uv[1].x - uv[0].x, uv[1].y - uv[0].y, 0),
456 Diligent::float3(uv[2].x - uv[0].x, uv[2].y - uv[0].y, 0)).z > 0.f)
457 { uv[1] = uv[2] = uv[0]; }
458
459 for(int i=0; i<3; i++) draw_list->PrimVtx(uv[i], wpUV, col[i]);
460 };
461
462 //////////////////////////////////////////////////////////////////
463 auto addQuad = [&] (ImU32 colLight)
464 { // test cull dir
465 if(Diligent::cross(Diligent::float3(uv[1].x-uv[0].x, uv[1].y-uv[0].y, 0),
466 Diligent::float3(uv[3].x-uv[0].x, uv[3].y-uv[0].y, 0)).z > 0.f)
467 { uv[3] = uv[1] = uv[2] = uv[0]; }
468
469 draw_list->PrimQuadUV(uv[0],uv[1],uv[2],uv[3], wpUV, wpUV, wpUV, wpUV, colLight);
470 };
471
472 //////////////////////////////////////////////////////////////////
473 auto drawSphere = [&] ()
474 {
475 draw_list->PrimReserve(sphereVtx.size(), sphereVtx.size()); // num vert/indices
476 auto itTess = sphereTess.begin();
477 for(auto itVtx = sphereVtx.begin(); itVtx != sphereVtx.end(); ) {
478 for(int h=0; h<3; h++, itTess++) {
479 Diligent::float3 coord = quat.RotateVector(*itVtx++ * solidResizeFactor); //Rotate
480
481 uv[h] = normalizeToControlSize(coord.x,coord.y);
482 const float drawSize = sphereRadius * solidResizeFactor;
483 col[h] = addLightEffect(sphereColors[*itTess], (-drawSize*.5f + (coord.z*coord.z) / (drawSize*drawSize)));
484 //col[h] = colorLightedY(sphereCol[i++], (-sizeSphereRadius.5f + (coord.z*coord.z) / (sizeSphereRadius*sizeSphereRadius)), coord.z);
485 }
486 addTriangle();
487 }
488 };
489
490 //////////////////////////////////////////////////////////////////
491 auto drawCube = [&] ()
492 {
493 draw_list->PrimReserve(cubeNorm.size()*6, cubeNorm.size()*4); // num vert/indices
494 for(auto itNorm = cubeNorm.begin(), itVtx = cubeVtx.begin() ; itNorm != cubeNorm.end();) {
495 Diligent::float3 coord;
496 Diligent::float3 norm = quat.RotateVector(*itNorm);
497 for (int i = 0; i<4; ) {
498 coord = quat.RotateVector(*itVtx++ * solidResizeFactor);
499 uv[i++] = normalizeToControlSize(coord.x,coord.y);
500 }
501 addQuad(addLightEffect(Diligent::float4(abs(*itNorm++), 1.0f), norm.z, coord.z));
502 }
503 };
504
505 //////////////////////////////////////////////////////////////////
506 auto drawPlane = [&] ()
507 {
508 draw_list->PrimReserve(planeNorm.size()*6, planeNorm.size()*4); // num vert/indices
509 for(auto itNorm = planeNorm.begin(), itVtx = planeVtx.begin() ; itNorm != planeNorm.end();) {
510 Diligent::float3 coord;
511 Diligent::float3 norm = quat.RotateVector(*itNorm);
512 for (int i = 0; i<4; ) {
513 coord = quat.RotateVector(*itVtx++ * solidResizeFactor);
514 uv[i++] = normalizeToControlSize(coord.x,coord.y);
515 }
516 itNorm++;
517 addQuad(addLightEffect(Diligent::float4(planeColor.x, planeColor.y, planeColor.z, planeColor.w), norm.z, coord.z));
518 }
519 };
520
521 //////////////////////////////////////////////////////////////////
522 auto drawAxes = [&] (int side)
523 {
524 for(int n = 0; n < 4; n++) { //Arrow: 2 Cone -> (Surface + cap) + 2 Cyl -> (Surface + cap)
525 for(int arrowAxis = 0; arrowAxis < 3; arrowAxis++) { // draw 3 axes
526 Diligent::float3 arrowCoord(0, 0, 0); arrowCoord[arrowAxis] = 1.0f; // rotate on 3 axis (arrow -> X, Y, Z ) in base to current arrowAxis
527 const float arrowCoordZ = Diligent::float3(quat.RotateVector(arrowCoord)).z; //.Rotate
528
529 const int i = (arrowCoordZ > 0) ? 3 - n : n; //painter algorithm: before farthest
530
531 bool skipCone =true;
532
533 if ((side == backSide && arrowCoordZ > 0) || (side == frontSide && arrowCoordZ <= 0)) {
534 if (!showFullAxes && (i == CYL_CAP)) continue; // skip if cylCap is hidden
535 if (i <= CONE_CAP) continue; // do not draw cone
536 else skipCone = false;
537 }
538
539 auto *ptrVtx = arrowVtx+i;
540 draw_list->PrimReserve(ptrVtx->size(), ptrVtx->size()); // // reserve vtx
541
542 for (auto itVtx = ptrVtx->begin(), itNorm = (arrowNorm+i)->begin(); itVtx != ptrVtx->end(); ) { //for all Vtx
543 #if !defined(imguiGizmo_INTERPOLATE_NORMALS)
544 Diligent::float3 norm( quat * fastRotate(arrowAxis, *itNorm++));
545 #endif
546 for(int h=0; h<3; h++) {
547 Diligent::float3 coord(*itVtx++ * resizeAxes); // reduction
548
549 // reposition starting point...
550 if (!skipCone && coord.x > 0) coord.x = -arrowStartingPoint;
551 if ((skipCone && coord.x <= 0) ||
552 (!showFullAxes && (coord.x < arrowStartingPoint)) ) coord.x = arrowStartingPoint;
553 //transform
554 coord = quat.RotateVector(fastRotate(arrowAxis, coord));
555 uv[h] = normalizeToControlSize(coord.x,coord.y);
556 #ifdef imguiGizmo_INTERPOLATE_NORMALS
557 Diligent::float3 norm( quat.RotateVector(fastRotate(arrowAxis, *itNorm++)));
558 #endif
559 //col[h] = addLightEffect(ImU32(0xFF) << arrowAxis*8, float(0xa0)*norm.z+.5f);
560 col[h] = addLightEffect(Diligent::float4(float(arrowAxis==axisIsX),float(arrowAxis==axisIsY),float(arrowAxis==axisIsZ), 1.0), norm.z, coord.z);
561 }
562 addTriangle();
563 }
564 }
565 }
566 };
567
568 //////////////////////////////////////////////////////////////////
569 auto drawComponent = [&] (const int idx, const Diligent::Quaternion& q, ptrFunc func)
570 {
571 auto *ptrVtx = arrowVtx+idx;
572 draw_list->PrimReserve(ptrVtx->size(), ptrVtx->size()); // reserve vtx
573 for (auto itVtx = ptrVtx->begin(), itNorm = (arrowNorm+idx)->begin(); itVtx != ptrVtx->end(); ) {
574 #if !defined(imguiGizmo_INTERPOLATE_NORMALS)
575 Diligent::float3 norm = (quat * *itNorm++);
576 #endif
577 for(int h=0; h<3; h++) {
578 Diligent::float3 coord = *itVtx++;
579 #ifdef imguiGizmo_INTERPOLATE_NORMALS
580 Diligent::float3 norm = (q.RotateVector(*itNorm++));
581 #endif
582 coord = q.RotateVector(func(coord) * resizeAxes); // remodelling Directional Arrow (func) and transforms;
583
584 uv[h] = normalizeToControlSize(coord.x,coord.y);
585 //col[h] = addLightEffect(color, float(0xa0)*norm.z+.5f);
586 col[h] = addLightEffect(Diligent::float4(directionColor.x, directionColor.y, directionColor.z, 1.0f), norm.z, coord.z > 0 ? coord.z : coord.z * .5f);
587 }
588 addTriangle();
589 }
590
591 };
592
593 //////////////////////////////////////////////////////////////////
594 auto dirArrow = [&] (const Diligent::Quaternion &q, int mode)
595 {
596 Diligent::float3 arrowCoord(quat.RotateVector(Diligent::float3(1.0f, 0.0f, 0.0f)));
597
598 ptrFunc func = (mode == modeDirPlane) ? adjustPlane : adjustDir;
599
600 if(arrowCoord.z <= 0) { for(int i = 0; i < 4; i++) drawComponent(i, q, func); if(mode == modeDirPlane) drawPlane(); }
601 else { if(mode == modeDirPlane) drawPlane(); for(int i = 3; i >= 0; i--) drawComponent(i, q, func); }
602
603 };
604
605 //////////////////////////////////////////////////////////////////
606 auto spotArrow = [&] (const Diligent::Quaternion &q, const float arrowCoordZ)
607 {
608 if(arrowCoordZ > 0) {
609 drawComponent(CONE_SURF, q, adjustSpotCone); drawComponent(CONE_CAP , q, adjustSpotCone);
610 drawComponent(CYL_SURF , q, adjustSpotCyl ); drawComponent(CYL_CAP , q, adjustSpotCyl );
611 } else {
612 drawComponent(CYL_CAP , q, adjustSpotCyl ); drawComponent(CYL_SURF , q, adjustSpotCyl );
613 drawComponent(CONE_CAP , q, adjustSpotCone); drawComponent(CONE_SURF, q, adjustSpotCone);
614 }
615
616 };
617
618 //////////////////////////////////////////////////////////////////
619 auto draw3DSystem = [&] ()
620 {
621 drawAxes(backSide);
622 if (axesOriginType & sphereAtOrigin) drawSphere();
623 else if(axesOriginType & cubeAtOrigin) drawCube();
624 drawAxes(frontSide);
625 };
626
627 // ... and now.. draw the widget!!!
628 ///////////////////////////////////////
629 if(drawMode & (modeDirection | modeDirPlane)) dirArrow(quat, drawMode);
630 else { // draw arrows & sphere
631 if(drawMode == modeDual) {
632 Diligent::float3 spot(qtV2.RotateVector(Diligent::float3(-1, 0, 0))); // versus opposite
633 if(spot.z>0) { draw3DSystem(); spotArrow(Diligent::normalize(qtV2),spot.z); }
634 else { spotArrow(Diligent::normalize(qtV2),spot.z); draw3DSystem(); }
635 } else draw3DSystem();
636 }
637
638 ImGui::EndGroup();
639 ImGui::PopID();
640
641 return value_changed;
642 }
643
644 //
645 // Polygon
646 //
647 ////////////////////////////////////////////////////////////////////////////
648 void imguiGizmo::buildPolygon(const Diligent::float3 &size, ImVector<Diligent::float3> &vtx, ImVector<Diligent::float3> &norm)
649 {
650
651 vtx .clear();
652 norm.clear();
653
654 #define V(a,b,c) vtx.push_back(Diligent::float3(a size.x, b size.y, c size.z))
655 #define N(x,y,z) norm.push_back(Diligent::float3(x, y, z))
656
657 N( 1.0, 0.0, 0.0); V(+,-,+); V(+,-,-); V(+,+,-); V(+,+,+);
658 N( 0.0, 1.0, 0.0); V(+,+,+); V(+,+,-); V(-,+,-); V(-,+,+);
659 N( 0.0, 0.0, 1.0); V(+,+,+); V(-,+,+); V(-,-,+); V(+,-,+);
660 N(-1.0, 0.0, 0.0); V(-,-,+); V(-,+,+); V(-,+,-); V(-,-,-);
661 N( 0.0,-1.0, 0.0); V(-,-,+); V(-,-,-); V(+,-,-); V(+,-,+);
662 N( 0.0, 0.0,-1.0); V(-,-,-); V(-,+,-); V(+,+,-); V(+,-,-);
663
664 #undef V
665 #undef N
666 }
667 //
668 // Sphere
669 //
670 ////////////////////////////////////////////////////////////////////////////
671 void imguiGizmo::buildSphere(const float radius, const int tessFactor)
672 {
673 const int tess = tessFactor;
674 const int div = tessFactor; //tessellation colors: meridians/div x paralles/div
675 const int meridians = 32; //64/2;
676 const int parallels = meridians/2;
677
678 sphereVtx .clear();
679 sphereTess.clear();
680
681 # define V(x,y,z) sphereVtx.push_back(Diligent::float3(x, y, z))
682 # define T(t) sphereTess.push_back(t)
683
684 const float incAngle = 2.f * Diligent::PI_F / (float)( meridians );
685 float angle = incAngle;
686
687 // Adjust z and radius as stacks are drawn.
688 float z0, z1 = cosf(angle)*radius;
689 float r0, r1 = sinf(angle)*radius;
690 float x1 = -1.0f;
691 float y1 = 0.0f;
692
693 // The first parallel is covered with triangles
694
695 for (int j=0; j<meridians; j++, angle+=incAngle)
696 {
697 const float x0 = x1; x1 = cosf(Diligent::PI_F - angle);
698 const float y0 = y1; y1 = sinf(Diligent::PI_F - angle);
699
700 const int tType = ((j>>div)&1);
701
702 V(0.0f, 0.0f, radius); T(tType);
703 V(x0*r1,-y0*r1, z1); T(tType);
704 V(x1*r1,-y1*r1, z1); T(tType);
705 }
706
707 // Cover each stack with a quad divided in 2 triangles, except the top and bottom stacks
708 angle = incAngle+incAngle;
709 x1 = 1.f; y1 = 0.f;
710
711 for(int i=1; i<parallels-1; i++, angle+=incAngle) {
712 //int div =8;
713 z0 = z1; z1 = cosf(angle)*radius;
714 r0 = r1; r1 = sinf(angle)*radius;
715 float angleJ = incAngle;
716
717 for(int j=0; j<meridians; j++, angleJ+=incAngle) {
718
719 const float x0 = x1; x1 = cosf(angleJ);
720 const float y0 = y1; y1 = sinf(angleJ);
721
722 const int tType = ((i>>div)&1) ? ((j>>div)&1) : !((j>>div)&1);
723
724 V(x0*r1, -y0*r1, z1); T(tType);
725 V(x0*r0, -y0*r0, z0); T(tType);
726 V(x1*r0, -y1*r0, z0); T(tType);
727 V(x0*r1, -y0*r1, z1); T(tType);
728 V(x1*r0, -y1*r0, z0); T(tType);
729 V(x1*r1, -y1*r1, z1); T(tType);
730 }
731 }
732
733 // The last parallel is covered with triangls
734
735 z0 = z1;
736 r0 = r1;
737 x1 = -1.0f; y1 = 0.f;
738
739 angle = incAngle;
740 for (int j=0; j<meridians; j++,angle+=incAngle)
741 {
742 const float x0 = x1; x1 = cosf(angle + Diligent::PI_F);
743 const float y0 = y1; y1 = sinf(angle + Diligent::PI_F);
744
745 const int tType = ((parallels-1)>>div)&1 ? ((j>>div)&1) : !((j>>div)&1);
746 //color = 0xff0000ff;
747
748 V( 0.0f, 0.0f,-radius); T(tType);
749 V(x0*r0, -y0*r0, z0); T(tType);
750 V(x1*r0, -y1*r0, z0); T(tType);
751 }
752 # undef V
753 # undef C
754 }
755 //
756 // Cone
757 //
758 ////////////////////////////////////////////////////////////////////////////
759 void imguiGizmo::buildCone(const float x0, const float x1, const float radius, const int slices)
760 {
761 const float height = x1-x0 ;
762 const float zStep = height;
763 const float rStep = radius/(float)slices;
764
765 // Scaling factors for vertex normals
766
767 const float sq = sqrtf( height * height + radius * radius );
768 const float cosn = height / sq;
769 const float sinn = radius / sq;
770
771
772 const float incAngle = 2 * Diligent::PI_F / (float)( slices );
773 float angle = incAngle;
774
775 float yt1 = sinn, y1 = radius;// cos(0) * sinn ... cos(0) * radius
776 float zt1 = 0.0f, z1 = 0.0f; // sin(0) * sinn ... sin(0) * radius
777
778 const float xt0 = x0 * cosn, xt1 = x1 * cosn;
779
780 arrowVtx[CONE_CAP ].clear(); arrowNorm[CONE_CAP ].clear();
781 arrowVtx[CONE_SURF].clear(); arrowNorm[CONE_SURF].clear();
782
783 # define V(i,x,y,z) arrowVtx [i].push_back(Diligent::float3(x, y, z))
784 # define N(i,x,y,z) arrowNorm[i].push_back(Diligent::float3(x, y, z))
785
786 for (int j=0; j<slices; j++, angle+=incAngle)
787 {
788 const float yt0 = yt1; yt1 = cosf(angle);
789 const float y0 = y1; y1 = yt1*radius; yt1*=sinn;
790 const float zt0 = zt1; zt1 = sinf(angle);
791 const float z0 = z1; z1 = zt1*radius; zt1*=sinn;
792
793 // Cover the circular base with a triangle fan...
794 V(CONE_CAP, x0, 0.f, 0.f);
795 V(CONE_CAP, x0, y0, -z0);
796 V(CONE_CAP, x0, y1, -z1);
797
798 N(CONE_CAP,-1.f, 0.f, 0.f);
799 # ifdef imguiGizmo_INTERPOLATE_NORMALS
800 N(CONE_CAP,-1.f, 0.f, 0.f);
801 N(CONE_CAP,-1.f, 0.f, 0.f);
802 #endif
803 V(CONE_SURF, x1, 0.f, 0.f);
804 V(CONE_SURF, x0, y0, z0);
805 V(CONE_SURF, x0, y1, z1);
806 # ifdef imguiGizmo_INTERPOLATE_NORMALS
807 N(CONE_SURF,xt1, 0.f, 0.f);
808 N(CONE_SURF,xt0, yt0, zt0);
809 N(CONE_SURF,xt0, yt1, zt1);
810 #else
811 N(CONE_SURF, xt0, yt0, zt0);
812 #endif
813 }
814 #undef V
815 #undef N
816 }
817 //
818 // Cylinder
819 //
820 ////////////////////////////////////////////////////////////////////////////
821 void imguiGizmo::buildCylinder(const float x0, const float x1, const float radius, const int slices)
822 {
823
824 float y1 = 1.0f, yr1 = radius;
825 float z1 = 0.0f, zr1 = 0.0f; // * radius
826
827
828 const float incAngle = 2 * Diligent::PI_F / (float)( slices );
829 float angle = incAngle;
830
831 arrowVtx[CYL_CAP ].clear(); arrowNorm[CYL_CAP ].clear();
832 arrowVtx[CYL_SURF].clear(); arrowNorm[CYL_SURF].clear();
833
834 # define V(i,x,y,z) arrowVtx [i].push_back(Diligent::float3(x, y, z))
835 # define N(i,x,y,z) arrowNorm[i].push_back(Diligent::float3(x, y, z))
836
837 for (int j=0; j<slices; j++, angle+=incAngle) {
838 const float y0 = y1; y1 = cosf(angle);
839 const float z0 = z1; z1 = sinf(angle);
840 const float yr0 = yr1; yr1 = y1 * radius;
841 const float zr0 = zr1; zr1 = z1 * radius;
842
843 // Cover the base
844 V(CYL_CAP, x0, 0.f, 0.f);
845 V(CYL_CAP, x0, yr0,-zr0);
846 V(CYL_CAP, x0, yr1,-zr1);
847
848 N(CYL_CAP, -1.f, 0.f, 0.f);
849 # ifdef imguiGizmo_INTERPOLATE_NORMALS
850 N(CYL_CAP, -1.f, 0.f, 0.f);
851 N(CYL_CAP, -1.f, 0.f, 0.f);
852 #endif
853 // Cover surface
854 N(CYL_SURF, 0.f, y0, z0);
855 N(CYL_SURF, 0.f, y0, z0);
856 # ifdef imguiGizmo_INTERPOLATE_NORMALS
857 N(CYL_SURF, 0.f, y1, z1);
858 N(CYL_SURF, 0.f, y0, z0);
859 N(CYL_SURF, 0.f, y1, z1);
860 N(CYL_SURF, 0.f, y1, z1);
861 #endif
862
863 V(CYL_SURF, x1, yr0, zr0);
864 V(CYL_SURF, x0, yr0, zr0);
865 V(CYL_SURF, x0, yr1, zr1);
866 V(CYL_SURF, x1, yr0, zr0);
867 V(CYL_SURF, x0, yr1, zr1);
868 V(CYL_SURF, x1, yr1, zr1);
869
870 #ifdef SHOW_FULL_CYLINDER
871 // Cover the top ..in the arrow this cap is covered from cone/pyramid
872 V(CYL_CAP , x1, 0.f, 0.f);
873 V(CYL_CAP , x1, yr0, zr0);
874 V(CYL_CAP , x1, yr1, zr1);
875 N(CYL_CAP , 1.f, 0.f, 0.f);
876 # ifdef imguiGizmo_INTERPOLATE_NORMALS
877 N(CYL_CAP , 1.f, 0.f, 0.f);
878 N(CYL_CAP , 1.f, 0.f, 0.f);
879 #endif
880 #endif
881 }
882 #undef V
883 #undef N
884 }
0 //------------------------------------------------------------------------------
1 // Copyright (c) 2018-2019 Michele Morrone
2 // All rights reserved.
3 //
4 // https://michelemorrone.eu - https://BrutPitt.com
5 //
6 // twitter: https://twitter.com/BrutPitt - github: https://github.com/BrutPitt
7 //
8 // mailto:brutpitt@gmail.com - mailto:me@michelemorrone.eu
9 //
10 // This software is distributed under the terms of the BSD 2-Clause license
11 //------------------------------------------------------------------------------
12 //
13 // Modified by Egor Yusov, Diligent Graphics LLC
14
15 #pragma once
16 #include <algorithm>
17
18 #include "imgui.h"
19 #define IMGUI_DEFINE_MATH_OPERATORS
20 #include "imgui_internal.h"
21
22 ////////////////////////////////////////////////////////////////////////////
23 ////////////////////////////////////////////////////////////////////////////
24 //
25 // NEED TO BUILD :
26 //
27 // - Using glm (OpenGL Mathematics) include files: need version 0.9.9 or later
28 // and GLM_ENABLE_EXPERIMENTAL compile option to enable "quaternion" class
29 // - Using include virtualGizmo.h (my virtualGizmoClass) to get imput controls
30 // and apply rotations
31 // - use c++11 standard
32 //
33 // Use preprocessor define imguiGizmo_INTERPOLATE_NORMALS, to a phong color effect
34 // for solid components, but there are more vertex memorized and more operations,
35 // even if the visual effect is better... the computational difference is:
36 // one normal for vertex VS one normal for plain figure (triangle or quad)
37 //
38 // comment/uncomment below or add as directive to compiler
39 ////////////////////////////////////////////////////////////////////////////
40 ////////////////////////////////////////////////////////////////////////////
41
42 #define imguiGizmo_INTERPOLATE_NORMALS
43 static constexpr float STARTING_ALPHA_PLANE = .75f;
44
45 ////////////////////////////////////////////////////////////////////////////
46 ////////////////////////////////////////////////////////////////////////////
47 //
48 // imguiGizmo 3D
49 //
50 // Buttons:
51 // Left: drag to free rotate axes
52 // Right: drag to free rotate spot (only dualmode!)
53 // Right & Left: drag to rotate together
54 // for ImGui features, right button drag is active only INSIDE the frame
55 // Modifiers:
56 // Shift: rotation only around X
57 // Ctrl: rotation only around Y
58 // Alt: rotation only around Z
59 ////////////////////////////////////////////////////////////////////////////
60 ////////////////////////////////////////////////////////////////////////////
61
62 // The data structure that holds the orientation among other things
63 struct imguiGizmo
64 {
65 Diligent::Quaternion qtV = {0, 0, 0, 1}; // Quaternion value
66 Diligent::Quaternion qtV2 = {0, 0, 0, 1}; // Quaternion value
67
68 enum
69 { //0b0000'0000, //C++14 notation
70 mode3Axes = 0x01, //0b0000'0001,
71 modeDirection = 0x02, //0b0000'0010,
72 modeDirPlane = 0x04, //0b0000'0010,
73 modeDual = 0x08, //0b0000'1000,
74 modeMask = 0x0f, //0b0000'1111,
75
76
77 cubeAtOrigin = 0x10, //0b0000'0000,
78 sphereAtOrigin = 0x20, //0b0001'0000,
79 noSolidAtOrigin = 0x40, //0b0010'0000,
80 modeFullAxes = 0x80,
81 axesModeMask = 0xf0 //0b1111'0000
82 };
83
84 enum
85 {
86 sphereTess16,
87 sphereTess8,
88 sphereTess4,
89 sphereTess2
90 };
91
92 enum
93 {
94 CONE_SURF,
95 CONE_CAP,
96 CYL_SURF,
97 CYL_CAP
98 };
99
100 //enum { SOLID_SURF, SOLID_CAP }
101 //enum {
102 enum
103 {
104 axisIsX,
105 axisIsY,
106 axisIsZ
107 };
108
109 enum solidSides
110 {
111 backSide,
112 frontSide
113 }; // or viceversa...
114
115 static ImVector<Diligent::float3> sphereVtx;
116 static ImVector<int> sphereTess;
117 static ImVector<Diligent::float3> cubeVtx;
118 static ImVector<Diligent::float3> cubeNorm;
119 static ImVector<Diligent::float3> planeVtx;
120 static ImVector<Diligent::float3> planeNorm;
121 static ImVector<Diligent::float3> arrowVtx[4];
122 static ImVector<Diligent::float3> arrowNorm[4];
123
124 static void buildPlane(const float size, const float thickness = planeThickness)
125 {
126 buildPolygon(Diligent::float3(thickness, size, size), planeVtx, planeNorm);
127 }
128
129 static void buildCube(const float size)
130 {
131 buildPolygon(Diligent::float3(size, size, size), cubeVtx, cubeNorm);
132 }
133
134 static void buildPolygon (const Diligent::float3& size, ImVector<Diligent::float3>& vtx, ImVector<Diligent::float3>& norm);
135 static void buildSphere (const float radius, const int tessFactor);
136 static void buildCone (const float x0, const float x1, const float radius, const int slices);
137 static void buildCylinder(const float x0, const float x1, const float radius, const int slices);
138
139
140 // helper functions
141 ///////////////////////////////////////
142 static void resizeAxesOf(const Diligent::float3& newSize)
143 {
144 savedAxesResizeFactor = axesResizeFactor;
145 axesResizeFactor = newSize;
146 }
147
148 static void restoreAxesSize()
149 {
150 axesResizeFactor = savedAxesResizeFactor;
151 }
152
153 static void resizeSolidOf(float newSize)
154 {
155 savedSolidResizeFactor = solidResizeFactor;
156 solidResizeFactor = newSize;
157 }
158
159 static void restoreSolidSize()
160 {
161 solidResizeFactor = savedSolidResizeFactor;
162 }
163
164 static void setDirectionColor(ImU32 dColor, const ImU32 pColor)
165 {
166 setDirectionColor(ImGui::ColorConvertU32ToFloat4(dColor), ImGui::ColorConvertU32ToFloat4(pColor));
167 }
168
169 static void setDirectionColor(const ImVec4& dColor, const ImVec4& pColor)
170 {
171 savedDirectionColor = directionColor;
172 savedPlaneColor = planeColor;
173 directionColor = dColor;
174 planeColor = pColor;
175 }
176
177 static void setDirectionColor(ImU32 color)
178 {
179 setDirectionColor(ImGui::ColorConvertU32ToFloat4(color));
180 }
181
182 static void setDirectionColor(const ImVec4& color)
183 {
184 setDirectionColor(color, ImVec4(color.x, color.y, color.z, STARTING_ALPHA_PLANE));
185 }
186
187 static void restoreDirectionColor()
188 {
189 directionColor = savedDirectionColor;
190 planeColor = savedPlaneColor;
191 }
192
193 static void setSphereColors(const ImVec4& a, const ImVec4& b)
194 {
195 setSphereColors(ImGui::ColorConvertFloat4ToU32(a), ImGui::ColorConvertFloat4ToU32(b));
196 }
197
198 static void setSphereColors(ImU32 a, ImU32 b)
199 {
200 savedSphereColors[0] = sphereColors[0];
201 savedSphereColors[1] = sphereColors[1];
202 sphereColors[0] = a;
203 sphereColors[1] = b;
204 }
205
206 static void restoreSphereColors()
207 {
208 sphereColors[0] = savedSphereColors[0];
209 sphereColors[1] = savedSphereColors[1];
210 }
211
212 //
213 // internals
214 //
215 ////////////////////////////////////////////////////////////////////////////
216 static bool solidAreBuilded;
217 static bool dragActivate;
218
219 int drawMode = mode3Axes;
220 int axesOriginType = cubeAtOrigin;
221 bool showFullAxes = false;
222
223 bool drawFunc(const char* label, float size);
224
225 void modeSettings(int mode)
226 {
227 drawMode = int(mode & modeMask);
228 axesOriginType = int(mode & axesModeMask);
229 showFullAxes = bool(modeFullAxes & mode);
230 }
231
232 void setDualMode(const int mode)
233 {
234 modeSettings((imguiGizmo::modeDual | imguiGizmo::axesModeMask) & (mode | imguiGizmo::modeDual));
235 }
236
237 // vec3 -> quat -> trackbalTransforms -> quat -> vec3
238 ////////////////////////////////////////////////////////////////////////////
239 bool getTransforms(Diligent::Quaternion& q, const char* label, Diligent::float3& dir, float size)
240 {
241 const float len = Diligent::length(dir);
242 q = Diligent::Quaternion::RotationFromAxisAngle(Diligent::normalize(Diligent::float3(.0f, -dir.z, dir.y)), acosf(dir.x/len));
243
244 bool ret = drawFunc(label, size);
245 if (ret) dir = q.RotateVector(Diligent::float3(1, 0, 0)) * len; //return vector with original length
246
247 return ret;
248 }
249 // Vec4 (xyz axis, w angle) -> quat -> trackbalTransforms -> quat -> vec4
250 ////////////////////////////////////////////////////////////////////////////
251 bool getTransforms(Diligent::Quaternion& q, const char* label, Diligent::float4& axis_angle, float size)
252 {
253 q = Diligent::Quaternion::RotationFromAxisAngle(Diligent::float3(axis_angle), axis_angle.w); //g.ConvertFromAxisAngle();
254
255 bool ret = drawFunc(label, size);
256
257 if (ret)q.GetAxisAngle((Diligent::float3&)axis_angle, axis_angle.w);
258
259 return ret;
260 }
261
262 //
263 // Settings
264 //
265 // axes/arrow are composed of cone (or pyramid) and cylinder
266 // (or parallelepiped): this solid are builded at first instance
267 // and will have same slices/radius/length for all controls in your
268 // applications but can be resized proportionally with a reductin
269 // factor: resizeAxesOf and resizeSolidOf (below).
270 // Also the colors of sphere tessellation are set at buil time,
271 // while colors of axes and cube are fixed
272 //
273 // if you want change solids attributes, change the static variables.
274 // If you need to resize solid and axes use resizeAxesOf and
275 // resizeSolidOf, they works like push/pop stack (without buffer!)
276 // with respective restoreAxesSize and restoreSolidSize.
277 // for example:
278 // // reDim axes ... same lenght,
279 // imguiGizmo::resizeAxesOf(Diligent::float3(imguiGizmo::axesResizeFactor.x, 2.0, 2.0));
280 // imguiGizmo::resizeSolidOf(1.25); // sphere bigger
281 // ImGui::gizmo3D("##RotB", b,sz);
282 // imguiGizmo::restoreSolidSize(); // restore at default
283 // imguiGizmo::restoreAxesSize();
284 ////////////////////////////////////////////////////////////////////////////
285
286 //
287 // Build solid components
288 //
289 ////////////////////////////////////////////////////////////////////////////
290
291 // arrow/axes components
292 ///////////////////////////////////////
293 static int coneSlices;
294 static float coneRadius;
295 static float coneLength;
296
297 static int cylSlices;
298 static float cylRadius; // sizeCylLength ... defined in base to control size
299
300 // Sphere components
301 ///////////////////////////////////////
302 static float sphereRadius;
303 static int sphereTessFactor;
304
305 // Cube components
306 ///////////////////////////////////////
307 static float cubeSize;
308
309 // Plane components
310 ///////////////////////////////////////
311 static float planeSize;
312 static float planeThickness;
313
314
315 //
316 // Resizing and color settings
317 //
318 ////////////////////////////////////////////////////////////////////////////
319
320
321 // Axes reduction
322 ///////////////////////////////////////
323 static Diligent::float3 axesResizeFactor;
324 static Diligent::float3 savedAxesResizeFactor;
325
326 // solid reduction
327 ///////////////////////////////////////
328 static float solidResizeFactor;
329 static float savedSolidResizeFactor;
330
331
332 static ImU32 sphereColors[2]; // Tessellation colors
333 static ImU32 savedSphereColors[2];
334 //ImU32 spherecolorA=0xff005cc0, spherecolorB=0xffc05c00;
335
336 static ImVec4 directionColor;
337 static ImVec4 savedDirectionColor;
338
339 static ImVec4 planeColor;
340 static ImVec4 savedPlaneColor;
341
342 static const int imguiGizmoDefaultSize;
343 };
344
345
346
347
348 #define IMGUIZMO_DEF_SIZE (ImGui::GetFrameHeightWithSpacing()*4 - ImGui::GetStyle().ItemSpacing.y*2)
349
350 namespace ImGui
351 {
352
353 IMGUI_API bool gizmo3D(const char*, Diligent::Quaternion&, float=IMGUIZMO_DEF_SIZE, const int=imguiGizmo::mode3Axes|imguiGizmo::cubeAtOrigin);
354 IMGUI_API bool gizmo3D(const char*, Diligent::float4&, float=IMGUIZMO_DEF_SIZE, const int=imguiGizmo::mode3Axes|imguiGizmo::cubeAtOrigin);
355 IMGUI_API bool gizmo3D(const char*, Diligent::float3&, float=IMGUIZMO_DEF_SIZE, const int=imguiGizmo::modeDirection);
356
357 IMGUI_API bool gizmo3D(const char*, Diligent::Quaternion&, Diligent::Quaternion&, float=IMGUIZMO_DEF_SIZE, const int=imguiGizmo::modeDual|imguiGizmo::cubeAtOrigin);
358 IMGUI_API bool gizmo3D(const char*, Diligent::Quaternion&, Diligent::float4&, float=IMGUIZMO_DEF_SIZE, const int=imguiGizmo::modeDual|imguiGizmo::cubeAtOrigin);
359 IMGUI_API bool gizmo3D(const char*, Diligent::Quaternion&, Diligent::float3&, float=IMGUIZMO_DEF_SIZE, const int=imguiGizmo::modeDual|imguiGizmo::cubeAtOrigin);
360
361 };
362
363 //#undef imguiGizmo_DEF_SIZE
0 BSD 2-Clause License
1
2 Copyright (c) 2018 Michele Morrone
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
8 1. Redistributions of source code must retain the above copyright notice, this
9 list of conditions and the following disclaimer.
10
11 2. Redistributions in binary form must reproduce the above copyright notice,
12 this list of conditions and the following disclaimer in the documentation
13 and/or other materials provided with the distribution.
14
15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.