Free Electron
SurfaceAccessorMaya.h
Go to the documentation of this file.
1 /* Copyright (C) 2003-2021 Free Electron Organization
2  Any use of this software requires a license. If a valid license
3  was not distributed with this file, visit freeelectron.org. */
4 
5 /** @file */
6 
7 #ifndef __maya_SurfaceAccessorMaya_h__
8 #define __maya_SurfaceAccessorMaya_h__
9 
10 #define FE_SAM_BLIND_DEBUG FALSE
11 
12 namespace fe
13 {
14 namespace ext
15 {
16 
17 // NOTE Maya normals are JIT, not threadsafe to read unless all preread
18 // NOTE setVertexNormal appears to never be threadsafe
19 
20 // NOTE MSpace::kWorld requires a MFnMesh created from a DagPath, not data
21 
22 /**************************************************************************//**
23  @brief Maya Surface Editing Implementation
24 
25  @ingroup maya
26 
27  Currently, this only supports poly meshes.
28  We need to add NURBS support here or in a different class.
29 *//***************************************************************************/
30 class FE_DL_EXPORT SurfaceAccessorMaya:
31  public SurfaceAccessorBase,
32  public CastableAs<SurfaceAccessorMaya>
33 {
34  public:
35 
36  enum PolyFormat
37  {
38  e_unknown,
39  e_closedPoly,
40  e_openPoly,
41  e_freePoint
42  };
43  SurfaceAccessorMaya(void):
44  m_markPoly(0),
45  m_markVertex(0),
46  m_markRawVertex(0),
47  m_pFnMesh(NULL),
48  m_blindDataID(-1),
49  m_polyFormatID(-1),
50  m_pGroupIt(NULL),
51  m_pStringCache(NULL),
52  m_pIntegerCache(NULL),
53  m_pRealCache(NULL),
54  m_pSpatialVectorCache(NULL),
55  m_pBooleanCache(NULL)
56  { setName("SurfaceAccessorMaya"); }
57 virtual ~SurfaceAccessorMaya(void)
58  {
59  if(m_pSpatialVectorCache)
60  {
61  if(m_attribute==SurfaceAccessibleI::e_normal)
62  {
63  MVectorArray normalArray;
64  MIntArray faceList;
65  MIntArray vertexList;
66 
67  const U32 normalCount=
68  m_faceVertTable.size();
69  for(U32 normalIndex=0;
70  normalIndex<normalCount;
71  normalIndex++)
72  {
73  if(!m_pBooleanCache)
74  {
75  continue;
76  }
77  SpatialVector normal;
78  if(m_useTransform)
79  {
80  normal=m_pSpatialVectorCache
81  [normalIndex];
82  }
83  else
84  {
85  rotateVector(m_inverse,
86  m_pSpatialVectorCache
87  [normalIndex],normal);
88  }
89  const MVector vector(normal[0],
90  normal[1],normal[2]);
91 
92  Array<FaceVert>& rFaceVertArray=
93  m_faceVertTable[normalIndex];
94  const U32 faceVertCount=
95  rFaceVertArray.size();
96  for(U32 faceVertIndex=0;
97  faceVertIndex<faceVertCount;
98  faceVertIndex++)
99  {
100  FaceVert& faceVert=rFaceVertArray
101  [faceVertIndex];
102  normalArray.append(vector);
103  faceList.append(faceVert.m_face);
104  vertexList.append(normalIndex);
105  }
106  }
107 // MStatus status=
108  m_pFnMesh->setFaceVertexNormals(
109  normalArray,faceList,vertexList);
110  }
111 
112  delete[] m_pSpatialVectorCache;
113  }
114  if(m_pBooleanCache)
115  {
116  delete[] m_pBooleanCache;
117  }
118  if(m_pRealCache)
119  {
120  delete[] m_pRealCache;
121  }
122  if(m_pIntegerCache)
123  {
124  delete[] m_pIntegerCache;
125  }
126  if(m_pStringCache)
127  {
128  delete[] m_pStringCache;
129  }
130  if(m_pFnMesh)
131  {
132  delete m_pFnMesh;
133  }
134  }
135 
136  using SurfaceAccessorBase::set;
137  using SurfaceAccessorBase::append;
138  using SurfaceAccessorBase::spatialVector;
139 
140  BWORD bind(SurfaceAccessibleI::Element a_element,
141  SurfaceAccessibleI::Attribute a_attribute)
142  {
143  FEASSERT(m_pFnMesh);
144 
145  m_attribute=a_attribute;
146  if(a_attribute==SurfaceAccessibleI::e_vertices ||
147  a_attribute==
148  SurfaceAccessibleI::e_properties)
149  {
150  FEASSERT(a_element==
151  SurfaceAccessibleI::e_primitive);
152  m_element=a_element;
153  return TRUE;
154  }
155 
156  return bindInternal(a_element,String());
157  }
158  BWORD bind(SurfaceAccessibleI::Element a_element,
159  const String& a_name)
160  {
161  FEASSERT(m_pFnMesh);
162 
163  String rename=a_name;
164  String textureName;
165 
166  m_attribute=SurfaceAccessibleI::e_generic;
167 
168  if(a_name=="P")
169  {
170  m_attribute=SurfaceAccessibleI::e_position;
171  }
172  else if(a_name=="N")
173  {
174  m_attribute=SurfaceAccessibleI::e_normal;
175  }
176  else if(a_name=="uv")
177  {
178  m_attribute=SurfaceAccessibleI::e_uv;
179  }
180  else if(a_name=="Cd")
181  {
182  m_attribute=SurfaceAccessibleI::e_color;
183  }
184  else if(a_element==SurfaceAccessibleI::e_point &&
185  a_name.match("[A-z0-9_]+\\.[A-z0-9_]+"))
186  {
187  textureName=a_name;
188 
189  m_attribute=SurfaceAccessibleI::e_uv;
190  rename="uv";
191  }
192 
193  if(!bindInternal(a_element,rename))
194  {
195  return FALSE;
196  }
197 
198  if(!textureName.empty())
199  {
200  cacheTexture(textureName);
201  }
202 
203  return TRUE;
204  }
205 
206  //* as SurfaceAccessorI
207 
208 virtual String type(void) const;
209 virtual U32 count(void) const
210  {
211  FEASSERT(m_pFnMesh);
212 
213  switch(m_element)
214  {
215  case SurfaceAccessibleI::e_point:
216  return vertexCount();
217 
218 // case SurfaceAccessibleI::e_vertex:
219 // return 0;
220 
221  case SurfaceAccessibleI::e_primitive:
222  return m_pFnMesh->numPolygons();
223 
224  case SurfaceAccessibleI::e_detail:
225  return 1;
226 
227  case SurfaceAccessibleI::e_pointGroup:
228  return (m_attrName=="")?
229  vertexCount():
230  m_groupList.size();
231 
232  case SurfaceAccessibleI::e_primitiveGroup:
233  return (m_attrName=="")?
234  m_pFnMesh->numPolygons():
235  m_groupList.size();
236 
237  default:
238  ;
239  }
240  return 0;
241  }
242 
243 virtual U32 subCount(U32 a_index) const
244  {
245  FEASSERT(m_pFnMesh);
246 
247  if(m_element==SurfaceAccessibleI::e_primitiveGroup
248  && m_attrName!="")
249  {
250  if(a_index>=m_groupList.size())
251  {
252  return 0;
253  }
254  return polyVertCount(m_groupList[a_index]);
255  }
256  else if(m_element==
257  SurfaceAccessibleI::e_primitiveGroup ||
258  m_attribute==SurfaceAccessibleI::e_vertices)
259  {
260  FEASSERT(m_element==
261  SurfaceAccessibleI::e_primitive ||
262  m_element==
263  SurfaceAccessibleI::e_primitiveGroup);
264 
265  return polyVertCount(a_index);
266  }
267 
268  return 1;
269  }
270 
271 virtual void set(U32 a_index,U32 a_subIndex,String a_string)
272  {
273  FEASSERT(m_pFnMesh);
274 
275  if(m_element==SurfaceAccessibleI::e_detail)
276  {
277  setDetail(m_attrName,a_string);
278  return;
279  }
280 
281  if(m_spSurfaceAccessibleI.isValid())
282  {
283  m_spSurfaceAccessibleI->lock(I64(this));
284  }
285 
286  assureBlindDataID("string");
287 
288  const I32 compID=rawVertex(a_index);
289  const MFn::Type component=componentType();
290  MStatus status=m_pFnMesh->setStringBlindData(
291  compID,
292  component,
293  m_blindDataID,
294  m_attrName.c_str(),
295  a_string.c_str());
296 
297  if(m_spSurfaceAccessibleI.isValid())
298  {
299  m_spSurfaceAccessibleI->unlock(I64(this));
300  }
301 
302  if(!status)
303  {
304  feLog("SurfaceAccessorMaya::set(... String)"
305  " index %d raw %d"
306  " setStringBlindData failed\n",
307  a_index, compID);
308  }
309 
310  if(m_pStringCache)
311  {
312  m_pStringCache[a_index]=a_string;
313  }
314  }
315 virtual String string(U32 a_index,U32 a_subIndex=0)
316  {
317  FEASSERT(m_pFnMesh);
318 
319  if(m_element==SurfaceAccessibleI::e_detail)
320  {
321  return getDetail(m_attrName);
322  }
323 
324  if(m_pStringCache)
325  {
326  return m_pStringCache[a_index];
327  }
328 
329  if(m_attrName==".shader")
330  {
331  cacheShaders();
332  return m_pStringCache[a_index];
333  }
334 
335  checkBlindDataID("string");
336 
337  if(!m_pFnMesh->isBlindDataTypeUsed(m_blindDataID))
338  {
339 #if FE_SAM_BLIND_DEBUG
340  feLog("SurfaceAccessorMaya::string"
341  " \"%s\" blind data %d not used\n",
342  m_attrName.c_str(),m_blindDataID);
343 #endif
344  return "";
345  }
346  const MFn::Type component=componentType();
347  if(!m_pFnMesh->hasBlindData(component))
348  {
349 #if FE_SAM_BLIND_DEBUG
350  feLog("SurfaceAccessorMaya::string"
351  " no component blind data\n");
352 #endif
353  return "";
354  }
355  const I32 compID=rawVertex(a_index);
356  if(!m_pFnMesh->hasBlindDataComponentId(compID,
357  component))
358  {
359 #if FE_SAM_BLIND_DEBUG
360  feLog("SurfaceAccessorMaya::string"
361  " no blind data on"
362  " index %d compID %d\n",a_index,compID);
363 #endif
364  return "";
365  }
366 
367  const I32 size=count();
368 
369  MIntArray compIDs;
370  MStringArray data;
371  MStatus status=m_pFnMesh->getStringBlindData(
372  component,
373  m_blindDataID,
374  m_attrName.c_str(),
375  compIDs,
376  data);
377  if(!status)
378  {
379  feLog("SurfaceAccessorMaya::integer"
380  " getStringBlindData failed\n");
381  return "";
382  }
383 
384  //* TODO reverse lookup for curves
385 
386  m_pStringCache=new String[size];
387  for(I32 m=0;m<size;m++)
388  {
389  m_pStringCache[m]="";
390  }
391 
392  const I32 found=compIDs.length();
393  for(I32 m=0;m<found;m++)
394  {
395  FEASSERT(compIDs[m]<size);
396  m_pStringCache[compIDs[m]]=data[m].asChar();
397  }
398 
399  return m_pStringCache[a_index];
400  }
401 
402 virtual void set(U32 a_index,U32 a_subIndex,I32 a_integer)
403  {
404  FEASSERT(m_pFnMesh);
405 
406  if(m_element==SurfaceAccessibleI::e_detail)
407  {
408  String text;
409  text.sPrintf("%d",a_integer);
410  setDetail(m_attrName,text);
411  return;
412  }
413 
414  if(m_spSurfaceAccessibleI.isValid())
415  {
416  m_spSurfaceAccessibleI->lock(I64(this));
417  }
418 
419 #if FALSE
420  const BWORD useBool=
421  (m_element==
422  SurfaceAccessibleI::e_pointGroup ||
423  m_element==
424  SurfaceAccessibleI::e_primitiveGroup);
425 #else
426  const BWORD useBool=FALSE;
427 #endif
428 
429  assureBlindDataID(useBool? "boolean": "integer");
430 
431  const I32 compID=rawVertex(a_index);
432  const MFn::Type component=componentType();
433 
434  if(useBool)
435  {
436  const bool data=a_integer;
437  MStatus status=m_pFnMesh->setBoolBlindData(
438  compID,
439  component,
440  m_blindDataID,
441  m_attrName.c_str(),
442  data);
443  if(!status)
444  {
445  feLog("SurfaceAccessorMaya::set(... I32)"
446  " index %d raw %d"
447  " setBoolBlindData failed\n",
448  a_index, compID);
449  }
450  }
451  else
452  {
453  const I32 data=a_integer;
454  MStatus status=m_pFnMesh->setIntBlindData(
455  compID,
456  component,
457  m_blindDataID,
458  m_attrName.c_str(),
459  data);
460  if(!status)
461  {
462  feLog("SurfaceAccessorMaya::set(... I32)"
463  " index %d raw %d"
464  " setIntBlindData failed\n",
465  a_index, compID);
466  }
467  }
468 
469  if(m_spSurfaceAccessibleI.isValid())
470  {
471  m_spSurfaceAccessibleI->unlock(I64(this));
472  }
473 
474  if(m_attrName=="POLY_FORMAT")
475  {
476  m_cachePolyFormat=PolyFormat(a_integer);
477  }
478 
479  if(m_pIntegerCache)
480  {
481  m_pIntegerCache[a_index]=a_integer;
482  }
483  }
484 virtual I32 integer(U32 a_index,U32 a_subIndex=0)
485  {
486  FEASSERT(m_pFnMesh);
487 
488  if(m_element==SurfaceAccessibleI::e_detail)
489  {
490  return getDetail(m_attrName).integer();
491  }
492 
493  if(m_pIntegerCache)
494  {
495  return m_pIntegerCache[a_index];
496  }
497 
498  const BWORD isGroup=
499  (m_element==
500  SurfaceAccessibleI::e_pointGroup ||
501  m_element==
502  SurfaceAccessibleI::e_primitiveGroup);
503 #if FALSE
504  const BWORD useBool=isGroup;
505 #else
506  const BWORD useBool=FALSE;
507 #endif
508 
509  checkBlindDataID(useBool? "boolean": "integer");
510 
511  if(isGroup && m_groupList.size())
512  {
513  FEASSERT(a_index<m_groupList.size());
514  return (a_index>=m_groupList.size())?
515  0: m_groupList[a_index];
516  }
517 
518  if(m_element==
519  SurfaceAccessibleI::e_primitiveGroup ||
520  m_attribute==SurfaceAccessibleI::e_vertices)
521  {
522  FEASSERT(m_element==
523  SurfaceAccessibleI::e_primitive ||
524  m_element==
525  SurfaceAccessibleI::e_primitiveGroup);
526 
527  I32 primitiveIndex=a_index;
528  if(m_element==
529  SurfaceAccessibleI::e_primitiveGroup &&
530  m_attrName!="")
531  {
532  FEASSERT(a_index<m_groupList.size());
533  if(a_index>=m_groupList.size())
534  {
535  return 0;
536  }
537  primitiveIndex=m_groupList[a_index];
538  }
539 
540  U32 subs=m_pFnMesh->polygonVertexCount(
541  primitiveIndex);
542  FEASSERT(a_subIndex<subs);
543  if(a_subIndex>=subs)
544  {
545  return 0;
546  }
547 
548  MIntArray vertexList;
549 // MStatus status=
550  m_pFnMesh->getPolygonVertices(
551  primitiveIndex,vertexList);
552 
553  const U32 raw=vertexList[a_subIndex];
554 
555  return logicalVertex(raw);
556  }
557 
558  if(m_attribute==SurfaceAccessibleI::e_properties)
559  {
560  FEASSERT(m_element==
561  SurfaceAccessibleI::e_primitive ||
562  m_element==
563  SurfaceAccessibleI::e_primitiveGroup);
564 
565  const PolyFormat format=polyFormat(a_index);
566  return format==e_openPoly;
567  }
568 
569  if(!m_pFnMesh->isBlindDataTypeUsed(m_blindDataID))
570  {
571 #if FE_SAM_BLIND_DEBUG
572  feLog("SurfaceAccessorMaya::integer"
573  " \"%s\" blind data %d not used\n",
574  m_attrName.c_str(),m_blindDataID);
575 #endif
576  return 0;
577  }
578  const MFn::Type component=componentType();
579  if(!m_pFnMesh->hasBlindData(component))
580  {
581 #if FE_SAM_BLIND_DEBUG
582  feLog("SurfaceAccessorMaya::integer"
583  " no component blind data\n");
584 #endif
585  return 0;
586  }
587  const I32 compID=rawVertex(a_index);
588  if(!m_pFnMesh->hasBlindDataComponentId(compID,
589  component))
590  {
591 #if FE_SAM_BLIND_DEBUG
592  feLog("SurfaceAccessorMaya::integer"
593  " no blind data on"
594  " index %d compID %d\n",a_index,compID);
595 #endif
596  return 0;
597  }
598 #if FALSE
599  //* NOTE very very slow
600  int data;
601  MStatus status=m_pFnMesh->getIntBlindData(
602  rawVertex(a_index),
603  component,
604  m_blindDataID,
605  m_attrName.c_str(),
606  data);
607  if(!status)
608  {
609  feLog("SurfaceAccessorMaya::integer"
610  " getIntBlindData failed\n");
611  return 0;
612  }
613  return data;
614 #else
615  const I32 size=count();
616 
617  MIntArray compIDs;
618  MIntArray data;
619  if(useBool)
620  {
621  MStatus status=m_pFnMesh->getBoolBlindData(
622  component,
623  m_blindDataID,
624  m_attrName.c_str(),
625  compIDs,
626  data);
627  if(!status)
628  {
629  feLog("SurfaceAccessorMaya::integer"
630  " getBoolBlindData failed\n");
631  return 0;
632  }
633  }
634  else
635  {
636  MStatus status=m_pFnMesh->getIntBlindData(
637  component,
638  m_blindDataID,
639  m_attrName.c_str(),
640  compIDs,
641  data);
642  if(!status)
643  {
644  feLog("SurfaceAccessorMaya::integer"
645  " getIntBlindData failed\n");
646  return 0;
647  }
648  }
649 
650  m_pIntegerCache=new I32[size];
651  for(I32 m=0;m<size;m++)
652  {
653  m_pIntegerCache[m]=0;
654  }
655 
656  const I32 found=compIDs.length();
657  for(I32 m=0;m<found;m++)
658  {
659  const I32 rawIndex=compIDs[m];
660  FEASSERT(rawIndex>=0);
661 
662  const I32 index=
663  logicalVertex(rawIndex);
664 
665  FEASSERT(index<size);
666  m_pIntegerCache[index]=data[m];
667  }
668 
669  return m_pIntegerCache[a_index];
670 #endif
671  }
672 virtual I32 duplicate(U32 index,U32 subIndex=0)
673  {
674  //* TODO
675  return -1;
676  }
677 virtual I32 append(SurfaceAccessibleI::Form a_form)
678  {
679  if(m_element==SurfaceAccessibleI::e_point)
680  {
681  //* HACK doesn't work
682  return -1;
683 
684  //* NOTE can be very inefficient
685  //* TODO resize all at once?
686 
687  const MPoint origin(0.0,0.0,0.0);
688 
689  MPointArray vertexArray;
690  m_pFnMesh->getPoints(vertexArray);
691 
692  feLog("SurfaceAccessorMaya::append was %d\n",
693  vertexArray.length());
694 
695 #if TRUE
696  vertexArray.append(origin);
697 
698  m_pFnMesh->setPoints(vertexArray);
699 #else
700  const int vertexId=count();
701  m_pFnMesh->setPoint(vertexId,origin);
702 #endif
703 
704  feLog("SurfaceAccessorMaya::append now %d\n",
705  count());
706 
707  return count()-1;
708  }
709 
710  if(m_element==SurfaceAccessibleI::e_primitive)
711  {
712  const bool mergeVertices=false;
713 
714  MPointArray vertexArray;
715  m_pFnMesh->addPolygon(
716  (const MPointArray&)vertexArray,
717  mergeVertices);
718 
719  return count()-1;
720  }
721 
722  return -1;
723  }
724 virtual I32 append(I32 a_integer,SurfaceAccessibleI::Form a_form)
725  {
726  if(m_element!=SurfaceAccessibleI::e_primitive ||
727  m_attribute!=SurfaceAccessibleI::e_vertices)
728  {
729  append(U32(0),a_integer);
730  return 0;
731  }
732 
733  /*** append a primitive with the specified
734  number of vertices */
735  MPointArray vertexArray;
736  vertexArray.setLength(a_integer);
737 
738  //* default of non-coincident non-linear points
739  for(I32 vertIndex=0;vertIndex<a_integer;vertIndex++)
740  {
741  vertexArray.set(vertIndex,0.01*vertIndex,0.0,
742  0.001*vertIndex*vertIndex);
743  }
744 
745  const bool mergeVertices=false;
746  m_pFnMesh->addPolygon(
747  (const MPointArray&)vertexArray,
748  mergeVertices);
749 
750  return m_pFnMesh->numPolygons()-1;
751  }
752 virtual void append(U32 a_index,I32 a_integer)
753  {
754  if(m_element==SurfaceAccessibleI::e_pointGroup ||
755  m_element==
756  SurfaceAccessibleI::e_primitiveGroup)
757  {
758  // a_index ignored
759 
760  set(a_integer,U32(0),I32(true));
761 
762  for(U32 m=0;m<m_groupList.size();m++)
763  {
764  if(m_groupList[m]==a_integer)
765  {
766  return;
767  }
768  }
769  m_groupList.push_back(a_integer);
770  }
771  }
772 
773 virtual void append(Array< Array<I32> >& a_rPrimVerts);
774 
775 virtual void remove(U32 a_index,I32 a_integer)
776  {
777  if(m_element==SurfaceAccessibleI::e_pointGroup ||
778  m_element==
779  SurfaceAccessibleI::e_primitiveGroup)
780  {
781  set(a_index,U32(0),I32(false));
782  for(U32 m=0;m<m_groupList.size();m++)
783  {
784  if(m_groupList[m]==I32(a_index))
785  {
786  m_groupList.erase(
787  m_groupList.begin()+m);
788  }
789  }
790  }
791  }
792 
793 virtual void set(U32 a_index,U32 a_subIndex,Real a_real)
794  {
795  FEASSERT(m_pFnMesh);
796 
797  if(m_element==SurfaceAccessibleI::e_detail)
798  {
799  String text;
800  text.sPrintf("%.8G",a_real);
801  setDetail(m_attrName,text);
802  return;
803  }
804 
805  if(m_element==SurfaceAccessibleI::e_detail)
806  {
807  //* try getting existing attribute
808  MStatus status;
809  MPlug plug=m_pFnMesh->findPlug(
810  m_attrName.c_str(),status);
811 
812  if(status && !plug.isNull())
813  {
814  plug.setDouble(a_real);
815  return;
816  }
817 
818  //* create missing attribute
819  MFnNumericAttribute numAttr;
820  MObject attrObject=numAttr.create(
821  m_attrName.c_str(),m_attrName.c_str(),
822  MFnNumericData::kDouble,a_real,&status);
823  if(!status)
824  {
825  feLog("SurfaceAccessorMaya::set(... Real)"
826  " index %d failed to create"
827  " detail attribute \"%s\""
828  " because \"%s\"\n",
829  a_index,m_attrName.c_str(),
830  status.errorString().asChar());
831  }
832 
833  status=m_pFnMesh->addAttribute(attrObject,
834  MFnDependencyNode::kLocalDynamicAttr);
835  if(!status)
836  {
837  feLog("SurfaceAccessorMaya::set(... Real)"
838  " index %d failed to add"
839  " detail attribute \"%s\""
840  " because \"%s\"\n",
841  a_index,m_attrName.c_str(),
842  status.errorString().asChar());
843  }
844 
845  return;
846  }
847 
848  if(m_spSurfaceAccessibleI.isValid())
849  {
850  m_spSurfaceAccessibleI->lock(I64(this));
851  }
852 
853  assureBlindDataID("real");
854 
855  const I32 compID=rawVertex(a_index);
856 
857  const double data=a_real;
858  const MFn::Type component=componentType();
859  MStatus status=m_pFnMesh->setDoubleBlindData(
860  compID,
861  component,
862  m_blindDataID,
863  m_attrName.c_str(),
864  data);
865 
866  if(m_spSurfaceAccessibleI.isValid())
867  {
868  m_spSurfaceAccessibleI->unlock(I64(this));
869  }
870 
871  if(!status)
872  {
873  feLog("SurfaceAccessorMaya::set(... Real)"
874  " index %d compID %d"
875  " setDoubleBlindData failed:"
876  " \"%s\"\n",
877  a_index, compID,
878  status.errorString().asChar());
879  }
880 
881  if(m_pRealCache)
882  {
883  m_pRealCache[a_index]=a_real;
884  }
885  }
886 virtual Real real(U32 a_index,U32 a_subIndex=0)
887  {
888  FEASSERT(m_pFnMesh);
889 
890  if(m_element==SurfaceAccessibleI::e_detail)
891  {
892  return getDetail(m_attrName).real();
893  }
894 
895  if(m_pRealCache)
896  {
897  return m_pRealCache[a_index];
898  }
899 
900  checkBlindDataID("real");
901 
902  if(!m_pFnMesh->isBlindDataTypeUsed(m_blindDataID))
903  {
904 #if FE_SAM_BLIND_DEBUG
905  feLog("SurfaceAccessorMaya::real"
906  " \"%s\" blind data %d not used\n",
907  m_attrName.c_str(),m_blindDataID);
908 #endif
909  return 0.0;
910  }
911 
912  const MFn::Type component=componentType();
913  if(!m_pFnMesh->hasBlindData(component))
914  {
915 #if FE_SAM_BLIND_DEBUG
916  feLog("SurfaceAccessorMaya::real"
917  " no component blind data\n");
918 #endif
919  return 0.0;
920  }
921 
922  const I32 compID=rawVertex(a_index);
923  if(!m_pFnMesh->hasBlindDataComponentId(compID,
924  component))
925  {
926 #if FE_SAM_BLIND_DEBUG
927  feLog("SurfaceAccessorMaya::real"
928  " no blind data on"
929  " index %d compID %d\n",a_index,compID);
930 #endif
931  return 0.0;
932  }
933 
934  const I32 size=count();
935 
936  MIntArray compIDs;
937  MDoubleArray data;
938  MStatus status=m_pFnMesh->getDoubleBlindData(
939  component,
940  m_blindDataID,
941  m_attrName.c_str(),
942  compIDs,
943  data);
944  if(!status)
945  {
946  feLog("SurfaceAccessorMaya::real"
947  " getDoubleBlindData failed\n");
948  return 0.0;
949  }
950 
951  m_pRealCache=new Real[size];
952  for(I32 m=0;m<size;m++)
953  {
954  m_pRealCache[m]=Real(0);
955  }
956 
957  const I32 found=compIDs.length();
958  for(I32 m=0;m<found;m++)
959  {
960  const I32 rawIndex=compIDs[m];
961  FEASSERT(rawIndex>=0);
962 
963  const I32 index=
964  logicalVertex(rawIndex);
965 
966  FEASSERT(index<size);
967  m_pRealCache[index]=data[m];
968  }
969 
970  return m_pRealCache[a_index];
971  }
972 
973 virtual void set(U32 a_index,U32 a_subIndex,
974  const SpatialVector& a_vector)
975  {
976  FEASSERT(m_pFnMesh);
977 
978  if(m_element==SurfaceAccessibleI::e_detail)
979  {
980  String text;
981  text.sPrintf("%.8G %.8G %.8G",
982  a_vector[0],a_vector[1],a_vector[2]);
983  setDetail(m_attrName,text);
984  return;
985  }
986 
987 #if FALSE
988  if(m_element==SurfaceAccessibleI::e_detail)
989  {
990  //* try getting existing attribute
991  MStatus status;
992  MPlug plug=m_pFnMesh->findPlug(
993  m_attrName.c_str(),status);
994 
995  if(status && !plug.isNull())
996  {
997  const U32 size=plug.numElements();
998  FEASSERT(size==3);
999  for(U32 m=0;m<size && m<3;m++)
1000  {
1001  plug[m].setDouble(a_vector[m]);
1002  }
1003  return;
1004  }
1005 
1006  //* create missing attribute
1007  MFnNumericAttribute numAttr;
1008  MObject attrObject=numAttr.create(
1009  m_attrName.c_str(),m_attrName.c_str(),
1010  MFnNumericData::k3Double,0,&status);
1011  if(!status)
1012  {
1013  feLog("SurfaceAccessorMaya::"
1014  "set(... SpatialVector)"
1015  " index %d failed to create"
1016  " detail attribute \"%s\""
1017  " because \"%s\"\n",
1018  a_index,m_attrName.c_str(),
1019  status.errorString().asChar());
1020  }
1021 
1022  numAttr.setDefault((double)a_vector[0],
1023  (double)a_vector[1],
1024  (double)a_vector[2]);
1025 
1026  status=m_pFnMesh->addAttribute(attrObject,
1027  MFnDependencyNode::kLocalDynamicAttr);
1028  if(!status)
1029  {
1030  feLog("SurfaceAccessorMaya::"
1031  "set(... SpatialVector)"
1032  " index %d failed to add"
1033  " detail attribute \"%s\""
1034  " because \"%s\"\n",
1035  a_index,m_attrName.c_str(),
1036  status.errorString().asChar());
1037  }
1038 
1039  return;
1040  }
1041 #endif
1042 
1043  if(m_element==SurfaceAccessibleI::e_pointGroup)
1044  {
1045  if(a_index>=m_groupList.size())
1046  {
1047  return;
1048  }
1049  a_index=m_groupList[a_index];
1050  }
1051  else if(m_element==
1052  SurfaceAccessibleI::e_primitiveGroup ||
1053  m_attribute==SurfaceAccessibleI::e_vertices)
1054  {
1055  if(m_element==
1056  SurfaceAccessibleI::e_primitiveGroup &&
1057  m_attrName!="")
1058  {
1059  if(a_index>=m_groupList.size())
1060  {
1061  return;
1062  }
1063  a_index=m_groupList[a_index];
1064  }
1065 
1066  FEASSERT(m_element==
1067  SurfaceAccessibleI::e_primitive ||
1068  m_element==
1069  SurfaceAccessibleI::e_primitiveGroup);
1070 
1071  const U32 subs=
1072  m_pFnMesh->polygonVertexCount(a_index);
1073  FEASSERT(a_subIndex<subs);
1074  if(a_subIndex>=subs)
1075  {
1076  return;
1077  }
1078 
1079  MIntArray vertexList;
1080  MStatus status=m_pFnMesh->getPolygonVertices(
1081  a_index,vertexList);
1082 
1083  SpatialVector local;
1084  if(m_useTransform)
1085  {
1086  transformVector(m_inverse,a_vector,local);
1087  }
1088  else
1089  {
1090  local=a_vector;
1091  }
1092 
1093  MPoint point(local[0],local[1],local[2]);
1094 
1095  const U32 raw=vertexList[a_subIndex];
1096  status=m_pFnMesh->setPoint(raw,point);
1097 
1098  const PolyFormat format=polyFormat(a_index);
1099  if(format==e_openPoly)
1100  {
1101  const U32 raw2=
1102  vertexList[subs-1-a_subIndex];
1103  status=m_pFnMesh->setPoint(raw2,point);
1104  }
1105  return;
1106  }
1107 
1108  // TODO set color
1109 
1110  if(m_attribute==SurfaceAccessibleI::e_position ||
1111  m_element==SurfaceAccessibleI::e_pointGroup)
1112  {
1113  SpatialVector local;
1114  if(m_useTransform)
1115  {
1116  transformVector(m_inverse,a_vector,local);
1117  }
1118  else
1119  {
1120  local=a_vector;
1121  }
1122 
1123  MPoint point(local[0],local[1],local[2]);
1124 
1125  const U32 raw=rawVertex(a_index);
1126  MStatus status=m_pFnMesh->setPoint(raw,point);
1127  const PolyFormat format=polyFormat(0); // HACK
1128  if(format==e_openPoly)
1129  {
1130  const U32 twin=twinVertex(a_index);
1131  status=m_pFnMesh->setPoint(twin,point);
1132  }
1133  return;
1134  }
1135 
1136  //* TODO verify UV editing
1137 
1138  if(m_element==SurfaceAccessibleI::e_point &&
1139  m_attribute==SurfaceAccessibleI::e_uv)
1140  {
1141  MVector vector;
1142  const U32 raw=rawVertex(a_index);
1143  if(!m_faceVertTable.size())
1144  {
1145  initializeFaceVertArray();
1146  }
1147  Array<FaceVert>& rFaceVertArray=
1148  m_faceVertTable[raw];
1149  const U32 faceVertCount=rFaceVertArray.size();
1150 
1151  for(U32 faceVertIndex=0;
1152  faceVertIndex<faceVertCount;
1153  faceVertIndex++)
1154  {
1155  FaceVert& faceVert=
1156  rFaceVertArray[faceVertIndex];
1157 
1158  I32 uvId=0;
1159  m_pFnMesh->getPolygonUVid(faceVert.m_face,
1160  faceVert.m_vert,uvId);
1161 
1162  m_pFnMesh->setUV(uvId,
1163  a_vector[0],a_vector[1]);
1164  }
1165  return;
1166  }
1167 
1168  if(m_element==SurfaceAccessibleI::e_primitive &&
1169  m_attribute==SurfaceAccessibleI::e_uv)
1170  {
1171  MVector vector;
1172  const U32 raw=rawVertex(a_index);
1173 
1174  I32 uvId=0;
1175  m_pFnMesh->getPolygonUVid(raw,a_subIndex,uvId);
1176 
1177  m_pFnMesh->setUV(uvId,a_vector[0],a_vector[1]);
1178  return;
1179  }
1180 
1181  if(m_element==SurfaceAccessibleI::e_point &&
1182  m_attribute==SurfaceAccessibleI::e_normal)
1183  {
1184  MVector vector(a_vector[0],a_vector[1],
1185  a_vector[2]);
1186 
1187  const U32 raw=rawVertex(a_index);
1188 
1189  MStatus status;
1190 
1191  if(!m_faceVertTable.size())
1192  {
1193  MFloatVectorArray normals;
1194  status=m_pFnMesh->getNormals(normals);
1195  if(!normals.length())
1196  {
1197  feLog("SurfaceAccessorMaya::set"
1198  " (vector3)"
1199  " no normals (%d points)\n",
1200  count());
1201  return;
1202  }
1203 
1204  initializeFaceVertArray();
1205 
1206 // MPointArray vertexArray;
1207 // m_pFnMesh->getPoints(vertexArray);
1208 
1209  const U32 normalCount=
1210  m_faceVertTable.size();
1211 
1212 // feLog("SurfaceAccessorMaya::set (vector3)"
1213 // " normalCount %d %d\n",
1214 // normalCount,normals.length());
1215 
1216  m_pSpatialVectorCache=
1217  new SpatialVector[normalCount];
1218  m_pBooleanCache=
1219  new BWORD[normalCount];
1220  if(m_useTransform)
1221  {
1222  for(U32 normalIndex=0;
1223  normalIndex<normalCount;
1224  normalIndex++)
1225  {
1226  MFloatVector& normal=
1227  normals[normalIndex];
1228  rotateVector(m_transform,
1229  SpatialVector(
1230  normal[0],normal[1],
1231  normal[2]),
1232  m_pSpatialVectorCache
1233  [normalIndex]);
1234 
1235  m_pBooleanCache[normalIndex]=FALSE;
1236  }
1237  }
1238  else
1239  {
1240  for(U32 normalIndex=0;
1241  normalIndex<normalCount;
1242  normalIndex++)
1243  {
1244  MFloatVector& normal=
1245  normals[normalIndex];
1246  m_pSpatialVectorCache[normalIndex]=
1247  SpatialVector(normal[0],
1248  normal[1],normal[2]);
1249 
1250  m_pBooleanCache[normalIndex]=FALSE;
1251  }
1252  }
1253  }
1254 
1255  FEASSERT(raw<m_faceVertTable.size());
1256  m_pSpatialVectorCache[raw]=a_vector;
1257  m_pBooleanCache[raw]=TRUE;
1258 
1259  return;
1260  }
1261 
1262  if(m_spSurfaceAccessibleI.isValid())
1263  {
1264  m_spSurfaceAccessibleI->lock(I64(this));
1265  }
1266 
1267  assureBlindDataID("vector3");
1268 
1269  MPoint point(a_vector[0],a_vector[1],a_vector[2]);
1270 
1271  I32 compID=rawVertex(a_index);
1272  for(U32 n=0;n<3;n++)
1273  {
1274  const double data=point[n];
1275  String name;
1276  name.sPrintf("%s_%c",m_attrName.c_str(),'x'+n);
1277 
1278  const MFn::Type component=componentType();
1279  MStatus status=m_pFnMesh->setDoubleBlindData(
1280  compID,
1281  component,
1282  m_blindDataID,
1283  name.c_str(),
1284  data);
1285  if(!status)
1286  {
1287  feLog("SurfaceAccessorMaya::set"
1288  "(... SpatialVector)"
1289  " index %d %d compID %d"
1290  " setDoubleBlindData failed:"
1291  " \"%s\"\n",
1292  a_index,n,compID,
1293  status.errorString().asChar());
1294  }
1295  }
1296 
1297  if(m_spSurfaceAccessibleI.isValid())
1298  {
1299  m_spSurfaceAccessibleI->unlock(I64(this));
1300  }
1301 
1302  if(m_pSpatialVectorCache)
1303  {
1304  m_pSpatialVectorCache[a_index]=a_vector;
1305  }
1306  }
1307 virtual SpatialVector spatialVector(U32 a_index,U32 a_subIndex=0)
1308  {
1309  FEASSERT(m_pFnMesh);
1310 
1311  if(m_element==SurfaceAccessibleI::e_detail)
1312  {
1313  const String text=getDetail(m_attrName);
1314 
1315  float x,y,z;
1316  sscanf(text.c_str(),"%f %f %f",&x,&y,&z);
1317 
1318  return SpatialVector(x,y,z);
1319  }
1320 
1321  if(m_pSpatialVectorCache)
1322  {
1323  return m_pSpatialVectorCache[a_index];
1324  }
1325 
1326  MPoint point;
1327 
1328  if(m_element==SurfaceAccessibleI::e_pointGroup)
1329  {
1330  if(a_index>=m_groupList.size())
1331  {
1332  return SpatialVector(0.0,0.0,0.0);
1333  }
1334  const U32 raw=rawVertex(m_groupList[a_index]);
1335 
1336 // MStatus status=
1337  m_pFnMesh->getPoint(raw,point);
1338  }
1339  else if(m_element==
1340  SurfaceAccessibleI::e_primitiveGroup ||
1341  m_attribute==SurfaceAccessibleI::e_vertices)
1342  {
1343  if(m_element==
1344  SurfaceAccessibleI::e_primitiveGroup &&
1345  m_attrName!="")
1346  {
1347  if(a_index>=m_groupList.size())
1348  {
1349  return SpatialVector(0.0,0.0,0.0);
1350  }
1351  a_index=m_groupList[a_index];
1352  }
1353 
1354  FEASSERT(m_element==
1355  SurfaceAccessibleI::e_primitive ||
1356  m_element==
1357  SurfaceAccessibleI::e_primitiveGroup);
1358 
1359  const U32 subs=
1360  m_pFnMesh->polygonVertexCount(a_index);
1361  FEASSERT(a_subIndex<subs);
1362  if(a_subIndex>=subs)
1363  {
1364  return SpatialVector(0.0,0.0,0.0);
1365  }
1366 
1367  MIntArray vertexList;
1368  MStatus status=m_pFnMesh->getPolygonVertices(
1369  a_index,vertexList);
1370 
1371  const U32 raw=vertexList[a_subIndex];
1372  status=m_pFnMesh->getPoint(raw,point);
1373  }
1374  else if(m_attribute==SurfaceAccessibleI::e_position)
1375  {
1376  const U32 raw=rawVertex(a_index);
1377 // MStatus status=
1378  m_pFnMesh->getPoint(raw,point);
1379  }
1380  else if(m_element==SurfaceAccessibleI::e_point &&
1381  (m_attribute==SurfaceAccessibleI::e_normal
1382  || m_attribute==SurfaceAccessibleI::e_uv))
1383  {
1384  MVector vector;
1385  const U32 raw=rawVertex(a_index);
1386  if(!m_faceVertTable.size())
1387  {
1388  initializeFaceVertArray();
1389  }
1390  Array<FaceVert>& rFaceVertArray=
1391  m_faceVertTable[raw];
1392  const U32 faceVertCount=rFaceVertArray.size();
1393  if(!faceVertCount)
1394  {
1395  return SpatialVector(0.0,0.0,0.0);
1396  }
1397 
1398  //* NOTE only looking at the first
1399  FaceVert& faceVert=rFaceVertArray[0];
1400 
1401  if(m_attribute==SurfaceAccessibleI::e_uv)
1402  {
1403  I32 uvId=0;
1404  m_pFnMesh->getPolygonUVid(faceVert.m_face,
1405  faceVert.m_vert,uvId);
1406 
1407  float u=0.0;
1408  float v=0.0;
1409  m_pFnMesh->getUV(uvId,u,v);
1410 
1411  return SpatialVector(u,v,0.0);
1412  }
1413 
1414 // MStatus status=
1415  m_pFnMesh->getFaceVertexNormal(
1416  faceVert.m_face,raw,vector);
1417 
1418  if(!m_useTransform)
1419  {
1420  return SpatialVector(vector[0],
1421  vector[1],vector[2]);
1422  }
1423 
1424  SpatialVector world;
1425  rotateVector(m_transform,
1426  SpatialVector(vector[0],
1427  vector[1],vector[2]),world);
1428  return world;
1429  }
1430 // else if(m_element==SurfaceAccessibleI::e_point &&
1431 // m_attribute==SurfaceAccessibleI::e_uv)
1432 // {
1433 // const U32 raw=rawVertex(a_index);
1434 // MStatus status=m_pFnMesh->getPoint(raw,point);
1435 //
1436 // //* NOTE don't know which polygon (arbitrary)
1437 // float2 uvPoint;
1438 // status=m_pFnMesh->getUVAtPoint(point,uvPoint);
1439 //
1440 // return SpatialVector(uvPoint[0],uvPoint[1],0.0);
1441 // }
1442  else if(m_element==SurfaceAccessibleI::e_primitive
1443  && m_attribute==SurfaceAccessibleI::e_uv)
1444  {
1445  MVector vector;
1446  const U32 raw=rawVertex(a_index);
1447 
1448  I32 uvId=0;
1449  m_pFnMesh->getPolygonUVid(raw,a_subIndex,uvId);
1450 
1451  float u=0.0;
1452  float v=0.0;
1453  m_pFnMesh->getUV(uvId,u,v);
1454 
1455  return SpatialVector(u,v,0.0);
1456  }
1457  else
1458  {
1459  // TODO get color
1460 
1461  checkBlindDataID("vector3");
1462 
1463  if(!m_pFnMesh->isBlindDataTypeUsed(
1464  m_blindDataID))
1465  {
1466 #if FE_SAM_BLIND_DEBUG
1467  feLog("SurfaceAccessorMaya::spatialVector"
1468  " \"%s\" blind data %d not used\n",
1469  m_attrName.c_str(),m_blindDataID);
1470 #endif
1471  return SpatialVector(0.0,0.0,0.0);
1472  }
1473 
1474  const MFn::Type component=componentType();
1475  if(!m_pFnMesh->hasBlindData(component))
1476  {
1477 #if FE_SAM_BLIND_DEBUG
1478  feLog("SurfaceAccessorMaya::spatialVector"
1479  " no component blind data\n");
1480 #endif
1481  return SpatialVector(0.0,0.0,0.0);
1482  }
1483 
1484  if(!m_pFnMesh->hasBlindDataComponentId(
1485  rawVertex(a_index),component))
1486  {
1487 #if FE_SAM_BLIND_DEBUG
1488  feLog("SurfaceAccessorMaya::spatialVector"
1489  " no blind data on"
1490  " index %d (%d)\n",
1491  a_index,rawVertex(a_index));
1492 #endif
1493  return SpatialVector(0.0,0.0,0.0);
1494  }
1495 
1496  const I32 size=count();
1497  m_pSpatialVectorCache=new SpatialVector[size];
1498  for(I32 m=0;m<size;m++)
1499  {
1500  fe::set(m_pSpatialVectorCache[m]);
1501  }
1502 
1503  for(U32 n=0;n<3;n++)
1504  {
1505  String name;
1506  name.sPrintf("%s_%c",
1507  m_attrName.c_str(),'x'+n);
1508 
1509  MIntArray compIDs;
1510  MDoubleArray data;
1511  MStatus status=
1512  m_pFnMesh->getDoubleBlindData(
1513  component,
1514  m_blindDataID,
1515  name.c_str(),
1516  compIDs,
1517  data);
1518  if(!status)
1519  {
1520  feLog("SurfaceAccessorMaya::"
1521  "spatialVector"
1522  " getDoubleBlindData failed\n");
1523 
1524  delete m_pSpatialVectorCache;
1525  m_pSpatialVectorCache=NULL;
1526 
1527  return SpatialVector(0.0,0.0,0.0);
1528  }
1529 
1530  const I32 found=compIDs.length();
1531  for(I32 m=0;m<found;m++)
1532  {
1533  const I32 rawIndex=compIDs[m];
1534  FEASSERT(rawIndex>=0);
1535 
1536  const I32 index=
1537  logicalVertex(rawIndex);
1538 
1539  FEASSERT(index<size);
1540  m_pSpatialVectorCache[index][n]=
1541  data[m];
1542  }
1543  }
1544 
1545  return m_pSpatialVectorCache[a_index];
1546  }
1547 
1548  SpatialVector world(point[0],point[1],point[2]);
1549  if(m_useTransform)
1550  {
1551  transformVector(m_transform,world,world);
1552  }
1553 
1554  return world;
1555  }
1556 
1557  //* Maya specific
1558  void setMeshNode(const MObject a_meshNode)
1559  {
1560  m_meshNode=a_meshNode;
1561  }
1562  void setMeshData(const MDataHandle a_meshData)
1563  {
1564  m_meshData=a_meshData;
1565  resetMark();
1566 
1567  if(m_pFnMesh)
1568  {
1569  delete m_pFnMesh;
1570  }
1571 
1572  //* not thread safe
1573  m_pFnMesh=new MFnMesh(m_meshData.asMesh());
1574 
1575  m_cachePolyFormat=PolyFormat(e_unknown);
1576  polyFormat(0); // HACK set cache
1577  }
1578 const MDataHandle meshData(void)
1579  { return m_meshData; }
1580  void setGroupIt(MItGeometry* a_pGroupIt)
1581  { m_pGroupIt=a_pGroupIt; }
1582 
1583  void clearTransform(void)
1584  {
1585  m_useTransform=FALSE;
1586  }
1587  void setTransform(SpatialTransform a_transform)
1588  {
1589  m_useTransform=TRUE;
1590  m_transform=a_transform;
1591  invert(m_inverse,m_transform);
1592  }
1593 
1594  //* TODO move to a shared base class
1595  void setMaster(sp<Master> a_spMaster)
1596  { m_spMaster=a_spMaster; }
1597 
1598 static String typeOfFormat(String a_format);
1599 
1600 static MFn::Type componentTypeOfElement(
1601  SurfaceAccessibleI::Element a_element)
1602  {
1603  /*
1604  kMeshEdgeComponent
1605  kMeshPolygonComponent
1606 
1607  kMeshVertComponent
1608  kMeshFaceVertComponent
1609  */
1610  switch (a_element)
1611  {
1612  case SurfaceAccessibleI::e_point:
1613  case SurfaceAccessibleI::e_pointGroup:
1614  return MFn::kMeshVertComponent;
1615 
1616  case SurfaceAccessibleI::e_vertex:
1617  //* TODO verify
1618  return MFn::kMeshFaceVertComponent;
1619 
1620  case SurfaceAccessibleI::e_primitive:
1621  case SurfaceAccessibleI::e_primitiveGroup:
1622  return MFn::kMeshPolygonComponent;
1623 
1624  case SurfaceAccessibleI::e_detail:
1625  //* HACK store on first point
1626 // return MFn::kMeshVertComponent;
1627 
1628  default:
1629  ;
1630  }
1631  return MFn::kInvalid;
1632  }
1633 
1634 static String readDetailAt(MDataHandle a_meshData,I32 a_id);
1635 static void writeDetailAt(MDataHandle a_meshData,I32 a_id,
1636  const String& a_rString);
1637 static void removeDetailAt(MDataHandle a_meshData,I32 a_id);
1638 static BWORD removeDetailFor(MDataHandle a_meshData,
1639  String a_name);
1640 static I32 findDetailKey(MDataHandle a_meshData,
1641  const String& a_rKey,BWORD a_createMissing);
1642 static void dumpDetail(MDataHandle a_meshData);
1643 
1644  private:
1645 virtual BWORD bindInternal(SurfaceAccessibleI::Element a_element,
1646  const String& a_name)
1647  {
1648  m_element=SurfaceAccessibleI::e_point;
1649  if(a_element>=0 && a_element<=5)
1650  {
1651  m_element=a_element;
1652  }
1653  m_blindDataID= -1;
1654  m_attrName=a_name;
1655  updateGroupList();
1656 
1657  return TRUE; //* TODO only TRUE if exists
1658  }
1659 
1660  void cacheShaders(void);
1661  void cacheTexture(String a_textureName);
1662  void updateGroupList(void);
1663 
1664  void checkBlindDataID(const String& a_attrType)
1665  {
1666 #if FE_SAM_BLIND_DEBUG
1667  feLog("SurfaceAccessorMaya::checkBlindDataID"
1668  " attr %d type \"%s\"\n",
1669  m_attribute,a_attrType.c_str());
1670 #endif
1671 
1672  if(m_attribute==SurfaceAccessibleI::e_generic &&
1673  m_blindDataID<0)
1674  {
1675  m_attrType=a_attrType;
1676  if(!m_attrName.empty())
1677  {
1678  const String attrKey=
1679  m_attrName+":"+m_attrType;
1680  m_blindDataID=
1681  m_spMaster->catalog()
1682  ->catalogOrDefault<I32>(
1683  "MayaBlindID",attrKey,-1);
1684 #if FE_SAM_BLIND_DEBUG
1685  feLog("SurfaceAccessorMaya::"
1686  "checkBlindDataID"
1687  " found id %d for \"%s\"\n",
1688  m_blindDataID,attrKey.c_str());
1689 #endif
1690  }
1691  }
1692  }
1693  void assureBlindDataID(const String& a_attrType)
1694  {
1695 #if FE_SAM_BLIND_DEBUG
1696  feLog("SurfaceAccessorMaya::assureBlindDataID"
1697  " attr %d type \"%s\"\n",
1698  m_attribute,a_attrType.c_str());
1699 #endif
1700 
1701  checkBlindDataID(a_attrType);
1702  if(m_attribute==SurfaceAccessibleI::e_generic &&
1703  m_blindDataID<0)
1704  {
1705  m_blindDataID=createBlindDataID(
1706  m_attrName,m_attrType);
1707 #if FE_SAM_BLIND_DEBUG
1708  feLog("SurfaceAccessorMaya::assureBlindDataID"
1709  " created new id %d for \"%s\"\n",
1710  m_blindDataID,m_attrName.c_str());
1711 #endif
1712  }
1713  }
1714  String getBlindFormat(String a_attrName);
1715  I32 getBlindDataID(String a_attrName,String a_attrType,
1716  BWORD& a_rFound);
1717  I32 createBlindDataID(String a_attrName,String a_attrType);
1718 
1719  void checkPolyFormatID(void)
1720  {
1721  if(m_polyFormatID<0)
1722  {
1723  const String attrKey="POLY_FORMAT:I32";
1724  m_polyFormatID=
1725  m_spMaster->catalog()->catalog<I32>(
1726  "MayaBlindID",attrKey,-1);
1727  }
1728  }
1729  void assurePolyFormatID(void)
1730  {
1731  checkPolyFormatID();
1732  if(m_polyFormatID<0)
1733  {
1734  m_polyFormatID=createBlindDataID(
1735  "POLY_FORMAT","integer");
1736  }
1737 
1738  //* This is apparently needed before hasBlindData()
1739  //* to wake it up or something.
1740  //* It doesn't have to be the same one we check.
1741  FEASSERT(m_pFnMesh);
1742  I32 probeInt= -1;
1743  m_pFnMesh->getIntBlindData(0,
1744  MFn::kMeshPolygonComponent,
1745  m_polyFormatID, "POLY_FORMAT",
1746  probeInt);
1747  }
1748  PolyFormat polyFormat(U32 a_index) const
1749  {
1750  //* TODO cache all polys, like with m_pIntegerCache
1751 
1752  if(m_cachePolyFormat!=e_unknown)
1753  {
1754  return m_cachePolyFormat;
1755  }
1756 
1757  const_cast<SurfaceAccessorMaya*>(this)
1758  ->assurePolyFormatID();
1759 
1760  PolyFormat format=e_unknown;
1761 
1762  I32 data=0;
1763  MStatus status=m_pFnMesh->getIntBlindData(
1764  a_index,
1765  MFn::kMeshPolygonComponent,
1766  m_polyFormatID,
1767  "POLY_FORMAT",
1768  data);
1769  if(status)
1770  {
1771  format=PolyFormat(data);
1772  }
1773  else
1774  {
1775  feLog("SurfaceAccessorMaya::polyFormat"
1776  " getIntegerBlindData failed\n");
1777  }
1778 
1779  if(format==e_unknown)
1780  {
1781  format=guessPolyFormat();
1782  }
1783  if(format==e_unknown)
1784  {
1785  format=e_closedPoly;
1786  }
1787 
1788  const_cast<SurfaceAccessorMaya*>(this)->
1789  m_cachePolyFormat=format;
1790  return m_cachePolyFormat;
1791  }
1792 
1793  PolyFormat guessPolyFormat(void) const;
1794 
1795  U32 polyVertCount(U32 a_index) const
1796  {
1797  FEASSERT(m_pFnMesh);
1798 
1799  const U32 rawCount=
1800  m_pFnMesh->polygonVertexCount(a_index);
1801  const PolyFormat format=polyFormat(a_index);
1802  switch(format)
1803  {
1804  case e_unknown:
1805  case e_closedPoly:
1806  return rawCount;
1807  case e_openPoly:
1808  return rawCount>>1;
1809  case e_freePoint:
1810  return rawCount? 1: 0;
1811  default:
1812  ;
1813  }
1814 
1815  return 0;
1816  }
1817  U32 vertexCount(void) const
1818  {
1819  //* wake up blind data
1820  polyFormat(0);
1821 
1822  if(!m_pFnMesh->hasBlindData(
1823  MFn::kMeshPolygonComponent,m_polyFormatID))
1824  {
1825 #if FALSE
1826  if(m_pFnMesh->numVertices()!=countVertices())
1827  {
1828  feLog("SurfaceAccessorMaya::vertexCount"
1829  " \"%s\""
1830  " bogus numVertices %d"
1831  " vs counted %d\n",
1832  m_attrName.c_str(),
1833  m_pFnMesh->numVertices(),
1834  countVertices());
1835 
1836  const U32 primitiveCount=
1837  m_pFnMesh->numPolygons();
1838  for(U32 primitiveIndex=0;
1839  primitiveIndex<primitiveCount;
1840  primitiveIndex++)
1841  {
1842  feLog(" prim %d/%d\n",
1843  primitiveIndex,primitiveCount);
1844 
1845  MIntArray vertexList;
1846  m_pFnMesh->getPolygonVertices(
1847  primitiveIndex,vertexList);
1848 
1849  const U32 subCount=
1850  m_pFnMesh->polygonVertexCount(
1851  primitiveIndex);
1852  for(U32 subIndex=0;
1853  subIndex<subCount;subIndex++)
1854  {
1855  const U32 raw=
1856  vertexList[subIndex];
1857 
1858  feLog(" sub %d/%d index %d\n",
1859  subIndex,subCount,raw);
1860  }
1861  }
1862 
1863  return countVertices();
1864  }
1865 #endif
1866 
1867  return m_pFnMesh->numVertices();
1868  }
1869  //* TODO account for potentially shared points
1870  return countVertices();
1871  }
1872  U32 countVertices(void) const
1873  {
1874  // TODO cache
1875  U32 sum=0;
1876  U32 primitiveCount=m_pFnMesh->numPolygons();
1877  for(U32 index=0;index<primitiveCount;index++)
1878  {
1879  sum+=polyVertCount(index);
1880  }
1881  return sum;
1882  }
1883  void resetMark(void)
1884  {
1885  m_markPoly=0;
1886  m_markVertex=0;
1887  m_markRawVertex=0;
1888  }
1889  U32 logicalVertex(U32 a_rawVertex)
1890  {
1891  //* wake up blind data
1892  polyFormat(0);
1893 #if FALSE
1894  if(!m_pFnMesh->hasBlindData(
1895  MFn::kMeshPolygonComponent,m_polyFormatID))
1896  {
1897  return a_rawVertex;
1898  }
1899 #else
1900  if(m_cachePolyFormat!=e_openPoly)
1901  {
1902  return a_rawVertex;
1903  }
1904 #endif
1905  while(TRUE)
1906  {
1907  if(a_rawVertex<m_markRawVertex)
1908  {
1909  if(m_markPoly<1)
1910  {
1911  feX("SurfaceAccessorMaya::rawVertex",
1912  "mark data corrupt");
1913  }
1914 // feLog("logicalVertex %d poly %d dec\n",
1915 // a_rawVertex,m_markPoly);
1916  m_markPoly--;
1917  m_markVertex-=polyVertCount(m_markPoly);
1918  m_markRawVertex-=
1919  m_pFnMesh->polygonVertexCount(
1920  m_markPoly);
1921  continue;
1922  }
1923  const U32 subIndex=a_rawVertex-m_markRawVertex;
1924  const U32 subs=polyVertCount(m_markPoly);
1925  if(subIndex<subs)
1926  {
1927  return m_markVertex+subIndex;
1928  }
1929  else if(subIndex<subs*2)
1930  {
1931  return m_markVertex+(subs*2-1-subIndex);
1932  }
1933  const U32 primitiveCount=
1934  m_pFnMesh->numPolygons();
1935 // feLog("logicalVertex %d poly %d/%d inc\n",
1936 // a_rawVertex,
1937 // m_markPoly,primitiveCount);
1938  if(m_markPoly>=primitiveCount-1)
1939  {
1940  feX("SurfaceAccessorMaya::logicalVertex",
1941  "excessive point index");
1942  }
1943  m_markVertex+=polyVertCount(m_markPoly);
1944  m_markRawVertex+=
1945  m_pFnMesh->polygonVertexCount(
1946  m_markPoly);
1947  m_markPoly++;
1948  }
1949  }
1950  U32 rawVertex(U32 a_logicalVertex)
1951  {
1952  const PolyFormat format=polyFormat(a_logicalVertex);
1953 
1954  if(format!=e_openPoly)
1955  {
1956  return a_logicalVertex;
1957  }
1958 
1959  while(TRUE)
1960  {
1961  if(a_logicalVertex<m_markVertex)
1962  {
1963  if(m_markPoly<1)
1964  {
1965  feX("SurfaceAccessorMaya::rawVertex",
1966  "mark data corrupt");
1967  }
1968 // feLog("rawVertex %d poly %d dec\n",
1969 // a_logicalVertex,m_markPoly);
1970  m_markPoly--;
1971  m_markVertex-=polyVertCount(m_markPoly);
1972  m_markRawVertex-=
1973  m_pFnMesh->polygonVertexCount(
1974  m_markPoly);
1975  continue;
1976  }
1977  const U32 subIndex=a_logicalVertex-m_markVertex;
1978  const U32 subs=polyVertCount(m_markPoly);
1979  if(subIndex<subs)
1980  {
1981  return m_markRawVertex+subIndex;
1982  }
1983  const U32 primitiveCount=
1984  m_pFnMesh->numPolygons();
1985 // feLog("rawVertex %d poly %d/%d inc\n",
1986 // a_logicalVertex,
1987 // m_markPoly,primitiveCount);
1988  if(m_markPoly>=primitiveCount-1)
1989  {
1990  feX("SurfaceAccessorMaya::rawVertex",
1991  "excessive point index");
1992  }
1993  m_markVertex+=polyVertCount(m_markPoly);
1994  m_markRawVertex+=
1995  m_pFnMesh->polygonVertexCount(
1996  m_markPoly);
1997  m_markPoly++;
1998  }
1999  }
2000  U32 twinVertex(U32 a_logicalVertex)
2001  {
2002  rawVertex(a_logicalVertex);
2003  const U32 subIndex=a_logicalVertex-m_markVertex;
2004  const U32 subs=m_pFnMesh->polygonVertexCount(
2005  m_markPoly);
2006 
2007  MIntArray vertexList;
2008 // MStatus status=
2009  m_pFnMesh->getPolygonVertices(
2010  m_markPoly,vertexList);
2011 
2012  return vertexList[subs-1-subIndex];
2013  }
2014 
2015  MFn::Type componentType(void)
2016  {
2017  return componentTypeOfElement(m_element);
2018  }
2019 
2020  void setDetail(const String& a_rKey,const String& a_rValue);
2021  String getDetail(const String& a_rKey);
2022 
2023  void initializeFaceVertArray(void);
2024 
2025  class FaceVert
2026  {
2027  public:
2028  FaceVert(void):
2029  m_face(-1),
2030  m_vert(-1) {}
2031 
2032  FaceVert(I32 a_face,I32 a_vert):
2033  m_face(a_face),
2034  m_vert(a_vert) {}
2035 
2036  I32 m_face;
2037  I32 m_vert;
2038  };
2039 
2040  Array< Array<FaceVert> > m_faceVertTable;
2041 
2042  //* cache last raw vertex lookup
2043  U32 m_markPoly;
2044  U32 m_markVertex;
2045  U32 m_markRawVertex;
2046 
2047  PolyFormat m_cachePolyFormat; // TODO mixed
2048 
2049  sp<Master> m_spMaster;
2050  MObject m_meshNode;
2051  MDataHandle m_meshData;
2052  MFnMesh* m_pFnMesh;
2053  I32 m_blindDataID;
2054  I32 m_polyFormatID;
2055 
2056  MItGeometry* m_pGroupIt;
2057  Array<I32> m_groupList;
2058 
2059  BWORD m_useTransform;
2060  SpatialTransform m_transform;
2061  SpatialTransform m_inverse;
2062 
2063  String* m_pStringCache;
2064  I32* m_pIntegerCache;
2065  Real* m_pRealCache;
2066  SpatialVector* m_pSpatialVectorCache;
2067  BWORD* m_pBooleanCache;
2068 };
2069 
2070 } /* namespace ext */
2071 } /* namespace fe */
2072 
2073 #endif /* __maya_SurfaceAccessorMaya_h__ */
const FESTRING_I8 * c_str(void) const
Return the contents of the 8-bit buffer cast as signed bytes.
Definition: String.h:352
kernel
Definition: namespace.dox:3
Matrix< 4, 4, T > & invert(Matrix< 4, 4, T > &a_inverted, const Matrix< 4, 4, T > &a_matrix)
4x4 full matrix inversion
Definition: Matrix.h:1033
Common Functionality for Accessor Surface.
Definition: SurfaceAccessorBase.h:20
BWORD empty(void) const
Returns true if the contents have zero length.
Definition: String.h:667
Maya Surface Editing Implementation.
Definition: SurfaceAccessorMaya.h:30
String & sPrintf(const char *fmt,...)
Populate the string in the manner of sprintf().
Definition: String.cc:529
Automatically reference-counted string container.
Definition: String.h:128
Wrapper for std::vector.
Definition: Array.h:21
Intrusive Smart Pointer.
Definition: src/core/ptr.h:53
U32 length(void) const
Return the number of represented characters, but not necessarily the size of any buffer.
Definition: String.h:662
Per-class participation non-RTTI fallback dynamic casting mechanism.
Definition: Castable.h:192