1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
|
/*
* Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
*
* NVIDIA CORPORATION and its licensors retain all intellectual property
* and proprietary rights in and to this software, related documentation
* and any modifications thereto. Any use, reproduction, disclosure or
* distribution of this software and related documentation without an express
* license agreement from NVIDIA CORPORATION is strictly prohibited.
*/
#ifndef APEX_RENDERMESH_ACTOR_H
#define APEX_RENDERMESH_ACTOR_H
#include "ApexUsingNamespace.h"
#include "RenderMeshAssetIntl.h"
#include "ApexActor.h"
#include "ApexRenderMeshAsset.h"
#include "ApexSharedUtils.h"
#include "ApexRWLockable.h"
#include "ReadCheck.h"
#include "WriteCheck.h"
namespace nvidia
{
namespace apex
{
// enables a hack that removes dead particles from the instance list prior to sending it to the application.
// this is a bad hack because it requires significant additional memory and copies.
#define ENABLE_INSTANCED_MESH_CLEANUP_HACK 0
/*
ApexRenderMeshActor - an instantiation of an ApexRenderMeshAsset
*/
class ApexRenderMeshActor : public RenderMeshActorIntl, public ApexResourceInterface, public ApexResource, public ApexActor, public ApexRWLockable
{
public:
APEX_RW_LOCKABLE_BOILERPLATE
void release();
Asset* getOwner() const
{
READ_ZONE();
return mRenderMeshAsset;
}
PxBounds3 getBounds() const
{
READ_ZONE();
return ApexRenderable::getBounds();
}
void lockRenderResources()
{
ApexRenderable::renderDataLock();
}
void unlockRenderResources()
{
ApexRenderable::renderDataUnLock();
}
// RenderMeshActors have global context, ignore ApexActor scene methods
#if PX_PHYSICS_VERSION_MAJOR == 3
void setPhysXScene(PxScene*) { }
PxScene* getPhysXScene() const
{
return NULL;
}
#endif
bool getVisibilities(uint8_t* visibilityArray, uint32_t visibilityArraySize) const;
bool setVisibility(bool visible, uint16_t partIndex = 0);
bool isVisible(uint16_t partIndex = 0) const
{
READ_ZONE();
return mVisiblePartsForAPI.isUsed(partIndex);
}
uint32_t visiblePartCount() const
{
READ_ZONE();
return mVisiblePartsForAPI.usedCount();
}
const uint32_t* getVisibleParts() const
{
READ_ZONE();
return mVisiblePartsForAPI.usedIndices();
}
uint32_t getRenderVisiblePartCount() const
{
return mBufferVisibility ? mVisiblePartsForRendering.size() : mVisiblePartsForAPI.usedCount();
}
const uint32_t* getRenderVisibleParts() const
{
return mBufferVisibility ? mVisiblePartsForRendering.begin() : mVisiblePartsForAPI.usedIndices();
}
virtual uint32_t getBoneCount() const
{
READ_ZONE();
return mRenderMeshAsset->getBoneCount();
}
void setTM(const PxMat44& tm, uint32_t boneIndex = 0);
void setTM(const PxMat44& tm, const PxVec3& scale, uint32_t boneIndex = 0);
const PxMat44 getTM(uint32_t boneIndex = 0) const
{
READ_ZONE();
return accessTM(boneIndex);
}
void setLastFrameTM(const PxMat44& tm, uint32_t boneIndex = 0);
void setLastFrameTM(const PxMat44& tm, const PxVec3& scale, uint32_t boneIndex = 0);
void setSkinningMode(RenderMeshActorSkinningMode::Enum mode);
RenderMeshActorSkinningMode::Enum getSkinningMode() const;
void syncVisibility(bool useLock = true);
void updateBounds();
void updateRenderResources(bool rewriteBuffers, void* userRenderData);
void updateRenderResources(bool useBones, bool rewriteBuffers, void* userRenderData);
void dispatchRenderResources(UserRenderer&);
void dispatchRenderResources(UserRenderer&, const PxMat44&);
void setReleaseResourcesIfNothingToRender(bool value);
void setBufferVisibility(bool bufferVisibility);
void setOverrideMaterial(uint32_t index, const char* overrideMaterialName);
//UserRenderVertexBuffer* getUserVertexBuffer(uint32_t submeshIndex) { if (submeshIndex < mSubmeshData.size()) return renderMeshAsset->vertexBuffers[submeshIndex]; return NULL; }
//UserRenderIndexBuffer* getUserIndexBuffer(uint32_t submeshIndex) { if (submeshIndex < mSubmeshData.size()) return mSubmeshData[submeshIndex].indexBuffer; return NULL; }
void addVertexBuffer(uint32_t submeshIndex, bool alwaysDirty, PxVec3* position, PxVec3* normal, PxVec4* tangents);
void removeVertexBuffer(uint32_t submeshIndex);
void setStaticPositionReplacement(uint32_t submeshIndex, const PxVec3* staticPositions);
void setStaticColorReplacement(uint32_t submeshIndex, const ColorRGBA* staticColors);
virtual UserRenderInstanceBuffer* getInstanceBuffer() const
{
READ_ZONE();
return mInstanceBuffer;
}
/// \sa RenderMeshActor::setInstanceBuffer
virtual void setInstanceBuffer(UserRenderInstanceBuffer* instBuf);
virtual void setMaxInstanceCount(uint32_t count);
/// \sa RenderMeshActor::setInstanceBufferRange
virtual void setInstanceBufferRange(uint32_t from, uint32_t count);
// ApexResourceInterface methods
void setListIndex(ResourceList& list, uint32_t index)
{
m_listIndex = index;
m_list = &list;
}
uint32_t getListIndex() const
{
return m_listIndex;
}
virtual void getLodRange(float& min, float& max, bool& intOnly) const;
virtual float getActiveLod() const;
virtual void forceLod(float lod);
/**
\brief Selectively enables/disables debug visualization of a specific APEX actor. Default value it true.
*/
virtual void setEnableDebugVisualization(bool state)
{
WRITE_ZONE();
ApexActor::setEnableDebugVisualization(state);
}
virtual bool rayCast(RenderMeshActorRaycastHitData& hitData,
const PxVec3& worldOrig, const PxVec3& worldDisp,
RenderMeshActorRaycastFlags::Enum flags = RenderMeshActorRaycastFlags::VISIBLE_PARTS,
RenderCullMode::Enum winding = RenderCullMode::CLOCKWISE,
int32_t partIndex = -1) const;
virtual void visualize(RenderDebugInterface& batcher, nvidia::apex::DebugRenderParams* debugParams, PxMat33* scaledRotations, PxVec3* translations, uint32_t stride, uint32_t numberOfTransforms) const;
protected:
ApexRenderMeshActor(const RenderMeshActorDesc& desc, ApexRenderMeshAsset& _renderMeshData, ResourceList& list);
virtual ~ApexRenderMeshActor();
struct SubmeshData;
void loadMaterial(SubmeshData& submeshData);
void init(const RenderMeshActorDesc& desc, uint16_t partCount, uint16_t boneCount);
void destroy();
PxMat44& accessTM(uint32_t boneIndex = 0) const
{
return (PxMat44&)mTransforms[mKeepVisibleBonesPacked ? mVisiblePartsForAPI.getRank(boneIndex) : boneIndex];
}
PxMat44& accessLastFrameTM(uint32_t boneIndex = 0) const
{
return (PxMat44&)mTransformsLastFrame[mKeepVisibleBonesPacked ? mVisiblePartsForAPILastFrame.getRank(boneIndex) : boneIndex];
}
/* Internal rendering APIs */
void createRenderResources(bool useBones, void* userRenderData);
void updatePartVisibility(uint32_t submeshIndex, bool useBones, void* userRenderData);
void updateBonePoses(uint32_t submeshIndex);
void updateInstances(uint32_t submeshIndex);
void releaseSubmeshRenderResources(uint32_t submeshIndex);
void releaseRenderResources();
bool submeshHasVisibleTriangles(uint32_t submeshIndex) const;
// Fallback skinning
void createFallbackSkinning(uint32_t submeshIndex);
void distributeFallbackData(uint32_t submeshIndex);
void updateFallbackSkinning(uint32_t submeshIndex);
void writeUserBuffers(uint32_t submeshIndex);
// Debug rendering
void visualizeTangentSpace(RenderDebugInterface& batcher, float normalScale, float tangentScale, float bitangentScale, PxMat33* scaledRotations, PxVec3* translations, uint32_t stride, uint32_t numberOfTransforms) const;
ApexRenderMeshAsset* mRenderMeshAsset;
Array<PxMat44> mTransforms;
Array<PxMat44> mTransformsLastFrame;
struct ResourceData
{
ResourceData() : resource(NULL), vertexCount(0), boneCount(0) {}
UserRenderResource* resource;
uint32_t vertexCount;
uint32_t boneCount;
};
struct SubmeshData
{
SubmeshData();
~SubmeshData();
Array<ResourceData> renderResources;
UserRenderIndexBuffer* indexBuffer;
void* fallbackSkinningMemory;
UserRenderVertexBuffer* userDynamicVertexBuffer;
UserRenderInstanceBuffer* instanceBuffer;
PxVec3* userPositions;
PxVec3* userNormals;
PxVec4* userTangents4;
// And now we have colors
const ColorRGBA* staticColorReplacement;
bool staticColorReplacementDirty;
// These are needed if the positions vary from what the asset has stored. Can happen with morph targets.
// so far we only replace positions, more can be added here
const PxVec3* staticPositionReplacement;
UserRenderVertexBuffer* staticBufferReplacement;
UserRenderVertexBuffer* dynamicBufferReplacement;
uint32_t fallbackSkinningMemorySize;
uint32_t visibleTriangleCount;
ResID materialID;
void* material;
bool isMaterialPointerValid;
uint32_t maxBonesPerMaterial;
uint32_t indexBufferRequestedSize;
bool userSpecifiedData;
bool userVertexBufferAlwaysDirty;
bool userIndexBufferChanged;
bool fallbackSkinningDirty;
};
nvidia::Array<SubmeshData> mSubmeshData;
IndexBank<uint32_t> mVisiblePartsForAPI;
IndexBank<uint32_t> mVisiblePartsForAPILastFrame;
RenderBufferHint::Enum mIndexBufferHint;
Array<uint32_t> mVisiblePartsForRendering;
Array<UserRenderVertexBuffer*> mPerActorVertexBuffers;
// Instancing
uint32_t mMaxInstanceCount;
uint32_t mInstanceCount;
uint32_t mInstanceOffset;
UserRenderInstanceBuffer* mInstanceBuffer;
UserRenderResource* mRenderResource;
// configuration
bool mRenderWithoutSkinning;
bool mForceBoneIndexChannel;
bool mApiVisibilityChanged;
bool mPartVisibilityChanged;
bool mInstanceCountChanged;
bool mKeepVisibleBonesPacked;
bool mForceFallbackSkinning;
bool mBonePosesDirty;
bool mOneUserVertexBufferChanged; // this will be true if one or more user vertex buffers changed
bool mBoneBufferInUse;
bool mReleaseResourcesIfNothingToRender; // is this ever set? I think we should remove it.
bool mCreateRenderResourcesAfterInit; // only needed when mRenderWithoutSkinning is set to true
bool mBufferVisibility;
bool mKeepPreviousFrameBoneBuffer;
bool mPreviousFrameBoneBufferValid;
RenderMeshActorSkinningMode::Enum mSkinningMode;
Array<uint32_t> mTMSwapBuffer;
Array<PxMat44> mRemappedPreviousBoneTMs;
// temporary
Array<uint16_t> mBoneIndexTempBuffer;
// CM: For some reason the new operator doesn't see these members and allocates not enough memory for the class (on a 64 bit build)
// Even though ENABLE_INSTANCED_MESH_CLEANUP_HACK is defined to be 1 earlier in this file.
// For now, these members are permanently here, since it's a tiny amount of memory if the define is off, and it fixes the allocation problem.
//#if ENABLE_INSTANCED_MESH_CLEANUP_HACK
void* mOrderedInstanceTemp;
uint32_t mOrderedInstanceTempSize;
//#endif
Array<uint32_t> mPartIndexTempBuffer;
friend class ApexRenderMeshAsset;
};
} // namespace apex
} // namespace nvidia
#endif // APEX_RENDERMESH_ACTOR_H
|