-
Notifications
You must be signed in to change notification settings - Fork 5
/
objectdata_planebypolygons.cpp
227 lines (192 loc) · 8.39 KB
/
objectdata_planebypolygons.cpp
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
#include "c4d_baseobject.h"
#include "c4d_objectdata.h"
#include "c4d_thread.h"
// Includes from example.main
#include "c4d_symbols.h"
#include "main.h"
// Local resources
#include "oplanebypolygons.h"
#include "c4d_resource.h"
#include "c4d_basebitmap.h"
/**A unique plugin ID. You must obtain this from http://www.plugincafe.com. Use this ID to create new instances of this object.*/
static const Int32 ID_SDKEXAMPLE_OBJECTDATA_PLANEBYPOLYGONS = 1038223;
namespace PlaneByPolygonsHelpers
{
//----------------------------------------------------------------------------------------
/// Global function responsible to create a plane composed by polygons.
/// @brief Global function responsible to create a plane composed by polygons.
/// @param[out] polygonObj Polygon object provided to store created geometry. @callerOwnsPointed{base object}
/// @param[in] planeWidth Base value for geometry construction.
/// @param[in] planeHeight Bounding box radius vector.
/// @param[in] planeWidthSegs Segmentation array.
/// @param[in] planeHeightSegs Space between columns along the x-axis.
/// @param[in] hhPtr A hierarchy helper for the operation. @callerOwnsPointed{hierarchy helper}
/// @return True if creation process succeeds.
//----------------------------------------------------------------------------------------
static maxon::Result<void> CreatePlaneByPolygons(PolygonObject& polygonObj, const Float& planeWidth, const Float& planeHeight, const Int32& planeWidthSegs, const Int32& planeHeightSegs, const HierarchyHelp* hhPtr = nullptr);
static maxon::Result<void> CreatePlaneByPolygons(PolygonObject& polygonObj, const Float& planeWidth, const Float& planeHeight, const Int32& planeWidthSegs, const Int32& planeHeightSegs, const HierarchyHelp* hhPtr /*= nullptr*/)
{
CPolygon* pPolygonsW = polygonObj.GetPolygonW();
if (!pPolygonsW)
return maxon::NullptrError(MAXON_SOURCE_LOCATION);
Vector* pVerticesW = polygonObj.GetPointW();
if (!pVerticesW)
return maxon::NullptrError(MAXON_SOURCE_LOCATION);
if (planeHeightSegs == 0 || planeWidthSegs == 0)
return maxon::IllegalArgumentError(MAXON_SOURCE_LOCATION);
// Compute the width/height of the single polygon
// composing the polygon object
const Float fWStep = planeWidth / planeWidthSegs;
const Float FHStep = planeHeight / planeHeightSegs;
// Fill the vertices and polygons indices array
for (Int32 j = 0; j < planeHeightSegs + 1; ++j)
{
for (Int32 i = 0; i < planeWidthSegs + 1; ++i)
{
if (hhPtr)
{
// Check from time to time (every 64 segments)
// if a user break has been requested
BaseThread* btPtr = hhPtr->GetThread();
if (btPtr && !(i & 63) && btPtr->TestBreak())
break;
}
// Fill the vertices data
const Int32 iVtxIdx = j * (planeWidthSegs + 1) + i;
pVerticesW[iVtxIdx] = Vector(planeWidth / 2 - i * fWStep, 0, planeHeight / 2 - j * FHStep);
// Fill the polygons indices
if (j < planeHeightSegs && i < planeWidthSegs)
{
// Define the general polygon index
const Int32 iPolyIdx = j * planeWidthSegs + i;
// Check if specifying tris or quads
if (polygonObj.GetPolygonCount() != (planeHeightSegs * planeWidthSegs))
{
const Int32 iPolyIdxA = 2 * iPolyIdx;
const Int32 iPolyIdxB = 2 * iPolyIdx + 1;
// Fill polygon (triangle A) by using indexes for the
// vertexes generated above
pPolygonsW[iPolyIdxA] = CPolygon(
i + (j) * (planeWidthSegs + 1),
i + (j + 1) * (planeWidthSegs + 1),
i + (j + 1) * (planeWidthSegs + 1) + 1);
// Fill polygon (triangle B) by using indexes for the
// vertexes generated above
pPolygonsW[iPolyIdxB] = CPolygon(
i + (j) * (planeWidthSegs + 1),
i + (j + 1) * (planeWidthSegs + 1) + 1,
i + (j) * (planeWidthSegs + 1) + 1);
}
else
{
// Fill polygon [quad] by using indexes for the
// vertexes generated above
pPolygonsW[iPolyIdx] = CPolygon(
i + (j) * (planeWidthSegs + 1),
i + (j + 1) * (planeWidthSegs + 1),
i + (j + 1) * (planeWidthSegs + 1) + 1,
i + (j) * (planeWidthSegs + 1) + 1
);
}
}
}
}
return maxon::OK;
}
}
//------------------------------------------------------------------------------------------------
/// Basic ObjectData implementation responsible for generating a simple plane centered in the
/// origin and 250x250cm (default) wide.
///
/// The provided parameters are width and height, and horizontal and vertical segmentations plus
/// a check box to turn on the option to generate triangles instead of standard quadrangles.
//------------------------------------------------------------------------------------------------
class PlaneByPolygons : public ObjectData
{
INSTANCEOF(PlaneByPolygons, ObjectData)
public:
static NodeData* Alloc() { return NewObj(PlaneByPolygons) iferr_ignore("PlaneByPolygons plugin not instanced"); }
virtual Bool Init(GeListNode* node, Bool isCloneInit);
virtual void GetDimension(const BaseObject* op, Vector* mp, Vector* rad) const;
virtual BaseObject* GetVirtualObjects(BaseObject* op, const HierarchyHelp* hh);
};
/// @name ObjectData functions
/// @{
Bool PlaneByPolygons::Init(GeListNode* node, Bool isCloneInit)
{
BaseObject* baseObjectPtr = static_cast<BaseObject*>(node);
BaseContainer* objectDataPtr = baseObjectPtr->GetDataInstance();
if (!isCloneInit)
{
objectDataPtr->SetFloat(SDK_EXAMPLE_PLANEBYPOLYGONS_WIDTH, 250);
objectDataPtr->SetFloat(SDK_EXAMPLE_PLANEBYPOLYGONS_HEIGHT, 250);
objectDataPtr->SetInt32(SDK_EXAMPLE_PLANEBYPOLYGONS_W_SUBD, 1);
objectDataPtr->SetInt32(SDK_EXAMPLE_PLANEBYPOLYGONS_H_SUBD, 1);
objectDataPtr->SetBool(SDK_EXAMPLE_PLANEBYPOLYGONS_USE_TRIS, false);
}
return true;
}
void PlaneByPolygons::GetDimension(const BaseObject* op, Vector* mp, Vector* rad) const
{
mp->SetZero();
rad->SetZero();
if (!op)
return;
const BaseContainer* objectDataPtr = op->GetDataInstance();
if (!objectDataPtr)
return;
Float fWidth = objectDataPtr->GetFloat(SDK_EXAMPLE_PLANEBYPOLYGONS_WIDTH);
Float fHeight = objectDataPtr->GetFloat(SDK_EXAMPLE_PLANEBYPOLYGONS_HEIGHT);
rad->x = fWidth * 0.5;
rad->z = fHeight * 0.5;
}
BaseObject* PlaneByPolygons::GetVirtualObjects(BaseObject* op, const HierarchyHelp* hh)
{
if (!op)
return BaseObject::Alloc(Onull);
Bool isDirty = op->CheckCache(hh) || op->IsDirty(DIRTYFLAGS::DATA);
if (!isDirty)
return op->GetCache();
BaseContainer* objectDataPtr = op->GetDataInstance();
if (!objectDataPtr)
return BaseObject::Alloc(Onull);
// Retrieve the value for the object parameters
const Float fWidth = objectDataPtr->GetFloat(SDK_EXAMPLE_PLANEBYPOLYGONS_WIDTH);
const Float fHeight = objectDataPtr->GetFloat(SDK_EXAMPLE_PLANEBYPOLYGONS_HEIGHT);
const Int32 iWSubds = objectDataPtr->GetInt32(SDK_EXAMPLE_PLANEBYPOLYGONS_W_SUBD);
const Int32 iHSubds = objectDataPtr->GetInt32(SDK_EXAMPLE_PLANEBYPOLYGONS_H_SUBD);
const Bool bUseTris = objectDataPtr->GetBool(SDK_EXAMPLE_PLANEBYPOLYGONS_USE_TRIS);
if (fWidth == 0 || fHeight == 0 || iWSubds == 0 || iHSubds == 0)
return BaseObject::Alloc(Onull);
// Compute the number of vertices based on the width and height subdivisions
const Int32 iVtxCnt = (iWSubds + 1) * (iHSubds + 1);
// Compute the number of polys based on the width and height subdivisions
// and type of output
Int32 iPolyCnt = iWSubds * iHSubds;
if (bUseTris)
iPolyCnt = 2 * iPolyCnt;
// Create the a PolygonObject object specifying vertices and
// polygons count
PolygonObject* polyObjPtr = PolygonObject::Alloc(iVtxCnt, iPolyCnt);
if (!polyObjPtr)
return BaseObject::Alloc(Onull);
// Fill the PolygonObject object with the vertices and polygons
// indices data
iferr (PlaneByPolygonsHelpers::CreatePlaneByPolygons(*polyObjPtr, fWidth, fHeight, iWSubds, iHSubds, hh))
{
DiagnosticOutput("Error occurred in CreatePlaneByPolygons: @", err);
PolygonObject::Free(polyObjPtr);
return BaseObject::Alloc(Onull);
}
polyObjPtr->Message(MSG_UPDATE);
polyObjPtr->MakeTag(Tphong);
return polyObjPtr;
}
/// @}
Bool RegisterPlaneByPolygons()
{
String registeredName = GeLoadString(IDS_OBJECTDATA_PLANEBYPOLYGONS);
if (!registeredName.IsPopulated() || registeredName == "StrNotFound")
registeredName = "C++ SDK - Plane By Polygon Generator Example";
return RegisterObjectPlugin(ID_SDKEXAMPLE_OBJECTDATA_PLANEBYPOLYGONS, registeredName, OBJECT_GENERATOR, PlaneByPolygons::Alloc, "oplanebypolygons"_s, AutoBitmap("planebypolygons.tif"_s), 0);
}