|
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 |
}
|