-
Notifications
You must be signed in to change notification settings - Fork 0
/
VimCommon.h
1961 lines (1833 loc) · 76.4 KB
/
VimCommon.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/**
* @mainpage VisMotive Framework
*
* @section intro 소개
* - VisMotive Framework 을 이루는 Global Data Structures, Helper Functions 그리고 Engine APIs를 설명한다.
*
* @section CREATEINFO 작성정보
* - 작성자 : 김동준
* - 작성일 : 2019/7/11
* - Contact : [email protected]
*
* @section MODIFYINFO 수정정보
* - 2019.7.11 : 이 일짜 소스를 기준으로 Framework Doxygen 0.0.1 최초 작성
*/
/**
* @file VimCommon.h
* @brief Global Data Structures 및 Classes 그리고 Helper Functions 선언된 파일.
* @section Include & Link 정보
* - Include : VimCommon.h
* - Library : CommonUnits.lib
* - Linking Binary : CommonUnits.dll
*/
#pragma once
//#define __VERSION "0.x beta" // released at 22.01.10
//#define __VERSION "1.00" // released at 22.02.5
//#define __VERSION "1.01" // released at 22.02.15
//#define __VERSION "1.10" // released at 22.04.02
//#define __VERSION "1.11" // released at 22.05.17
//#define __VERSION "1.12" // released at 22.08.08
//#define __VERSION "1.13" // released at 22.12.05
//#define __VERSION "1.20" // released at 23.04.03
#define __VERSION "1.21" // released at 23.07.16
#define _HAS_STD_BYTE 0
#include <map>
#include <unordered_map>
#include <vector>
#include <set>
#include <string>
#include <sstream>
#include <math.h>
#include <algorithm>
#include <typeinfo>
#include <typeindex>
#include <any>
#include "VimHelpers.h"
#define __WINDOWS
#define __FILEMAP
#ifdef __WINDOWS
#define NOMINMAX
#include <windows.h>
#endif
/**
* @brief VisMotive Framework
*/
//=====================================================================
// Please, project's character set as UNICODE
// GLM library is used as a common math
// Copyright by DongJoon Kim. All rights reserved.
//=====================================================================
// ONLY FOR WINDOWS VERSION
#define VMENGINEVERSION 0x29AD7 // 170711(allocating 20 bits) and 12 bits for modules and engine enhancement version
#define VMSAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } }
#define VMSAFE_DELETEARRAY(p) { if(p) { delete[] (p); (p)=NULL; } }
#define VMSAFE_DELETE2DARRAY(pp, numPtrs) { if(pp){ for(int i = 0; i < numPtrs; i++){ VMSAFE_DELETEARRAY(pp[i]);} VMSAFE_DELETEARRAY(pp); } }
#ifdef __WINDOWS
typedef HMODULE VmHMODULE;
#define VMLOADLIBRARY(hModule, filename) hModule = LoadLibraryA(filename)
#define VMGETPROCADDRESS(pModule, pProcName) GetProcAddress(pModule, pProcName)
#define VMFREELIBRARY(pModule) FreeLibrary(pModule)
#endif
#define __vmstatic extern "C" __declspec(dllexport)
#define __vmstaticinline extern "C" __declspec(dllexport) inline
#define __vmstaticclass class __declspec(dllexport)
#define __vmstaticstruct struct __declspec(dllexport)
#define VM_PI 3.14159265358979323846
#define VM_fPI ((float) 3.141592654f)
#ifndef ushort
typedef unsigned short ushort;
#endif
#ifndef uint
typedef unsigned int uint;
#endif
#if !defined(byte)
//typedef unsigned char byte;
//#define byte unsigned char
#endif
//typedef std::byte byte;
#ifndef ullong
typedef unsigned long long ullong;
#endif
#ifndef llong
typedef long long llong;
#endif
// temp typedefs
// our proj math structures are based on glm::
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtc/constants.hpp>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
typedef struct color4 {
union { struct { byte r, g, b, a; }; struct { byte x, y, z, w; }; };
color4() { r = g = b = a = (byte)0; };
color4(byte _r, byte _g, byte _b, byte _a) { r = _r; g = _g; b = _b; a = _a; };
} vmbyte4;
typedef struct color3 {
union { struct { byte r, g, b; }; struct { byte x, y, z; }; };
color3() { r = g = b = (byte)0; };
color3(byte _r, byte _g, byte _b) { r = _r; g = _g; b = _b; };
} vmbyte3;
typedef struct char2 {
char x, y; char2() { x = y = 0; }
char2(char _x, char _y) { x = _x; y = _y; }
} vmchar2;
typedef struct byte2 {
byte x, y; byte2() { x = y = (byte)0; }
byte2(byte _x, byte _y) { x = _x; y = _y; }
} vmbyte2;
typedef struct short2 {
short x, y; short2() { x = y = 0; }
short2(short _x, short _y) { x = _x; y = _y; }
} vmshort2;
typedef struct ushort2 {
ushort x, y; ushort2() { x = y = 0; }
ushort2(ushort _x, ushort _y) { x = _x; y = _y; }
} vmushort2;
typedef struct short3 {
short x, y, z; short3() { x = y = z = 0; }
short3(short _x, short _y, short _z) {
x = _x; y = _y; z = _z;
}
} vmshort3;
typedef struct ushort3 {
ushort x, y, z; ushort3() { x = y = z = 0; }
ushort3(ushort _x, ushort _y, ushort _z) { x = _x; y = _y; z = _z; }
} vmushort3;
typedef glm::ivec2 vmint2;
typedef glm::ivec3 vmint3;
typedef glm::ivec4 vmint4;
typedef glm::uvec2 vmuint2;
typedef glm::uvec3 vmuint3;
typedef glm::uvec4 vmuint4;
typedef glm::dvec2 vmdouble2;
typedef glm::dvec3 vmdouble3;
typedef glm::dvec4 vmdouble4;
typedef glm::fvec2 vmfloat2;
typedef glm::fvec3 vmfloat3;
typedef glm::fvec4 vmfloat4;
typedef glm::dmat4x4 vmmat44;
typedef glm::fmat4x4 vmmat44f;
#define __VMCVT3__(d, s, t3, tt) d=t3((tt)s.x, (tt)s.y, (tt)s.z)
#define __OPS__(d, s, op) d=op(d, s)
namespace vmlog {
__vmstatic void InitLog(const std::string& coreName, const std::string& logFileName);
__vmstatic void GetLoggerPtr(std::shared_ptr<void>& logger);
__vmstatic void SetLogLevel(const int logLevel);
__vmstatic void LogInfo(std::string str);
__vmstatic void LogWarn(std::string str);
__vmstatic void LogErr(std::string str);
}
//=====================================
// Global Enumerations
//=====================================
/**
* @package vmenums
* @brief Common Data Structure로 사용되는 enumeration 을 모은 namespace
*/
namespace vmenums {
/*! Framework에서 지원하는 변환 좌표계의 종류, 4x4 matrix가 정의하는 Projecting 변환에서 닫혀 있음 */
enum EvmCoordSpace {
CoordSpaceSCREEN = 0,/*!< Pixel로 정의되는 Screen Space */
CoordSpacePROJECTION,/*!< Normalized Frustrum으로 정의되는 Projection Space */
CoordSpaceCAMERA,/*!< Viewing Frustrum으로 정의되는 Camera Space */
CoordSpaceWORLD,/*!< 객체가 실제로 배치되는 World Space */
CoordSpaceOBJECT/*!< 객체가 정의되는 Object Space */
};
/*! Camera의 초기 States(위치, View 및 Up Vector)에 대한 종류 */
enum EvmStageViewType {
StageViewORTHOBOXOVERVIEW = 0,/*!< 3D View에서 OS의 Object Bounding Box의 대각선 방향에 대한 Overview를 정의 */
StageViewCENTERFRONT,/*!< 단면 영상에서 OS의 Object Bounding Box의 기준 Front (or Coronal) View 정의 */
StageViewCENTERRIGHT,/*!< 단면 영상에서 OS의 Object Bounding Box의 기준 Right (or Sagittal) View 정의 */
StageViewCENTERHORIZON/*!< 단면 영상에서 OS의 Object Bounding Box의 기준 Top (or Axial) View 정의 */
};
/*! Polygonal VObject를 정의하는 Primitive 종류 */
enum EvmPrimitiveType {
PrimitiveTypeUNDEFINED = 0,/*!< Undefined */
PrimitiveTypeLINE,/*!< Line */
PrimitiveTypeTRIANGLE,/*!< Triangle */
PrimitiveTypePOINT/*!< Point */
};
/*! VObject 의 Element 단위의 Bounding Unit 의 종류 */
enum EvmBoundingUnitType {
BoundingUnitTypeOBB = 0,/*!< OBB */
BoundingUnitTypeAABB,/*!< AABB */
BoundingUnitTypeSPHERE,/*!< Sphere */
};
/*! Module-Platform interoperation에 사용되는 VmObject의 type 종류 */
enum EvmObjectType {
ObjectTypeOBJECT = 1,/*!< Just an Object for archiving something */
ObjectTypeVOLUME,/*!< Volume Object */
ObjectTypePRIMITIVE,/*!< Polygon Object */
ObjectTypeIMAGEPLANE/*!< Image Plane을 정의하는 VmObject이며 Camera Object를 갖음 */
};
/*! VmIObject에서 사용하는 Frame Buffer 종류 */
enum EvmFrameBufferUsage {
FrameBufferUsageNONE = 0,/*!< Undefined, There is no allocated frame buffer */
// Render //
FrameBufferUsageRENDEROUT,/*!< Used for rendering out buffer, the buffer should have vmbyte4 as data type */
// Depth //
FrameBufferUsageDEPTH,/*!< Used for depth buffer, the buffer should have vmfloat4 as data type */
// Custom //
FrameBufferUsageCUSTOM,/*!< Used for customized purpose, the buffer may have any type */
FrameBufferUsageALIGNEDSTURCTURE,/*!< custom defined bytes, defined as custom structure, aligned by 16 bytes, the buffer may have any type */
FrameBufferUsageVIRTUAL,/*!< Used for customized purpose, the buffer is NULL */
};
}
/**
* @class LocalProgress
* @brief Framework에서 정의하는 progress 에 대한 자료구조
*/
struct LocalProgress {
/**
* @brief progress의 시작, 0.0 에서 100.0 사이
*/
double start;
/**
* @brief progress의 범위, 0.0 에서 100.0 사이
*/
double range;
/**
* @brief progress의 현재 진행 정도가 기록되는 module/function 내의 static parameter 에 대한 포인터
*/
double* progress_ptr; /*out*/
/// constructor, 초기화
LocalProgress()
{
start = 0;
range = 100;
progress_ptr = NULL;
}
/*!
* @fn void vmobjects::LocalProgress::Init()
* @brief >> *progress_ptr = start;
*/
void Init()
{
if (!progress_ptr) return;
*progress_ptr = start;
}
/*!
* @fn void vmobjects::LocalProgress::SetProgress(double dProgress, double dTotal)
* @brief >> *progress_ptr = start + range * progress / total;
*/
void SetProgress(const double progress, const double total)
{
if (!progress_ptr) return;
*progress_ptr =
start + range * progress / total;
}
/*!
* @fn void vmobjects::LocalProgress::Deinit()
* @brief >> dStartProgress = *pdProgressOfCurWork;
*/
void Deinit()
{
if (!progress_ptr) return;
start = *progress_ptr;
}
};
typedef void(*VmDelegate)(void* pv);
/**
* @package vmobjects
* @brief Framework의 Global Data Structures 및 VmObject Classes를 모은 namespace
*/
namespace vmobjects
{
using namespace vmenums;
//=========================
// Object Structures
//=========================
template <typename NAME, typename T, class HASH_COMP = std::hash<NAME>> struct VmMap {
private:
std::string __PM_VERSION = "LIBI_1.4";
std::unordered_map<NAME, T, HASH_COMP> __params;
public:
bool GetParamCheck(const NAME& param_name, T& param) {
auto it = __params.find(param_name);
if (it == __params.end()) return false;
param = it->second;
return true;
}
T GetParam(const NAME& param_name, const T& init_v) {
auto it = __params.find(param_name);
if (it == __params.end()) return init_v;
return it->second;
}
T* GetParamPtr(const NAME& param_name) {
auto it = __params.find(param_name);
if (it == __params.end()) return NULL;
return &it->second;
}
template <typename DSTV> bool GetParamCastingCheck(const NAME& param_name, DSTV& param) {
auto it = __params.find(param_name);
if (it == __params.end()) return false;
param = (DSTV)it->second;
return true;
}
template <typename DSTV> DSTV GetParamCasting(const NAME& param_name, const DSTV& init_v) {
auto it = __params.find(param_name);
if (it == __params.end()) return init_v;
return (DSTV)it->second;
}
void SetParam(const NAME& param_name, const T& param) {
__params[param_name] = param;
}
void RemoveParam(const NAME& param_name) {
auto it = __params.find(param_name);
if (it != __params.end()) {
__params.erase(it);
}
}
void RemoveAll() {
__params.clear();
}
size_t Size() {
return __params.size();
}
std::string GetPMapVersion() {
return __PM_VERSION;
}
typedef std::unordered_map<NAME, T> MapType;
typename typedef MapType::iterator iterator;
typename typedef MapType::const_iterator const_iterator;
typename typedef MapType::reference reference;
iterator begin() { return __params.begin(); }
const_iterator begin() const { return __params.begin(); }
iterator end() { return __params.end(); }
const_iterator end() const { return __params.end(); }
};
template <typename NAME, typename ANY> struct VmParamMap {
private:
std::string __PM_VERSION = "LIBI_1.4";
std::unordered_map<NAME, ANY> __params;
public:
template <typename SRCV> bool GetParamCheck(const NAME& param_name, SRCV& param) {
auto it = __params.find(param_name);
if (it == __params.end()) return false;
param = std::any_cast<SRCV&>(it->second);
return true;
}
template <typename SRCV> SRCV GetParam(const NAME& param_name, const SRCV& init_v) {
auto it = __params.find(param_name);
if (it == __params.end()) return init_v;
return std::any_cast<SRCV&>(it->second);
}
template <typename SRCV> SRCV* GetParamPtr(const NAME& param_name) {
auto it = __params.find(param_name);
if (it == __params.end()) return NULL;
return (SRCV*)&std::any_cast<SRCV&>(it->second);
}
template <typename SRCV, typename DSTV> bool GetParamCastingCheck(const NAME& param_name, DSTV& param) {
auto it = __params.find(param_name);
if (it == __params.end()) return false;
param = (DSTV)std::any_cast<SRCV&>(it->second);
return true;
}
template <typename SRCV, typename DSTV> DSTV GetParamCasting(const NAME& param_name, const DSTV& init_v) {
auto it = __params.find(param_name);
if (it == __params.end()) return init_v;
return (DSTV)std::any_cast<SRCV&>(it->second);
}
void SetParam(const NAME& param_name, const ANY& param) {
__params[param_name] = param;
}
void RemoveParam(const NAME& param_name) {
auto it = __params.find(param_name);
if (it != __params.end()) {
__params.erase(it);
}
}
void RemoveAll() {
__params.clear();
}
size_t Size() {
return __params.size();
}
std::string GetPMapVersion() {
return __PM_VERSION;
}
typedef std::unordered_map<NAME, ANY> MapType;
typename typedef MapType::iterator iterator;
typename typedef MapType::const_iterator const_iterator;
typename typedef MapType::reference reference;
iterator begin() { return __params.begin(); }
const_iterator begin() const { return __params.begin(); }
iterator end() { return __params.end(); }
const_iterator end() const { return __params.end(); }
};
struct data_type {
std::string type_name; // <typeinfo>
size_t type_hash;
size_t type_bytes;
data_type() {
type_name = ""; type_hash = 0; type_bytes = 0;
}
data_type(const std::type_info& info, size_t type_size) {
type_name = info.name(); type_hash = info.hash_code(); type_bytes = type_size;
};
template<typename T>
static data_type dtype() {
data_type d(typeid(T), sizeof(T));
return d;
};
bool operator == (data_type other) const
{
return type_hash == other.type_hash;
}
bool operator != (data_type other) const
{
return type_hash != other.type_hash;
}
};
/**
* @class AaBbMinMax
* @brief 현재 좌표계의 Axis에 평행한 Box를 정의하는 자료구조
*/
struct AaBbMinMax {
/// 현재 좌표계의 Axis에 평행한 Box에 대한 최소점, 최대점 위치
vmdouble3 pos_min, pos_max;
/// constructor, 모두 0 (NULL or false)으로 초기화
AaBbMinMax() { }
/// 현재 좌표계의 AaBbMinMax 가 유효하게 정의되었는가 확인
AaBbMinMax(vmint3 volSize) {
pos_min = vmdouble3(-0.5, -0.5, -0.5);
vmint3 idx_max = volSize - vmint3(1, 1, 1);
pos_max = vmdouble3((double)idx_max.x, (double)idx_max.y, (double)idx_max.z) + vmdouble3(0.5, 0.5, 0.5);
}
bool IsAvailableBox() const {
if (pos_max.x <= pos_min.x || pos_max.y <= pos_min.y || pos_max.z <= pos_min.z)
return false;
return true;
}
};
/**
* @class AxisInfoRS2OS
* @brief Resource Space 에 정의된 x축(1,0,0), y축(0,1,0), z축(0,0,z)이 처음 Object Space (RHS) 에 배치될 때의 방향을 정의 \n
* pitch 는 고려되지 않으며 방향만 정의, (즉 vector 에 대해서만 유효함)
* @sa
* @ref vmobjects::VolumeData
*/
struct AxisInfoRS2OS {
/**
* @brief Resource Space 정의된 x축(1,0,0)에 대응되는 Object Space 상에 배치된 Object의 x축을 정의, unit vector
*/
vmdouble3 vec_axisx_os;
/**
* @brief Resource Space 정의된 y축(0,1,0)에 대응되는 Object Space 상에 배치된 Object의 y축을 정의, unit vector
*/
vmdouble3 vec_axisy_os;
/**
* @brief Object Space 정의된 z축(0,0,1)에 대응되는 World Space 상에 배치된 Object의 z축을 정의하기 위한 XY RHS cross vecor 방향의 reverse 여부\n
* true 면 RHS 로 배치되며 Affine Space 에서 변환 성립, false 면 LHS 로 z툭이 배치
*/
bool is_rhs;
/**
* @brief vec_axisx_ws, vec_axisy_ws, is_rhs 로부터 정의되는 초기 RS2OS 변환 행렬
*/
vmmat44 mat_rs2os;
/**
* @brief constructor, 초기화 작업 수행
* @details
* >> vec_axisx_ws = (1, 0, 0);
* >> vec_axisy_ws = (0, 1, 0);
* >> RHS;
* >> mat_os2ws is identity matrix
*/
AxisInfoRS2OS()
{
vec_axisx_os = vmdouble3(1, 0, 0);
vec_axisy_os = vmdouble3(0, 1, 0);
is_rhs = true;
ComputeInitalMatrix();
}
AxisInfoRS2OS(vmdouble3 _vec_axisx_os, vmdouble3 _vec_axisy_os, bool _is_rhs)
{
vec_axisx_os = _vec_axisx_os;
vec_axisy_os = _vec_axisy_os;
is_rhs = _is_rhs;
ComputeInitalMatrix();
}
/// 정의된 vec_axisx_ws와 vec_axisy_ws로부터 mat_os2ws 계산하여 등록
void ComputeInitalMatrix() {
vmdouble3 z_vec_rhs;
vmmath::CrossDotVector(&z_vec_rhs, &vec_axisy_os, &vec_axisx_os); // note the z-dir in lookat
vmmat44 matT;
vmmath::MatrixWS2CS(&matT, &vmdouble3(0, 0, 0), &vec_axisy_os, &z_vec_rhs);
vmmath::MatrixInverse(&mat_rs2os, &matT);
if (!is_rhs)
{
vmmat44 matInverseZ;
vmmath::MatrixScaling(&matInverseZ, &vmdouble3(1., 1., -1.));
mat_rs2os = mat_rs2os * matInverseZ;
}
}
};
/**
* @class VolumeData
* @brief Framework에서 정의하는 Volume의 상세 정보를 위한 자료구조
* @sa
* @ref vmobjects::VmVObjectVolume \n
*/
struct VolumeData {
/**
* @brief Volume array 의 data type, <typeinfo>
*/
data_type store_dtype;
/**
* @brief 메모리에 저장되기 전 Volume Original data type
*/
data_type origin_dtype;
/**
* @brief Volume을 저장한 2D array (safe sample version)
* @details
* 실제 할당된 x 축 방향 크기 = i3VolumeSize.x + i3SizeExtraBoundary.x*2 \n
* 실제 할당된 y 축 방향 크기 = i3VolumeSize.y + i3SizeExtraBoundary.y*2 \n
* 실제 할당된 z 축 방향 크기 = i3VolumeSize.z + i3SizeExtraBoundary.z*2 \n
* @par ex.
* ushort 512x512x512 Volume에서 (100, 120, 150) index 값 sample \n
* @par
* >> int iSamplePosX = 100 + i3SizeExtraBoundary.x; \n
* >> int iSamplePosY = 120 + i3SizeExtraBoundary.y; \n
* >> int iSamplePosZ = 150 + i3SizeExtraBoundary.z; \n
* >> ushort usValue = ((ushort**)ppvVolumeSlices)[iSamplePosZ][iSamplePosX + iSamplePosY*(i3VolumeSize.x + i3SizeExtraBoundary.x*2)];
*/
void** vol_slices;
/**
* @brief CPU Memory Access Violation을 피하기 위해 System Memory 상의 Extra Boundary 영역의 한쪽면 크기
* @details bnd_size = (한쪽 x축 방향 크기, 한쪽 y축 방향 크기, 한쪽 z축 방향 크기)
*/
vmint3 bnd_size;
/**
* @brief Volume 의 크기 vol_size = (width, height, depth or slices)
* @details bnd_size 가 포함되지 않음
*/
vmint3 vol_size;
/**
* @brief 단위 Voxel에 대해 OS 상 cell 의 WS 상의 크기
* @details vox_pitch = (OS 상의 x 방향 voxel 크기, OS 상의 y 방향 voxel 크기, OS 상의 z 방향 voxel 크기)
*/
vmdouble3 vox_pitch;
/**
* @brief Volume으로 저장된(ppvVolumeSlices)의 최소값 store_Mm_values.x, 최대값 store_Mm_values.y
*/
vmdouble2 store_Mm_values;
/**
* @brief Volume으로 저장되기 전에 정의된 최소값 actual_Mm_values.x, 최대값 actual_Mm_values.y
* @par ex.
* file format float으로 -1.5 ~ 2.5 저장된 볼륨을 ushort 으로 저장할 경우
* @par
* >> store_Mm_values = vmdouble2(0, 65535), actual_Mm_values = vmdouble2(-1.5, 2.5);
*/
vmdouble2 actual_Mm_values;
/**
* @brief Volume에 대한 Histogram 을 정의하는 array
* @details
* array 크기는 uint(d2MinMaxValue.y - d2MinMaxValue.x + 1.5) \n
* pullHistogram[volume value] = # of voxels
*/
ullong* histo_values;
/**
* @brief memory 에 저장된 volume space (샘플 좌표)와 초기 world space 에 배치되는 변환 matrix 정의
*/
AxisInfoRS2OS axis_info;
/**
* @brief constructor, 초기화 작업 수행
*/
VolumeData() {
vol_size = vox_pitch = bnd_size = vmdouble3(0);
store_dtype = data_type(typeid(void), 0);
origin_dtype = data_type(typeid(void), 0);
store_Mm_values = actual_Mm_values = vmdouble2(DBL_MAX, -DBL_MAX);
vol_slices = NULL;
histo_values = NULL;
}
/**
* @brief Histogram array 의 크기를 얻음, uint(store_Mm_values.y - store_Mm_values.x + 1.5)
*/
uint GetHistogramSize() { return (uint)((double)__max(store_Mm_values.y - store_Mm_values.x + 1.5, 1.0)); }
/**
* @brief ppvVolumeSlices array 크기를 얻음, Extra Boundary가 적용된 크기
*/
vmint3 GetSampleSize() { return vmint3(vol_size.x + bnd_size.x * 2, vol_size.y + bnd_size.y * 2, vol_size.z + bnd_size.z * 2); }
// 포인터 ppvVolumeSlices 및 pullHistogram 에 할당된 메모리 해제
void Delete() {
VMSAFE_DELETE2DARRAY(vol_slices, vol_size.z + bnd_size.z * 2);
VMSAFE_DELETEARRAY(histo_values);
}
};
/**
* @class PrimitiveData
* @brief Framework 에서 정의하는 Primitive 로 이루어진 객체의 상세 정보를 위한 자료구조
* @sa vmobjects::VmVObjectPrimitive
*/
struct PrimitiveData {
private:
/**
* @brief vertex array를 저장하는 container map
* string ==> POSITION, NORMAL, TEXCOORD[n], ...
* memory 할당된 pointer를 value로 갖고, @ref PrimitiveData::Delete 에서 해제됨.
*/
std::map<std::string, vmfloat3*> defined_buffers;
public:
/**
* @brief Primitive로 구성 된 객체의 Polygon 의 normal vector 기준의 vertex 배열 방향
*/
bool is_ccw; // will be deprecated
/**
* @brief Primitive Type
*/
EvmPrimitiveType ptype;
/**
* @brief Primitive를 정의하는 vertex의 배열 기준, true : stripe, false : list
*/
bool is_stripe;
/**
* @brief Primitive를 정의하는 vertex 및 edge 의 중복성을 없앴는가의 유무
*/
bool check_redundancy;
/**
* @brief Primitive로 구성 된 객체의 Polygon 개수
*/
uint num_prims;
/**
* @brief 하나의 Primitive(Polygon)을 정의하는 index 개수
*/
uint idx_stride;
/**
* @brief Vertex의 Index기반으로 Polygon을 정의하기 위한 Index Buffer (puiIndexList) 의 크기
* @details
* >> if(is_stripe)\n
* >> num_vidx = num_prims + (idx_stride - 1);\n
* >> else\n
* >> num_vidx = num_prims * idx_stride;
*/
uint num_vidx;
/**
* @brief Vertex의 Index 기반으로 Polygon를 위한 Index Buffer가 정의된 array
*/
uint* vidx_buffer;
/**
* @brief Primitive로 구성 된 객체의 Vertex 개수
*/
uint num_vtx;
/**
* @brief PrimitiveData 단위의 OS 상에서 정의되는 bounding box
*/
AaBbMinMax aabb_os;
/**
* @brief Texture Resource 에 대한 정보 \n
* <w, h, bytes_stride, res_ptr>
*/
std::map<std::string, std::tuple<int, int, int, byte*>> texture_res_info;
bool GetTexureInfo(const std::string& desc, int& w, int& h, int& bytes_stride, byte** res_ptr)
{
auto it = texture_res_info.find(desc);
if (it == texture_res_info.end()) return false;
auto tx_res = it->second;
w = std::get<0>(tx_res);
h = std::get<1>(tx_res);
bytes_stride = std::get<2>(tx_res);
*res_ptr = std::get<3>(tx_res);
return true;
}
/// constructor, 모두 0 (NULL or false)으로 초기화
PrimitiveData() {
is_ccw = true; num_prims = 0; num_vtx = 0;
idx_stride = num_vidx = 0;
ptype = PrimitiveTypeUNDEFINED;
is_stripe = false;
check_redundancy = false;
vidx_buffer = NULL;
}
/*!
* @fn void vmobjects::PrimitiveData::Delete()
* @brief 포인터 puiIndexList 및 defined_buffers 의 value로 정의된 pointer 에 할당된 메모리 해제
*/
void Delete() {
VMSAFE_DELETEARRAY(vidx_buffer);
for (auto it = texture_res_info.begin(); it != texture_res_info.end(); it++)
{
byte* p = std::get<3>(it->second);
VMSAFE_DELETEARRAY(p);
}
texture_res_info.clear();
for (std::map<std::string, vmfloat3*>::iterator itrVertex3D = defined_buffers.begin(); itrVertex3D != defined_buffers.end(); itrVertex3D++)
{
VMSAFE_DELETEARRAY(itrVertex3D->second);
}
defined_buffers.clear();
}
/*!
* @fn vmfloat3* vmobjects::PrimitiveData::GetVerticeDefinition(const string& vtype)
* @brief defined_buffers 의 value로 정의된 pointer 반환하는 method,
* @param vtype [in] \n string \n vertex buffer의 이름, (defined_buffers의 key) \n
* keys : POSITION, NORMAL, TEXCOORD[n], ...
* @return vmfloat3 \n vertex buffer 포인터. 없으면 NULL 반환
*/
vmfloat3* GetVerticeDefinition(const std::string& vtype) {
std::map<std::string, vmfloat3*>::iterator itrVtxDef = defined_buffers.find(vtype);
if (itrVtxDef == defined_buffers.end())
return NULL;
return itrVtxDef->second;
}
/*!
* @fn void vmobjects::PrimitiveData::ReplaceOrAddVerticeDefinition(const string& vtype, vmfloat3* vtx_buffer)
* @brief defined_buffers 의 value로 정의된 pointer 반환하는 method,
* @param vtype [in] \n string \n vertex buffer의 이름, POSITION, NORMAL, TEXCOORD[n], ...
* @param vtx_buffer [in] \n vmfloat3* \n vertex buffer를 정의하는 vmfloat3의 포인터.
* @remarks string vtype 을 키로 갖기 때문에 이미 등록된 vertex definition 이 있을 경우, \n
* 해당 definition 의 vertex pointer 를 메모리에서 해제하고 새로운 vertex pointer 를 등록
*/
void ReplaceOrAddVerticeDefinition(const std::string& vtype, vmfloat3* vtx_buffer) {
vmfloat3* vtx_buffer_old = GetVerticeDefinition(vtype);
if (vtx_buffer_old != NULL)
{
VMSAFE_DELETEARRAY(vtx_buffer_old);
defined_buffers.erase(vtype);
}
defined_buffers.insert(std::pair<std::string, vmfloat3*>(vtype, vtx_buffer));
}
/*!
* @fn int vmobjects::PrimitiveData::GetNumVertexDefinitions()
* @brief 등록된 vertex definition 의 개수를 얻음
* @return int \n 등록된 vertex definition 의 개수
*/
int GetNumVertexDefinitions() const
{
return (int)defined_buffers.size();
}
/*!
* @fn void vmobjects::PrimitiveData::ClearVertexDefinitionContainer()
* @brief mapVerticeDefinitions 를 clear 함.
* @remarks 등록된 vertex pointer 에 대한 메모리 해제는 하지 않고 container 만 clear 함.
*/
void ClearVertexDefinitionContainer()
{
defined_buffers.clear();
}
/*!
* @fn void vmobjects::PrimitiveData::ComputeOrthoBoundingBoxWithCurrentValues()
* @brief defined_buffers 에 등록된 POSITION vtx_buffer 의 position 을 기반으로 AABB min/max 를 구함.
* @remarks 이미 PrimitiveData 의 aabb_os 를 계산했으면 하지 않아도 되나, 그렇지 않으면 반드시 이를 실행하여 AABB 를 정의해야 함.
*/
void ComputeOrthoBoundingBoxWithCurrentValues()
{
vmfloat3* vtx_buffer = GetVerticeDefinition("POSITION");
assert(vtx_buffer != NULL && num_vtx > 0);
aabb_os.pos_min = vmfloat3(DBL_MAX, DBL_MAX, DBL_MAX);
aabb_os.pos_max = vmfloat3(-DBL_MAX, -DBL_MAX, -DBL_MAX);
for (int j = 0; j < (int)num_vtx; j++)
{
const vmfloat3& p = vtx_buffer[j];
vmdouble3 _p;
__VMCVT3__(_p, p, vmdouble3, double);
__OPS__(aabb_os.pos_min.x, _p.x, __min);
__OPS__(aabb_os.pos_min.y, _p.y, __min);
__OPS__(aabb_os.pos_min.z, _p.z, __min);
__OPS__(aabb_os.pos_max.x, _p.x, __max);
__OPS__(aabb_os.pos_max.y, _p.y, __max);
__OPS__(aabb_os.pos_max.z, _p.z, __max);
}
}
};
/**
* @class TMapData
* @brief Framework에서 정의하는 OTF에 대한 상세 정보를 위한 자료구조
* @sa vmobjects::VmTObject
*/
struct MapTable {
/**
* @brief OTF array 의 pointer
* @details
* 1D : [0][0 to (array_lengths.x - 1)] - default, [1][0 to (array_lengths.x - 1)] - customized
* 2D : [0][0 to (array_lengths.x*array_lengths.y - 1)] - default, [...][0 to (array_lengths.x*array_lengths.y - 1)] - customized
* 3D : [0 to (array_lengths.z - 1)][0 to (array_lengths.x*array_lengths.y - 1)]
*/
void** tmap_buffers;
/**
* @brief OTF array 의 pointer dimension
* @details num_dim = 1 or 2 or 3
*/
int num_dim;
/**
* @brief OTF array 에 할당되어 있는 각각의 dimension에 대한 OTF array index 중 최소값
* @details
* valid_min_idx.x : 1st dimension 의 array index 의 최소값 \n
* valid_min_idx.y : 2nd dimension 의 array index 의 최소값 \n
* valid_min_idx.z : 3rd dimension 의 array index 의 최소값
*/
vmint3 valid_min_idx;
/**
* @brief OTF array 에 할당되어 있는 각각의 dimension에 대한 OTF array 값 중 최대값
* @details
* valid_max_idx.x : 1st dimension 의 array 의 최대값 \n
* valid_max_idx.y : 2nd dimension 의 array 의 최대값 \n
* valid_max_idx.z : 3rd dimension 의 array 의 최대값
*/
vmint3 valid_max_idx;
/**
* @brief OTF array 의 각 dimension 에 대한 크기
* @details
* array_lengths.x : 1st dimension 의 array 크기 \n
* array_lengths.y : 2nd dimension 의 array 크기 \n
* array_lengths.z : 3rd dimension 의 array 크기 \n
* Valid dimension에 대하여 array_lengths.xyz > 0, Invalid demension에 대하여 array_lengths.xyz <= 0
*/
vmint3 array_lengths;
/**
* @brief OTF metric의 기준이 되는 Volume 값의 범위에 대한 bin 크기
* @par ex.
* 16 bit Volume Data에 대한 2D OTF (density, gradient magnitude), 각각의 범위를 0~65535 라고 가정할 때 \n
* 512x1024 크기의 2D OTF 를 정의하면, bin 의 XY 크기는 (65536/512, 65536/1024) 가 됨.
*/
vmdouble3 bin_size;
/**
* @brief OTF array 값에 대한 data type
*/
data_type dtype;
/**
* @brief constructor, 모두 0 (NULL or false)으로 초기화
*/
MapTable() {
tmap_buffers = NULL;
num_dim = 0;
valid_min_idx = valid_max_idx = bin_size = vmdouble3(0);
array_lengths = vmint3(0);
}
// Static Helper Functions //
/*!
* @brief VolumeData 에 저장되는 OTF array를 할당하는 static helper 함수
* @param num_dim [in] \n int \n OTF dimension
* @param dim_length [in] \n int 3 \n OTF dimension 의 크기
* @param dtype [in] \n data_type \n OTF array의 data type
* @param res_tmap [in] \n void \n 2D OTF array에 대한 void**의 포인터 (3D 포인터)
* @return bool \n 성공하면 true, 실패하면 false 반환
* @remarks OTF array 는 항상 2D OTF로 저장됨
* @sa vmobjects::TMapData
*/
bool CreateTMapBuffer(const int num_dim, const vmint3& dim_length)
{
if (num_dim <= 0 || num_dim > 3)
{
printf("TMapData::CreateTMapBuffer - UNAVAILABLE INPUT");
return false;
}
switch (num_dim)
{
case 1:
case 2:
if (dim_length.x <= 0 || dim_length.y <= 0)
{
printf("TMapData::CreateTMapBuffer - Type Error 2");
return false;
}
vmhelpers::AllocateVoidPointer2D(&tmap_buffers, dim_length.y, dtype.type_bytes * dim_length.x);
break;
case 3:
if (dim_length.x <= 0 || dim_length.y <= 0 || dim_length.z <= 0)
{
printf("TMapData::CreateTMapBuffer - Type Error 2");
return false;
}
vmhelpers::AllocateVoidPointer2D(&tmap_buffers, dim_length.z, dtype.type_bytes * dim_length.x * dim_length.y);
break;
default:
printf("TMapData::CreateTMapBuffer - UNAVAILABLE INPUT");
return false;
}
return true;
}
/*!
* @fn void vmobjects::TMapData::Delete()
* @brief OTF array 에 대한 포인터 ppvArchiveTF 에 할당된 memory 해제
*/
void Delete() {
switch (num_dim)
{
case 1:
case 2:
VMSAFE_DELETE2DARRAY(tmap_buffers, array_lengths.y);
break;
case 3:
VMSAFE_DELETE2DARRAY(tmap_buffers, array_lengths.z);
break;
default:
break;
}
}
};
/**
* @class VolumeBlocks
* @brief block 기반의 volume에 대한 자료구조
* @sa vmobjects::VmVObjectVolume, vmobjects::VolumeData
*/
struct VolumeBlocks {
/**
* @brief 단위 block의 크기
* @details extra boundary가 포함되지 않은 크기 \n
* unitblk_size = vmint3(size of x, size of y, size of z)
*/
vmint3 unitblk_size;
/**
* @brief block 정보를 저장하는 mM_blks 및 pbTaggedActivatedBlocks 의 extra boundary 의 크기
* @details 이를 고려하여 mM_blks 및 pbTaggedActivatedBlocks 의 값을 샘플해야 함 \n
*/
vmint3 blk_bnd_size;
/**
* @brief 하나의 VolumeBlocks 에 각 축 방향으로 정의된 block들의 개수
* @details 모든 block의 개수 = blk_vol_size.x * blk_vol_size.y * blk_vol_size.z;
*/
vmint3 blk_vol_size;
/**
* @brief block 의 최소 최대 값에 대한 단일 channel data type
* @details 일반적으로 vmobjects::VolumeData.store_dtype 와 같음
*/
data_type dtype;
/**
* @brief block 단위의 최소 최대값을 저장하는 1D array
* @details
* array의 크기는 block의 전체 개수와 동일, extra boundary을 고려하지 않음 \n
* data type은 2 channel을 갖고 volume type과 같음. x : 최소값, y : 최대값
* @par ex.
* 8x8x8 block을 단위로 정의된 512x512x512 volume (ushort) 에서 OS의 (100, 100, 100) 좌표에 해당하는 block의 최소 최대값 \n
* 이 경우 unitblk_size = vmint3(8, 8, 8), blk_vol_size = (ceil(512/8), ceil(512/8), ceil(512/8)) \n
*
* @par
* >> vmint3 blk_id = vmint3(floor(100/8), floor(100/8), floor(100/8)); \n
* >> int blk_idx = blk_id.x + blk_bnd_size.x
* >> + (blk_id.y + blk_bnd_size.y)*(blk_id.x + 2*blk_bnd_size.x)
* >> + (blk_id.z + blk_bnd_size.z)*(blk_id.x + 2*blk_bnd_size.x)*(blk_id.y + 2*blk_bnd_size.y); \n
* >> vmushort2 mM = ((vmushort2*)mM_blks)[iBlockIdIndex];
*/
void* mM_blks;
/**
* @brief Object 별로 정의된, block 단위로 binary tag가 지정된 1D array
* @details
* array의 크기는 block의 전체 개수와 동일, extra boundary을 고려하지 않음 \n
* resource manager 에서 TObject 삭제 시, 등록된 Volume Object 의 Block 들에 대해 resouece 정리 수행 \n
* VolumeBlocks::GetTaggedActivatedBlocks 와 VolumeBlocks::GetTaggedActivatedBlocks 로 Pointer 작업 가능 \n
* @par ex.