mqsdx 310.0.1 MQPluginSDK Extention Library / mqsdkをC++またはCLI(.Net)拡張するサポートライブラリ

- メインページ
- 関連ページ
- モジュール
- クラス
- ファイル

- ファイル一覧

全て クラス 関数 変数 型定義 プロパティ グループ ページ
MQ0x.hpp
1 /*
2 First author tiritomato 2013.
3
4 mqsdx is distributed under the GNU Lesser General Public License 3.0(LGPLv3).
5
6 support blog (Japanese only)
7 http://d.hatena.ne.jp/tiri_tomato/
8 */
9
10 #ifndef __MQSDKPlugIn0x_11_h__
11 #define __MQSDKPlugIn0x_11_h__
12
13 #define _USE_MATH_DEFINES
14 #include <math.h>
15 #include <stdint.h>
16 #include <string.h>
17
18 #include <algorithm>
19 #include <cmath>
20 #include <functional>
21 #include <iomanip>
22 #include <regex>
23 #include <sstream>
24 #include <utility>
25 #include <vector>
26
27 #define NOMINMAX
28 #define WIN32_LEAN_AND_MEAN
29 #include <windows.h>
30
31 #include <MQSetting.h>
32 #include <MQBasePlugin.h>
33 #include <MQPlugin.h>
34 #include <MQ3DLib.h>
35
36 #include "impl/MQ0x_11.hpp"
37
38 // Plugin Version Checker
39 #ifdef MQPLUGIN_VERSION
40 #if MQPLUGIN_VERSION < 0x0300
41 "MQx" need newer than mqsdk300
42 #endif
43 #else
44 "MQx" need newer than mqsdk300
45 #endif
46
47 namespace MQ0x {
48
78 template <typename T_OUT, const size_t default_seed = 17> struct CollectionHashCode {
79 public:
81 static const T_OUT defaultSeed = (T_OUT)default_seed;
83 CollectionHashCode( const T_OUT seed = defaultSeed ) : m_val( seed ) {}
89 template <typename T_IN> CollectionHashCode( const T_IN *pSrc, const size_t ct, const T_OUT seed = defaultSeed ) : m_val(seed) {
90 if ( pSrc != NULL ) for ( size_t i = 0; i < ct; i++ ) m_val = (m_val * (T_OUT)(sizeof(T_IN) * 8 - 1)) ^ pSrc[i];
91 }
96 CollectionHashCode( const char *pSrc, const T_OUT seed = defaultSeed ) : m_val(FromTrailCodeCollection(pSrc,'\0',seed)) {}
101 CollectionHashCode( const wchar_t *pSrc, const T_OUT seed = defaultSeed ) : m_val(FromTrailCodeCollection(pSrc,L'\0',seed)) {}
107 template <typename T_IN> static CollectionHashCode FromTrailCodeCollection( const T_IN *pSrc, const T_IN trailCode, const T_OUT seed = defaultSeed ) {
108 CollectionHashCode ret(seed);
109 if ( pSrc != NULL ) while ( (*pSrc) != trailCode ) ret.m_val = (ret.m_val * (T_OUT)(sizeof(T_IN) * 8 - 1)) ^ (*(pSrc++));
110 return ret;
111 }
113 operator T_OUT() { return m_val; }
114 private:
115 T_OUT m_val;
116 };
117
120 template <typename T> struct HSV {
121 typedef T value_type;
122 T h;
123 T s;
124 T v;
125 HSV() : h(T(0)), s(T(0)), v(T(0)) {}
126 HSV(T h_, T s_, T v_) : h(h_), s(s_), v(v_) {}
127 HSV( const HSV& src ) : h(src.h), s(src.s), v(src.v) {}
128 HSV( const MQColor& rgb ) : h(T(0)), s(T(0)), v(T(0)) {
130 const T min = T(std::min(std::min(rgb.r,rgb.g),rgb.b));
131 const T max = T(std::max(std::max(rgb.r,rgb.g),rgb.b));
132 const T delta = max - min;
133 v = max;
134 if(delta!=T(0)) {
135 s = delta / max;
136 if ( rgb.r == max ) h = (rgb.g-rgb.b) / delta;
137 else if (rgb.g == max) h = T(2) + (rgb.b-rgb.r) / delta;
138 else h = T(4) + (rgb.r-rgb.g) / delta;
139 h /= T(6);
140 if ( h < T(0) ) h += T(1);
141 }
142 }
146 bool isGrayScale( T threshold ) const { return threshold < s; }
149 bool isGrayScale() const { return isGrayScale(std::numeric_limits<T>::epsilon()); }
152 void normalize() {
153 h -= std::floor(h);
154 s = clamp01(s);
155 v = clamp01(v);
156 }
158 MQColor toMQColor() const {
159 const HSV normal = toNormalized(); // to [0,1]
160 if ( normal.isGrayScale() ) return MQColor( normal.v );
161 const T H = normal.h * T(6);
162 const int Hi = static_cast<int>(H);
163 const T fr = H - T(Hi);
164 const T m = normal.v * (T(1)-normal.s);
165 const T n = normal.v * (T(1)-normal.s*fr);
166 const T p = normal.v * (T(1)-normal.s*(T(1)-fr));
167 switch(Hi) {
168 case 0: return MQColor( float(normal.v), float(p), float(m) );
169 case 1: return MQColor( float(n), float(normal.v), float(m) );
170 case 2: return MQColor( float(m), float(normal.v), float(p) );
171 case 3: return MQColor( float(m), float(n), float(normal.v) );
172 case 4: return MQColor( float(p), float(m), float(normal.v) );
173 default: return MQColor( float(normal.v), float(m), float(n) );
174 }
175 }
177 HSV toNormalized() const { return HSV( h - std::floor(h), Clamp01(s), Clamp01(v) ); }
178 };
179
193 struct SettingProxy {
194 public:
196 struct Handle {
198 friend struct SettingProxy;
199 template <typename T_MQPLUGIN> friend class PluginBase;
201 static Handle Empty() { return Handle(NULL); }
202 public:
203 Handle( MQBasePlugin* plugin ) { this->plugin = plugin; }
204 MQBasePlugin* plugin;
205 };
206 SettingProxy( Handle handle );
207 ~SettingProxy() { Close(); }
208 void Close();
209 bool Load(const char *name, bool& value, bool default_value=false);
210 bool Load(const char *name, int& value, int default_value=0);
211 bool Load(const char *name, unsigned int& value, unsigned int default_value=0);
212 bool Load(const char *name, float& value, float default_value=0.0f);
213 bool Load(const char *name, std::string& value, std::string default_value="");
214 bool Save(const char *name, const bool& value);
215 bool Save(const char *name, const int& value);
216 bool Save(const char *name, const unsigned int& value);
217 bool Save(const char *name, const float& value);
218 bool Save(const char *name, const char* value);
219 bool Save(const char *name, const std::string& value);
220 private:
221 SettingProxy(const SettingProxy&); // kill copy
222 SettingProxy& operator=(const SettingProxy&); // kill copy
223 MQBasePlugin* m_plugin;
224 MQSetting* m_setting;
225 };
226
262 template <typename T_MQPLUGIN> class PluginBase : public T_MQPLUGIN {
263 public:
264 PluginBase( const char* productName, const char* pluginFullName, const char* pluginString ) :
265 m_productName( productName ),
266 m_pluginFullName( pluginFullName ),
267 m_pluginString( pluginString ),
268 m_idProduct( CollectionHashCode<DWORD>(productName) ),
269 m_idPlugin( CollectionHashCode<DWORD>(pluginFullName) )
270 {
271 }
272
273 PluginBase( const char* productName, const char* pluginFullName, const char* pluginString,
274 const DWORD idProduct, const DWORD idPlugin ) :
275 m_productName( productName ),
276 m_pluginFullName( pluginFullName ),
277 m_pluginString( pluginString ),
278 m_idProduct( idProduct ),
279 m_idPlugin( idPlugin )
280 {
281 }
282
284 virtual void GetPlugInID(DWORD *Product, DWORD *ID) {
285 *Product = m_idProduct;
286 *ID = m_idPlugin;
287 }
289 virtual const char *GetPlugInName() { return m_pluginFullName.c_str(); }
291 virtual const char *EnumString() { return m_pluginString.c_str(); }
293 const char* GetProductName() { return m_productName.c_str(); }
295 MQBasePlugin* BasePlugin() { return this; }
297 SettingProxy::Handle Setting() { return SettingProxy::Handle(BasePlugin()); }
299 DWORD ProductID() { return m_idProduct; }
301 DWORD PluginID() { return m_idPlugin; }
302 protected:
303 const std::string m_productName;
304 const std::string m_pluginFullName;
305 const std::string m_pluginString;
306 const DWORD m_idProduct;
307 const DWORD m_idPlugin;
308 };
309
310 namespace Math {
313
315 template <typename T> inline T Ceil( T src ) { return src; }
317 template <> inline float Ceil( float src ) { return std::ceil(src); }
318 template <> inline double Ceil( double src ) { return std::ceil(src); }
319 template <> inline long double Ceil( long double src ) { return std::ceil(src); }
321
323 template <typename T> inline T Clamp( T src, T min, T max ) {
324 return std::min( std::max(min,max), std::max( std::min(min,max), src) );
325 }
326
328 template <typename T> inline T Clamp01( T src ) { return std::min(T(1),std::max(T(0),src)); }
329
331 template <typename T> inline T Floor( T src ) { return src; }
333 template <> inline float Floor( float src ) { return std::floor(src); }
334 template <> inline double Floor( double src ) { return std::floor(src); }
335 template <> inline long double Floor( long double src ) { return std::floor(src); }
337
340 template <typename T> inline T Lerp(T from, T to, T t) { return from + (to - from) * clamp01(t); }
341
343 template <typename T> inline T MoveTo( T from, T to, T mov ) {
344 mov = std::abs(mov);
345 if ( std::abs(from - to) < mov ) return to;
346 return from += ( from < to ? mov : -mov );
347 }
348
350 template <typename T> inline T Pi() { return (T)M_PI; }
352 template <> long double Pi();
354
360 template <typename T> inline T Deg2Rad() { return Pi<T>() / (T)180; }
362 template <typename T> inline T Deg2Rad(T degree) { return Deg2Rad<T>() * degree; }
363
369 template <typename T> inline T Rad2Deg() { return (T)180 / Pi<T>(); }
371 template <typename T> inline T Rad2Deg(T degree) { return Rad2Deg() * degree; }
372
374 template <typename T> inline T Repeat( T t, T length ) { return t - std::floor(t/length)*length; }
375
377 template <typename T> inline T Trunc( T src ) { if ( T(0) < src ) return floor(src); return ceil(src); }
379 }
380 using namespace Math;
381
382
383 namespace Polygon {
386
388 struct VertexNormalBuffer;
390
395 struct FaceNormalBuffer {
396 typedef std::vector<MQPoint>::size_type size_type;
398 static bool IsInvalid( const MQPoint& src ) { return src.x >= std::numeric_limits<float>::infinity(); }
400 FaceNormalBuffer() : m_obj(NULL), m_buffer(0), invalid_value( std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity() ) {}
402 FaceNormalBuffer( const ::MQObject obj ) : m_obj( obj ), m_buffer(0),
403 invalid_value( std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity() ) {
404 if ( obj != NULL ) {
405 const int ctFaceMax = obj->GetFaceCount();
406 m_buffer.resize( ctFaceMax );
407 for ( int ctFace = 0; ctFace < ctFaceMax; ctFace++ ) m_buffer[ctFace].x = invalid_value.x;
408 }
409 }
413 void Clear( const bool isCompact = false ) {
414 if ( isCompact ) {
415 size_type sz = 0; if ( m_obj != NULL ) sz = size_type(m_obj->GetFaceCount());
416 std::vector<MQPoint>(sz).swap( m_buffer );
417 }
418 for ( size_type ctFace = 0; ctFace < m_buffer.size(); ctFace++ ) m_buffer[ctFace].x = invalid_value.x;
419 }
423 void Clear( const ::MQObject obj, const bool isCompact = false ) { m_obj = obj; Clear(isCompact); }
425 void Compact() {
426 size_type sz = 0; if ( m_obj != NULL ) sz = size_type(m_obj->GetFaceCount());
427 m_buffer.resize(sz);
428 m_buffer.shrink_to_fit();
429 }
431 const ::MQObject MQObject() const { return m_obj; }
438 const MQPoint& operator [] ( size_type index ) {
439 if ( m_obj == NULL ) {
440 if ( (index < m_buffer.size()) && (IsInvalid(m_buffer[index])==false) ) return m_buffer[index];
441 }
442 else {
443 const size_type ctFaceMax = size_type(m_obj->GetFaceCount());
444 if ( index < ctFaceMax ) {
445 const size_type registedSize = m_buffer.size();
446 if ( registedSize < ctFaceMax ) {
447 m_buffer.resize( ctFaceMax );
448 for ( size_type ct = registedSize; ct < ctFaceMax; ct++ ) m_buffer[ct].x = invalid_value.x;
449 }
450 if ( IsInvalid(m_buffer[index]) ) {
451 const int ctFacePointMax = m_obj->GetFacePointCount( index );
452 if ( (ctFacePointMax==3) || (ctFacePointMax==4) ) {
453 int v[4];
454 m_obj->GetFacePointArray( index, v );
455 if ( ctFacePointMax==3 )
456 m_buffer[index] = GetNormal( m_obj->GetVertex(v[0]), m_obj->GetVertex(v[1]), m_obj->GetVertex(v[2]) );
457 else if ( ctFacePointMax==4 )
458 m_buffer[index] = GetQuadNormal( m_obj->GetVertex(v[0]), m_obj->GetVertex(v[1]), m_obj->GetVertex(v[2]), m_obj->GetVertex(v[3]) );
459 }
460 }
461 return m_buffer[index];
462 }
463 }
464 return invalid_value;
465 }
466 private:
468 friend struct Polygon::VertexNormalBuffer;
470 const MQPoint invalid_value;
471 ::MQObject m_obj;
472 std::vector<MQPoint> m_buffer;
473 };
474
479 struct VertexNormalBuffer {
480 typedef std::vector<MQPoint>::size_type size_type;
482 static bool IsInvalid( const MQPoint& src ) { return FaceNormalBuffer::IsInvalid(src); }
484 VertexNormalBuffer() : m_face_normals( NULL ), m_buffer(0) {}
486 VertexNormalBuffer( const ::MQObject obj ) : m_face_normals( obj ), m_buffer(0) { if (obj != NULL) Clear(obj); }
490 void Clear( const bool isCompact = false ) {
491 if ( isCompact ) {
492 size_type sz = 0;
493 if ( m_face_normals.m_obj != NULL ) sz = size_type(m_face_normals.m_obj->GetVertexCount());
494 std::vector<MQPoint>(sz).swap( m_buffer );
495 }
496 for ( size_type ctFace = 0; ctFace < m_buffer.size(); ctFace++ ) m_buffer[ctFace].x = m_face_normals.invalid_value.x;
497 m_face_normals.Clear(isCompact);
498 }
502 void Clear( const ::MQObject obj, const bool isCompact = false ) {
503 if ( isCompact ) {
504 size_type sz = 0; if ( obj != NULL ) sz = size_type(obj->GetVertexCount());
505 std::vector<MQPoint>(sz).swap( m_buffer );
506 }
507 for ( size_type ctFace = 0; ctFace < m_buffer.size(); ctFace++ ) m_buffer[ctFace].x = m_face_normals.invalid_value.x;
508 m_face_normals.Clear(obj,isCompact);
509 }
512 void Compact() {
513 size_type sz = 0;
514 if ( m_face_normals.m_obj != NULL ) sz = size_type(m_face_normals.m_obj->GetVertexCount());
515 m_buffer.resize(sz);
516 m_buffer.shrink_to_fit();
517 m_face_normals.Compact();
518 }
526 const MQPoint& FaceNormal( FaceNormalBuffer::size_type index ) { return m_face_normals[index]; }
528 const ::MQObject MQObject() const { return m_face_normals.MQObject(); }
535 const MQPoint& VertexNormal( size_type index ) {
536 if ( m_face_normals.m_obj == NULL ) {
537 if ( (index < m_buffer.size()) && (IsInvalid(m_buffer[index])==false) ) return m_buffer[index];
538 }
539 else {
540 const size_type ctVertexMax = size_type(m_face_normals.m_obj->GetVertexCount());
541 if ( index < ctVertexMax ) {
542 const size_type registedSize = m_buffer.size();
543 if ( registedSize < ctVertexMax ) {
544 m_buffer.resize( ctVertexMax );
545 for ( size_type ct = registedSize; ct < ctVertexMax; ct++ ) m_buffer[ct].x = m_face_normals.invalid_value.x;
546 }
547 MQPoint& ret = m_buffer[index]; // get [in,out] reference
548 if ( IsInvalid(ret) ) {
549 const std::vector<int>::size_type ctFaceMax = std::vector<int>::size_type(m_face_normals.m_obj->GetVertexRelatedFaces( index, NULL ));
550 if (ctFaceMax == 1)
551 {
552 int face_index;
553 m_face_normals.m_obj->GetVertexRelatedFaces( index, &face_index );
554 ret = FaceNormal(FaceNormalBuffer::size_type(face_index));
555 }
556 else if ( 1 < ctFaceMax ) {
557 std::vector<int> face_indexes( ctFaceMax );
558 std::vector<int> vertexIndexesOfFace(4);
559 m_face_normals.m_obj->GetVertexRelatedFaces( index, &face_indexes[0] );
560 unsigned int ctAdd = 0;
561 ret.zero(); // ret reference clear
562 for ( std::vector<int>::size_type ct = 0; ct < ctFaceMax; ct++ ) // all check of related face
563 {
564 const MQPoint& n = FaceNormal(FaceNormalBuffer::size_type(face_indexes[ct]));
565 if ( FaceNormalBuffer::IsInvalid(n) == false )
566 {
567 const std::vector<int>::size_type vertexCountOfFace = std::vector<int>::size_type(m_face_normals.m_obj->GetFacePointCount(face_indexes[ct]));
568 if (vertexIndexesOfFace.size() < vertexCountOfFace) vertexIndexesOfFace.resize(vertexCountOfFace);
569 m_face_normals.m_obj->GetFacePointArray(face_indexes[ct], &vertexIndexesOfFace[0]);
570 int findCt = 0;
571 std::vector<int>::size_type findPosition;
572 for (std::vector<int>::size_type ct = 0; ct < vertexCountOfFace; ct++)
573 {
574 if (index == vertexIndexesOfFace[ct]) if (findCt++ == 0) findPosition = ct;
575 }
576 if (findCt != 1) continue;
577 const int prevVertexIndex = vertexIndexesOfFace[(findPosition <= 0 ? vertexCountOfFace : findPosition) - 1];
578 const int nextVertexIndex = vertexIndexesOfFace[(findPosition + 1) < vertexCountOfFace ? (findPosition + 1) : 0];
579 const MQPoint vertex = m_face_normals.m_obj->GetVertex(index);
580 MQPoint toPrevVertex = m_face_normals.m_obj->GetVertex(prevVertexIndex) - vertex;
581 MQPoint toNextVertex = m_face_normals.m_obj->GetVertex(nextVertexIndex) - vertex;
582 float cos = GetInnerProduct(toPrevVertex, toNextVertex) / (GetSize(toPrevVertex) * GetSize(toNextVertex));
583 ret += (n * (1.0f - cos)); // n * (2.0 - (cos + 1.0))
584 ctAdd++;
585 }
586 }
587 if (0 < ctAdd) ret.normalize();
588 else ret.x = m_face_normals.invalid_value.x;
589 }
590 }
591 return ret;
592 }
593 }
594 return m_face_normals.invalid_value;
595 }
597 const MQPoint& operator [] ( size_type index ) { return VertexNormal(index); }
598 private:
599 FaceNormalBuffer m_face_normals;
600 std::vector<MQPoint> m_buffer;
601 };
602
604 class UVFaceBuffer {
605 public:
606
608 struct UVPoint {
609 MQCoordinate uv;
610 UVPoint( const MQCoordinate& initial_uv ) : uv(initial_uv) {}
616 struct Buffer {
617 typedef uint16_t resolution_type;
618 static const resolution_type resolution = 10;
619 private:
620 typedef std::vector<UVPoint> base_buffer_type;
621 base_buffer_type m_buffer[resolution];
623 friend struct Index;
625 public:
629 struct Index : public std::pair<resolution_type, base_buffer_type::size_type> {
631 friend struct MQ0x::Polygon::UVFaceBuffer::UVPoint::Buffer;
633 typedef std::pair<resolution_type, base_buffer_type::size_type> base_type;
634 Index() : base_type( resolution, 0 ) {}
635 private:
636 Index( resolution_type first, base_buffer_type::size_type second ) : base_type(first, second) {}
637 resolution_type first() const { return base_type::first; }
638 base_buffer_type::size_type second() const { return base_type::second; }
639 };
642 const UVPoint* GetAccessAt( const Index& index ) const {
643 if ( ( index.first() < resolution ) && ( index.second() < m_buffer[index.first()].size() ) ) return &(m_buffer[index.first()][index.second()]);
644 return NULL;
645 }
649 const Index GetIndexOf( const MQCoordinate &uv, const float epsilon ) {
650 const float abs_e = std::abs(epsilon);
651 const resolution_type first = std::min( resolution_type(std::max( uv.u * float(resolution), 0.0f)), resolution_type(resolution - 1) );
652 const base_buffer_type::size_type size = m_buffer[first].size();
653 for ( base_buffer_type::size_type ct = 0; ct < size; ct++ ) {
654 const MQCoordinate& buffer_uv = m_buffer[first][ct].uv;
655 if ( (std::abs(uv.u - buffer_uv.u) < abs_e) && (std::abs(uv.v - buffer_uv.v) < abs_e) ) return Index( first, ct );
656 }
657 m_buffer[first].push_back( UVPoint(uv) );
658 return Index( first, size );
659 }
662 void Clear( const bool isCompact = false ) {
663 for ( int ct = 0; ct < resolution; ct++ ) {
664 if ( isCompact ) base_buffer_type().swap( m_buffer[ct] );
665 else m_buffer[ct].clear();
666 }
667 }
669 void Compact() { for ( int ct = 0; ct < resolution; ct++ ) m_buffer[ct].shrink_to_fit(); }
671 UVPoint& operator [] ( const Index& index ) { return m_buffer[index.first()][index.second()]; }
672 };
673 };
674
676 struct Face {
678 struct Point {
679 UVPoint::Buffer::Index index;
680 uint32_t color;
681 };
682
684 struct Buffer {
685 private:
686 typedef std::vector<Face> buffer_type;
687 friend class Polygon::UVFaceBuffer;
688 public:
690 typedef buffer_type::size_type Index;
693 struct IndexBuffer {
695 typedef std::vector<Index>::size_type Index;
697 typedef std::vector<Index>::const_iterator ConstIterator;
699 Face::Buffer::Index operator[] ( IndexBuffer::Index index ) const { return m_buffer[index]; }
702 Face::Buffer::IndexBuffer::Index Add( Face::Buffer::Index index ) {
703 IndexBuffer::Index ret;
704 if ( Contains( index, &ret ) == false ) {
705 ret = m_buffer.size();
706 m_buffer.push_back(index);
707 }
708 return ret;
709 }
711 ConstIterator Begin() const { return m_buffer.begin(); }
713 bool Contains( const Face::Buffer::Index src, IndexBuffer::Index* find_index = NULL ) const {
714 for ( Index index = 0; index < m_buffer.size(); index++ ) {
715 if ( m_buffer[index] == src ) { if ( find_index != NULL ) *find_index = index; return true; }
716 }
717 return false;
718 }
720 IndexBuffer::Index Count() const { return m_buffer.size(); }
722 ConstIterator End() const { return m_buffer.end(); }
723 private:
724 std::vector<Face::Buffer::Index> m_buffer;
725 };
727 const Face* operator [] ( Index index ) const { if ( index < m_buffer.size() ) return &m_buffer[index]; return NULL; }
729 void Add( const Face& add_item ) { m_buffer.push_back( add_item ); }
731 Index BeginIndex() const { return 0; }
733 void Clear( const bool isCompact = false ) { if ( isCompact ) std::vector<Face>().swap( m_buffer ); else m_buffer.clear(); }
735 void Compact() { m_buffer.shrink_to_fit(); }
737 Index Count() const { return m_buffer.size(); }
739 Index EndIndex() const { return m_buffer.size(); }
741 void Reserve( const Index size ) { m_buffer.reserve( size ); }
742 private:
743 buffer_type m_buffer;
744 };
746 UINT object_uid;
748 UINT face_uid;
750 std::size_t PointsCount() const { return m_szPoints; }
752 const Point* GetPointFrom( const UVPoint::Buffer::Index& search_index ) const {
753 for ( std::size_t ct = 0; ct < m_szPoints; ct++ ) if ( m_points[ct].index == search_index ) return (m_points + ct);
754 return NULL;
755 }
757 const Point& Points(std::size_t index) const { return m_points[index]; }
758 Face() : m_szPoints(0) {}
759 private:
761 friend class Polygon::UVFaceBuffer;
763 std::size_t m_szPoints;
764 Face::Point m_points[4];
765 };
766
768 struct Edge {
769
774 struct VertexPair : public std::pair<UVPoint::Buffer::Index, UVPoint::Buffer::Index> {
775 typedef std::pair<UVPoint::Buffer::Index, UVPoint::Buffer::Index> base_type;
776 VertexPair( const UVPoint::Buffer::Index& first, const UVPoint::Buffer::Index& second )
777 : base_type( std::min(first, second), std::max(first, second) ) {}
778 VertexPair( const VertexPair& src ) : base_type( src[0], src[1] ) {}
779 VertexPair( const UVPoint::Buffer::Index* pSrc ) { *this = pSrc; }
780 VertexPair& operator = ( const UVPoint::Buffer::Index* pSrc ) {
782 if ( pSrc != NULL ) {
783 if ( pSrc[0] < pSrc[1] ) {
784 base_type::first = pSrc[0];
785 base_type::second = pSrc[1];
786 }
787 else {
788 base_type::first = pSrc[1];
789 base_type::second = pSrc[0];
790 }
791 }
792 return *this;
793 }
795 VertexPair& operator = ( const VertexPair& src ) { base_type::first = src[0]; base_type::second = src[1]; return *this; }
797 UVPoint::Buffer::Index operator [](int index) const { return index == 0 ? base_type::first : base_type::second; }
799 bool Contains( const UVPoint::Buffer::Index& index ) const { return (base_type::first == index) || (base_type::second == index); }
800 private:
801 UVPoint::Buffer::Index first(); // kill access
802 UVPoint::Buffer::Index second(); // kill access
803 };
804
806 struct Buffer {
807 private:
808 typedef std::vector<Edge> buffer_type;
809 public:
810 typedef buffer_type::const_iterator ConstIterator;
811 void Add( const VertexPair& vertex_pair, const Face::Buffer::Index& index );
814 ConstIterator Begin() const { return m_buffer.begin(); }
815 void Clear( const bool isCompact = false ) { if ( isCompact ) std::vector<Edge>().swap( m_buffer ); else m_buffer.clear(); }
817 void Compact() { m_buffer.shrink_to_fit(); }
818 ConstIterator End() const { return m_buffer.end(); }
819 private:
820 buffer_type m_buffer;
821 };
822
823 Edge( const VertexPair& v_pair, Face::Buffer::Index face_index ) : m_vertex_pair(v_pair) { m_owner_faces.Add(face_index); }
824 Edge( const UVPoint::Buffer::Index* pSrc, Face::Buffer::Index face_index ) : m_vertex_pair(pSrc) {
825 if ( pSrc != NULL ) m_owner_faces.Add(face_index);
826 }
828 bool operator == ( const VertexPair& src ) const { return (const VertexPair::base_type&)m_vertex_pair == (const VertexPair::base_type&)src; }
830 const VertexPair& IndexPair() const { return m_vertex_pair; }
833 UVPoint::Buffer::Index IndexPair(int index) const { return m_vertex_pair[index]; }
836 const Face::Buffer::IndexBuffer& Owners() const { return m_owner_faces; }
839 Face::Buffer::Index Owners( const Face::Buffer::IndexBuffer::Index& index ) const { return m_owner_faces[index]; }
840 private:
842 friend struct Edge::Buffer;
844 VertexPair m_vertex_pair;
845 Face::Buffer::IndexBuffer m_owner_faces;
846 };
847
848 struct Functors {
851 struct BasicUVTransformFunctor {
860 bool operator()( MQCoordinate* const uv_coorinates, DWORD* const colors,
861 const MQObject obj, const int count_of_points, const int face_index, const UINT face_uid ) { return true; }
862 };
863
866 struct NormaledUVTransformFunctor {
877 bool operator()( MQCoordinate* const uv_coorinates, DWORD* const colors,
878 const MQObject obj, const int count_of_points, const int face_index, const UINT face_uid,
879 const MQPoint& normal, MQPoint* const point_normals ) { return true; }
880 };
881
882 template <class _NormaledCoordinateTransformFunctor> struct CoordinateTransformFunctorFromNormaled {
883 _NormaledCoordinateTransformFunctor functor;
885 bool operator()(
886 MQCoordinate* const uv_coorinates, DWORD* const colors,
887 const MQObject obj, const int count_of_points, const int face_index, const UINT face_uid )
888 {
889 MQPoint v_normal_buffer[4];
890 int v_index_buffer[4];
891 obj->GetFacePointArray( face_index, v_index_buffer );
892 for ( int ctFacePoint = 0; ctFacePoint < count_of_points; ctFacePoint++ ) {
893 v_normal_buffer[ctFacePoint] = m_normal_buffer.VertexNormal( VertexNormalBuffer::size_type(v_index_buffer[ctFacePoint]) );
894 }
895 return functor( uv_coorinates, colors, obj, count_of_points, face_index, face_uid, m_normal_buffer.FaceNormal(face_index), v_normal_buffer );
896 }
897 private:
898 VertexNormalBuffer m_normal_buffer;
899 };
900 };
901
903 UVFaceBuffer() : m_epsilon( std::numeric_limits<float>::epsilon() ) {}
904
907 template <class _BasicUVTransformFunctor> void AddObject( const MQObject obj, _BasicUVTransformFunctor& coordinateTrans ) {
908 if ( obj == NULL ) return;
909 MQCoordinate coordinate_buffer[4];
910 DWORD vertex_color_buffer[4];
911 Face add_face;
912 const int ctFaceMax = obj->GetFaceCount();
913 const UINT obj_uid = obj->GetUniqueID();
914 const float eps = m_epsilon;
915 m_face_buffer.Reserve( m_face_buffer.Count() + (Face::Buffer::Index)ctFaceMax );
916 add_face.object_uid = obj_uid;
917 for ( int ctFace = 0; ctFace < ctFaceMax; ctFace++ ) {
918 const UINT uidFace = obj->GetFaceUniqueID( ctFace );
919 const int ctFacePointMax = obj->GetFacePointCount( ctFace );
920 if ( (ctFacePointMax<3)||(4<ctFacePointMax) ) continue;
921 obj->GetFaceCoordinateArray( ctFace, coordinate_buffer );
922 for ( int ctFacePoint = 0; ctFacePoint < ctFacePointMax; ctFacePoint++ ) {
923 vertex_color_buffer[ctFacePoint] = obj->GetFaceVertexColor( ctFace, ctFacePoint );
924 }
925 if ( coordinateTrans( coordinate_buffer, vertex_color_buffer, obj, ctFacePointMax, ctFace, uidFace ) == false ) continue;
926 add_face.face_uid = uidFace;
927 add_face.m_szPoints = ctFacePointMax;
928 for ( int ctFacePoint = 0; ctFacePoint < ctFacePointMax; ctFacePoint++ ) {
929 add_face.m_points[ctFacePoint].index = m_uv_buffer.GetIndexOf( coordinate_buffer[ctFacePoint], eps );
930 add_face.m_points[ctFacePoint].color = vertex_color_buffer[ctFacePoint];
931 }
932 m_face_buffer.Add(add_face);
933 for ( int ctFacePoint = 0; ctFacePoint < ctFacePointMax; ctFacePoint++ ) {
934 int ctFacePointNext = (ctFacePoint < (ctFacePointMax-1)) ? ctFacePoint + 1 : 0;
935 const Edge::VertexPair add_edge( add_face.m_points[ctFacePoint].index, add_face.m_points[ctFacePointNext].index );
936 m_edge_buffer.Add( add_edge, m_face_buffer.Count()-1 );
937 }
938 }
939 }
941 void AddObject( const MQObject obj ) { AddObject( obj, Functors::BasicUVTransformFunctor() ); }
943 template <class _BasicUVTransformFunctor> void AddObjectRecursive(const MQDocument doc, const MQObject obj, _BasicUVTransformFunctor& coordinateTrans)
944 {
945 if ( (doc == NULL) || (obj == NULL) ) return;
946 AddObject( obj, coordinateTrans );
947 const int ctChild = doc->GetChildObjectCount(obj);
948 for ( int indexCh = 0; indexCh < ctChild; indexCh++ ) AddObjectRecursive( doc, doc->GetChildObject( obj, indexCh ), coordinateTrans );
949 }
951 void AddObjectRecursive(const MQDocument doc, const MQObject obj) { AddObjectRecursive(doc, obj, Functors::BasicUVTransformFunctor()); }
952
955 void Clear( const bool isCompact = false ) { m_edge_buffer.Clear(isCompact); m_face_buffer.Clear(isCompact); m_uv_buffer.Clear(isCompact); }
957 void Compact() { m_uv_buffer.Compact(); m_face_buffer.Compact(); m_edge_buffer.Compact(); }
959 const Edge::Buffer& EdgeBuffer() const { return m_edge_buffer; }
961 float Epsilon() const { return m_epsilon; }
963 float Epsilon( float setValue ) { return m_epsilon = std::abs(setValue); }
965 const Face* FaceBuffer( const Face::Buffer::Index& index ) const { return m_face_buffer[index]; }
967 const Face::Buffer& FaceBuffer() const { return m_face_buffer; }
969 const UVPoint* UVBuffer( const UVPoint::Buffer::Index& index ) const { return m_uv_buffer.GetAccessAt(index); }
970
971 private:
972 float m_epsilon;
973 UVPoint::Buffer m_uv_buffer;
974 Face::Buffer m_face_buffer;
975 Edge::Buffer m_edge_buffer;
976 };
979
981 inline void UVFaceBuffer::Edge::Buffer::Add( const Edge::VertexPair& vertex_pair, const Face::Buffer::Index& index ) {
982 for ( buffer_type::iterator itr = m_buffer.begin(); itr != m_buffer.end(); itr++ ) {
983 if ( *itr == vertex_pair ) { itr->m_owner_faces.Add( index ); return; }
984 }
985 m_buffer.push_back( Edge(vertex_pair, index ) );
986 }
988 }
989
993 #ifdef _DEBUG
995 static const std::vector<char>::size_type GetNameInitialBufferSize = 2;
996 #else
997 static const std::vector<char>::size_type GetNameInitialBufferSize = 32;
998 #endif
999
1002 inline bool DeleteMaterial( const MQDocument doc, const MQMaterial mat ) {
1003 int index = prv_impl::GetIdentifiedIndex(doc, mat);
1004 if ( index < 0 ) return false;
1005 doc->DeleteMaterial(index); return true;
1006 }
1009 inline bool DeleteObject( const MQDocument doc, const MQObject obj ) {
1010 int index = prv_impl::GetIdentifiedIndex(doc, obj);
1011 if ( index < 0 ) return false;
1012 doc->DeleteObject(index); return true;
1013 }
1026 inline std::string GetCountUpCloneableUniqueName( const MQDocument doc, const MQMaterial src, std::vector<char>* const buf = NULL ) {
1027 return prv_impl::GetCountUpCloneableUniqueName(doc,src,buf);
1028 }
1041 inline std::string GetCountUpCloneableUniqueName( const MQDocument doc, const MQObject src, std::vector<char>* const buf = NULL ) {
1042 return prv_impl::GetCountUpCloneableUniqueName(doc,src,buf);
1043 }
1046 inline MQMaterial GetMaterial( const MQDocument doc, const char* name ) { return prv_impl::GetNamed<MQMaterial>( doc, name ); }
1051 inline MQMaterial GetMaterial( const MQDocument doc, const UINT id ) {
1052 #if 0x0310 <= MQPLUGIN_VERSION
1053 if ( doc != NULL ) return doc->GetMaterialFromUniqueID(id);
1054 return NULL;
1055 #else
1056 return prv_impl::GetIdentified<MQMaterial>( doc, id );
1057 #endif
1058 }
1059
1061 std::string GetMaterialTextureName( const MQMaterial, DWORD );
1063
1065 inline std::string GetMaterialAlphaName( const MQMaterial mat ) { return GetMaterialTextureName(mat,MQMAPPING_ALPHA); }
1067 inline std::string GetMaterialBumpName( const MQMaterial mat ) { return GetMaterialTextureName(mat,MQMAPPING_BUMP); }
1070 inline int GetMaterialIndex( const MQDocument doc, const char* name ) { return prv_impl::GetNamedIndex<MQMaterial>( doc, name ); }
1073 inline int GetMaterialIndex( const MQDocument doc, const UINT id ) { return prv_impl::GetIdentifiedIndex<MQMaterial>( doc, id ); }
1081 inline std::string GetMaterialTextureName( const MQMaterial mat, const DWORD map_type = MQMAPPING_TEXTURE ) {
1082 if ( mat != NULL )
1083 {
1084 std::vector<char> buf;
1085 prv_impl::GetMaterialTextureName(&buf, mat, map_type);
1086 return std::string(&buf[0]);
1087 }
1088 return "";
1089 }
1092 inline std::string GetName( const MQMaterial mat ){ return prv_impl::GetName( mat ); }
1095 inline std::string GetName( const MQObject obj ){ return prv_impl::GetName( obj ); }
1098 inline MQObject GetObject( const MQDocument doc, const char* name ) { return prv_impl::GetNamed<MQObject>( doc, name ); }
1103 inline MQObject GetObject( const MQDocument doc, const UINT id ) {
1104 #if 0x0310 <= MQPLUGIN_VERSION
1105 if ( doc != NULL ) return doc->GetObjectFromUniqueID(id);
1106 return NULL;
1107 #else
1108 return prv_impl::GetIdentified<MQObject>(doc, id );
1109 #endif
1110 }
1113 inline int GetObjectIndex( const MQDocument doc, const char* name ) { return prv_impl::GetNamedIndex<MQObject>( doc, name ); }
1116 inline int GetObjectIndex( const MQDocument doc, const UINT id ) { return prv_impl::GetIdentifiedIndex<MQObject>(doc, id ); }
1117
1118 #if 0x0310 <= MQPLUGIN_VERSION
1119
1123 inline std::string GetUnusedMaterialName( const MQDocument doc, const char* base_name = NULL ) {
1124 return prv_impl::GetUnusedNameString<MQMaterial>( doc, base_name );
1125 }
1130 inline std::string GetUnusedMaterialName( const MQDocument doc, const MQMaterial base_name_material ) {
1131 if ( base_name_material == NULL ) return prv_impl::GetUnusedNameString<MQMaterial>( doc );
1132 return prv_impl::GetUnusedNameString<MQMaterial>( doc, GetName( base_name_material ).c_str() );
1133 }
1137 inline std::string GetUnusedObjectName( const MQDocument doc, const char* base_name = NULL ) {
1138 return prv_impl::GetUnusedNameString<MQObject>( doc, base_name );
1139 }
1144 inline std::string GetUnusedObjectName( const MQDocument doc, const MQObject base_name_object ) {
1145 if ( base_name_object == NULL ) return prv_impl::GetUnusedNameString<MQMaterial>( doc );
1146 return prv_impl::GetUnusedNameString<MQMaterial>( doc, GetName( base_name_object ).c_str() );
1147 }
1148
1149 #endif
1150
1152
1154
1155 namespace prv_impl {}; // kill prv_impl access ( to private header implement trap )
1156 };
1157
1158 #endif