// Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // * Neither the name of NVIDIA CORPORATION nor the names of its // contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved. #include "PxPvdUserRenderImpl.h" #include "PxPvdInternalByteStreams.h" #include "PxPvdBits.h" #include using namespace physx; using namespace physx::pvdsdk; namespace { template struct RenderWriter : public RenderSerializer { TStreamType& mStream; RenderWriter(TStreamType& stream) : mStream(stream) { } template void write(const TDataType* val, uint32_t count) { uint32_t numBytes = count * sizeof(TDataType); mStream.write(reinterpret_cast(val), numBytes); } template void write(const TDataType& val) { write(&val, 1); } template void writeRef(DataRef& val) { uint32_t amount = val.size(); write(amount); if(amount) write(val.begin(), amount); } virtual void streamify(uint64_t& val) { write(val); } virtual void streamify(uint32_t& val) { write(val); } virtual void streamify(float& val) { write(val); } virtual void streamify(uint8_t& val) { write(val); } virtual void streamify(DataRef& val) { writeRef(val); } virtual void streamify(PxDebugText& val) { write(val.color); write(val.position); write(val.size); uint32_t amount = static_cast(strlen(val.string)) + 1; write(amount); if(amount) write(val.string, amount); } virtual void streamify(DataRef& val) { writeRef(val); } virtual void streamify(DataRef& val) { writeRef(val); } virtual void streamify(DataRef& val) { writeRef(val); } virtual uint32_t hasData() { return false; } virtual bool isGood() { return true; } private: RenderWriter& operator=(const RenderWriter&); }; struct UserRenderer : public PvdUserRenderer { ForwardingMemoryBuffer mBuffer; uint32_t mBufferCapacity; RendererEventClient* mClient; UserRenderer(uint32_t bufferFullAmount) : mBuffer("UserRenderBuffer"), mBufferCapacity(bufferFullAmount), mClient(NULL) { } virtual ~UserRenderer() { } virtual void release() { PVD_DELETE(this); } template void handleEvent(TEventType evt) { RenderWriter _writer(mBuffer); RenderSerializer& writer(_writer); PvdUserRenderTypes::Enum evtType(getPvdRenderTypeFromType()); writer.streamify(evtType); evt.serialize(writer); if(mBuffer.size() >= mBufferCapacity) flushRenderEvents(); } virtual void setInstanceId(const void* iid) { handleEvent(SetInstanceIdRenderEvent(PVD_POINTER_TO_U64(iid))); } // Draw these points associated with this instance virtual void drawPoints(const PxDebugPoint* points, uint32_t count) { handleEvent(PointsRenderEvent(points, count)); } // Draw these lines associated with this instance virtual void drawLines(const PxDebugLine* lines, uint32_t count) { handleEvent(LinesRenderEvent(lines, count)); } // Draw these triangles associated with this instance virtual void drawTriangles(const PxDebugTriangle* triangles, uint32_t count) { handleEvent(TrianglesRenderEvent(triangles, count)); } virtual void drawText(const PxDebugText& text) { handleEvent(TextRenderEvent(text)); } virtual void drawRenderbuffer(const PxDebugPoint* pointData, uint32_t pointCount, const PxDebugLine* lineData, uint32_t lineCount, const PxDebugTriangle* triangleData, uint32_t triangleCount) { handleEvent(DebugRenderEvent(pointData, pointCount, lineData, lineCount, triangleData, triangleCount)); } // Constraint visualization routines virtual void visualizeJointFrames(const PxTransform& parent, const PxTransform& child) PX_OVERRIDE { handleEvent(JointFramesRenderEvent(parent, child)); } virtual void visualizeLinearLimit(const PxTransform& t0, const PxTransform& t1, float value) PX_OVERRIDE { handleEvent(LinearLimitRenderEvent(t0, t1, value, true)); } virtual void visualizeAngularLimit(const PxTransform& t0, float lower, float upper) PX_OVERRIDE { handleEvent(AngularLimitRenderEvent(t0, lower, upper, true)); } virtual void visualizeLimitCone(const PxTransform& t, float tanQSwingY, float tanQSwingZ) PX_OVERRIDE { handleEvent(LimitConeRenderEvent(t, tanQSwingY, tanQSwingZ, true)); } virtual void visualizeDoubleCone(const PxTransform& t, float angle) PX_OVERRIDE { handleEvent(DoubleConeRenderEvent(t, angle, true)); } // Clear the immedate buffer. virtual void flushRenderEvents() { if(mClient) mClient->handleBufferFlush(mBuffer.begin(), mBuffer.size()); mBuffer.clear(); } virtual void setClient(RendererEventClient* client) { mClient = client; } private: UserRenderer& operator=(const UserRenderer&); }; template struct RenderReader : public RenderSerializer { MemPvdInputStream mStream; ForwardingMemoryBuffer& mBuffer; RenderReader(ForwardingMemoryBuffer& buf) : mBuffer(buf) { } void setData(DataRef data) { mStream.setup(const_cast(data.begin()), const_cast(data.end())); } virtual void streamify(uint32_t& val) { mStream >> val; } virtual void streamify(uint64_t& val) { mStream >> val; } virtual void streamify(float& val) { mStream >> val; } virtual void streamify(uint8_t& val) { mStream >> val; } template void readRef(DataRef& val) { uint32_t count; mStream >> count; uint32_t numBytes = sizeof(TDataType) * count; TDataType* dataPtr = reinterpret_cast(mBuffer.growBuf(numBytes)); mStream.read(reinterpret_cast(dataPtr), numBytes); val = DataRef(dataPtr, count); } virtual void streamify(DataRef& val) { readRef(val); } virtual void streamify(DataRef& val) { readRef(val); } virtual void streamify(DataRef& val) { readRef(val); } virtual void streamify(PxDebugText& val) { mStream >> val.color; mStream >> val.position; mStream >> val.size; uint32_t len = 0; mStream >> len; uint8_t* dataPtr = mBuffer.growBuf(len); mStream.read(dataPtr, len); val.string = reinterpret_cast(dataPtr); } virtual void streamify(DataRef& val) { readRef(val); } virtual bool isGood() { return mStream.isGood(); } virtual uint32_t hasData() { return uint32_t(mStream.size() > 0); } private: RenderReader& operator=(const RenderReader&); }; template <> struct RenderReader : public RenderSerializer { MemPvdInputStream mStream; ForwardingMemoryBuffer& mBuffer; RenderReader(ForwardingMemoryBuffer& buf) : mBuffer(buf) { } void setData(DataRef data) { mStream.setup(const_cast(data.begin()), const_cast(data.end())); } template void read(TDataType& val) { mStream >> val; swapBytes(val); } virtual void streamify(uint64_t& val) { read(val); } virtual void streamify(uint32_t& val) { read(val); } virtual void streamify(float& val) { read(val); } virtual void streamify(uint8_t& val) { read(val); } template void readRef(DataRef& val) { uint32_t count; mStream >> count; swapBytes(count); uint32_t numBytes = sizeof(TDataType) * count; TDataType* dataPtr = reinterpret_cast(mBuffer.growBuf(numBytes)); PVD_FOREACH(idx, count) RenderSerializerMap().serialize(*this, dataPtr[idx]); val = DataRef(dataPtr, count); } virtual void streamify(DataRef& val) { readRef(val); } virtual void streamify(DataRef& val) { readRef(val); } virtual void streamify(DataRef& val) { readRef(val); } virtual void streamify(PxDebugText& val) { mStream >> val.color; mStream >> val.position; mStream >> val.size; uint32_t len = 0; mStream >> len; uint8_t* dataPtr = mBuffer.growBuf(len); mStream.read(dataPtr, len); val.string = reinterpret_cast(dataPtr); } virtual void streamify(DataRef& val) { readRef(val); } virtual bool isGood() { return mStream.isGood(); } virtual uint32_t hasData() { return uint32_t(mStream.size() > 0); } private: RenderReader& operator=(const RenderReader&); }; } PvdUserRenderer* PvdUserRenderer::create(uint32_t bufferSize) { return PVD_NEW(UserRenderer)(bufferSize); }