fix for draw cone and draw cylinder

these werent rendering correctly and we suspect draw cone was trying to draw more than it was allocating. On a volatle buffer that causes issues.
This commit is contained in:
marauder2k7 2025-07-31 17:55:38 +01:00
parent 1b7768925b
commit b9193072c1
2 changed files with 112 additions and 93 deletions

View file

@ -1486,69 +1486,73 @@ void GFXDrawUtil::_drawWireCapsule( const GFXStateBlockDesc &desc, const Point3F
void GFXDrawUtil::drawCone( const GFXStateBlockDesc &desc, const Point3F &basePnt, const Point3F &tipPnt, F32 baseRadius, const ColorI &color ) void GFXDrawUtil::drawCone( const GFXStateBlockDesc &desc, const Point3F &basePnt, const Point3F &tipPnt, F32 baseRadius, const ColorI &color )
{ {
VectorF uvec = tipPnt - basePnt; VectorF dir = tipPnt - basePnt;
F32 height = uvec.len(); F32 height = dir.len();
uvec.normalize(); dir.normalize();
MatrixF mat( true );
MathUtils::getMatrixFromUpVector( uvec, &mat );
mat.setPosition(basePnt);
Point3F scale( baseRadius, baseRadius, height ); MatrixF mat(true);
mat.scale(scale); MathUtils::getMatrixFromUpVector(dir, &mat);
mat.setPosition(basePnt);
mat.scale(Point3F(baseRadius, baseRadius, height));
GFXTransformSaver saver; GFXTransformSaver saver;
mDevice->pushWorldMatrix(); mDevice->pushWorldMatrix();
mDevice->multWorld(mat); mDevice->multWorld(mat);
S32 numPoints = sizeof(circlePoints)/sizeof(Point2F); const S32 numPoints = sizeof(circlePoints) / sizeof(Point2F);
GFXVertexBufferHandle<GFXVertexPCT> verts(mDevice, numPoints * 3 + 2, GFXBufferTypeVolatile);
// Vertex index layout
const S32 baseCenterIdx = 0;
const S32 baseStartIdx = 1;
const S32 tipIdx = baseStartIdx + numPoints;
const S32 sideStartIdx = tipIdx + 1;
const S32 totalVerts = sideStartIdx + numPoints * 3;
GFXVertexBufferHandle<GFXVertexPCT> verts(mDevice, totalVerts, GFXBufferTypeVolatile);
verts.lock(); verts.lock();
F32 sign = -1.f;
S32 indexDown = 0; //counting down from numPoints
S32 indexUp = 0; //counting up from 0
S32 index = 0; //circlePoints index for cap
for (S32 i = 0; i < numPoints + 1; i++) // Base center vertex (at origin in local space)
verts[baseCenterIdx].point = Point3F(0, 0, 0);
verts[baseCenterIdx].color = color;
// Base circle vertices
for (S32 i = 0; i < numPoints; i++)
{ {
//Top cap verts[baseStartIdx + i].point = Point3F(circlePoints[i].x, circlePoints[i].y, 0);
if (i != numPoints) verts[baseStartIdx + i].color = color;
{ }
if (sign < 0)
index = indexDown;
else
index = indexUp;
verts[i].point = Point3F(circlePoints[index].x, circlePoints[index].y, 0); // Tip vertex (pointing "up" in local Z)
verts[i].color = color; verts[tipIdx].point = Point3F(0, 0, 1);
verts[tipIdx].color = color;
if (sign < 0) // Side triangles: one triangle per segment
indexUp += 1; for (S32 i = 0; i < numPoints; i++)
else {
indexDown = numPoints - indexUp; S32 triBase = sideStartIdx + i * 3;
// invert sign // Each triangle is (tip, base[i], base[(i+1)%numPoints])
sign *= -1.0f; verts[triBase + 0].point = verts[tipIdx].point;
} verts[triBase + 1].point = verts[baseStartIdx + i].point;
verts[triBase + 2].point = verts[baseStartIdx + ((i + 1) % numPoints)].point;
//cone verts[triBase + 0].color = color;
S32 imod = i % numPoints; verts[triBase + 1].color = color;
S32 vertindex = 2 * i + numPoints; verts[triBase + 2].color = color;
verts[vertindex].point = Point3F(circlePoints[imod].x, circlePoints[imod].y, 0);
verts[vertindex].color = color;
verts[vertindex + 1].point = Point3F(0.0f, 0.0f, 1.0f);
verts[vertindex + 1].color = color;
} }
verts.unlock(); verts.unlock();
mDevice->setStateBlockByDesc( desc ); mDevice->setStateBlockByDesc(desc);
mDevice->setVertexBuffer(verts);
mDevice->setVertexBuffer( verts );
mDevice->setupGenericShaders(); mDevice->setupGenericShaders();
mDevice->drawPrimitive(GFXTriangleStrip, 0, numPoints - 2); // Draw base cap using triangle fan
mDevice->drawPrimitive(GFXTriangleStrip, numPoints, numPoints * 2); mDevice->drawPrimitive(GFXTriangleList, baseCenterIdx, numPoints - 2);
// Draw sides using triangle list
mDevice->drawPrimitive(GFXTriangleList, sideStartIdx, numPoints);
mDevice->popWorldMatrix(); mDevice->popWorldMatrix();
@ -1556,71 +1560,89 @@ void GFXDrawUtil::drawCone( const GFXStateBlockDesc &desc, const Point3F &basePn
void GFXDrawUtil::drawCylinder( const GFXStateBlockDesc &desc, const Point3F &basePnt, const Point3F &tipPnt, F32 radius, const ColorI &color ) void GFXDrawUtil::drawCylinder( const GFXStateBlockDesc &desc, const Point3F &basePnt, const Point3F &tipPnt, F32 radius, const ColorI &color )
{ {
VectorF uvec = tipPnt - basePnt; VectorF dir = tipPnt - basePnt;
F32 height = uvec.len(); F32 height = dir.len();
uvec.normalize(); dir.normalize();
MatrixF mat( true );
MathUtils::getMatrixFromUpVector( uvec, &mat ); MatrixF mat(true);
MathUtils::getMatrixFromUpVector(dir, &mat);
mat.setPosition(basePnt); mat.setPosition(basePnt);
mat.scale(Point3F(radius, radius, height));
Point3F scale( radius, radius, height * 2 );
mat.scale(scale);
GFXTransformSaver saver; GFXTransformSaver saver;
mDevice->pushWorldMatrix(); mDevice->pushWorldMatrix();
mDevice->multWorld(mat); mDevice->multWorld(mat);
S32 numPoints = sizeof(circlePoints) / sizeof(Point2F); const S32 numPoints = sizeof(circlePoints) / sizeof(Point2F);
GFXVertexBufferHandle<GFXVertexPCT> verts(mDevice, numPoints *4 + 2, GFXBufferTypeVolatile);
// Vertex index layout
const S32 baseCenterIdx = 0;
const S32 topCenterIdx = 1;
const S32 baseStartIdx = 2;
const S32 topStartIdx = baseStartIdx + numPoints;
const S32 sideStartIdx = topStartIdx + numPoints;
const S32 totalVerts = sideStartIdx + numPoints * 6;
GFXVertexBufferHandle<GFXVertexPCT> verts(mDevice, totalVerts, GFXBufferTypeVolatile);
verts.lock(); verts.lock();
F32 sign = -1.f;
S32 indexDown = 0; //counting down from numPoints
S32 indexUp = 0; //counting up from 0
S32 index = 0; //circlePoints index for caps
for (S32 i = 0; i < numPoints + 1; i++) // Base center
verts[baseCenterIdx].point = Point3F(0, 0, 0);
verts[baseCenterIdx].color = color;
// Top center
verts[topCenterIdx].point = Point3F(0, 0, 1);
verts[topCenterIdx].color = color;
// Base circle
for (S32 i = 0; i < numPoints; ++i)
{ {
//Top/Bottom cap verts[baseStartIdx + i].point = Point3F(circlePoints[i].x, circlePoints[i].y, 0);
if (i != numPoints) verts[baseStartIdx + i].color = color;
{ }
if (sign < 0)
index = indexDown;
else
index = indexUp;
verts[i].point = Point3F(circlePoints[index].x, circlePoints[index].y, 0); // Top circle
verts[i].color = color; for (S32 i = 0; i < numPoints; ++i)
verts[i + numPoints].point = Point3F(circlePoints[index].x, circlePoints[index].y, 0.5f); {
verts[i + numPoints].color = color; verts[topStartIdx + i].point = Point3F(circlePoints[i].x, circlePoints[i].y, 1.0f);
verts[topStartIdx + i].color = color;
}
if (sign < 0) // Side triangles
indexUp += 1; for (S32 i = 0; i < numPoints; ++i)
else {
indexDown = numPoints - indexUp; S32 next = (i + 1) % numPoints;
S32 idx = sideStartIdx + i * 6;
// invert sign // First triangle (base[i], base[next], top[i])
sign *= -1.0f; verts[idx + 0].point = verts[baseStartIdx + i].point;
} verts[idx + 1].point = verts[baseStartIdx + next].point;
verts[idx + 2].point = verts[topStartIdx + i].point;
//cylinder // Second triangle (top[i], base[next], top[next])
S32 imod = i % numPoints; verts[idx + 3].point = verts[topStartIdx + i].point;
S32 vertindex = 2 * i + (numPoints * 2); verts[idx + 4].point = verts[baseStartIdx + next].point;
verts[vertindex].point = Point3F(circlePoints[imod].x, circlePoints[imod].y, 0); verts[idx + 5].point = verts[topStartIdx + next].point;
verts[vertindex].color = color;
verts[vertindex + 1].point = Point3F(circlePoints[imod].x, circlePoints[imod].y, 0.5f); for (int j = 0; j < 6; ++j)
verts[vertindex + 1].color = color; verts[idx + j].color = color;
} }
verts.unlock(); verts.unlock();
mDevice->setStateBlockByDesc( desc ); mDevice->setStateBlockByDesc(desc);
mDevice->setVertexBuffer(verts);
mDevice->setVertexBuffer( verts );
mDevice->setupGenericShaders(); mDevice->setupGenericShaders();
mDevice->drawPrimitive( GFXTriangleStrip, 0, numPoints-2 ); // Draw base cap
mDevice->drawPrimitive( GFXTriangleStrip, numPoints, numPoints - 2); mDevice->drawPrimitive(GFXTriangleList, baseCenterIdx, numPoints - 2);
mDevice->drawPrimitive( GFXTriangleStrip, numPoints*2, numPoints * 2);
// Draw top cap
mDevice->drawPrimitive(GFXTriangleList, topCenterIdx, numPoints - 2);
// Draw sides (2 triangles per segment)
mDevice->drawPrimitive(GFXTriangleList, sideStartIdx, numPoints * 2);
mDevice->popWorldMatrix(); mDevice->popWorldMatrix();
} }

View file

@ -704,9 +704,6 @@ inline void GFXGLDevice::postDrawPrimitive(U32 primitiveCount)
{ {
mDeviceStatistics.mDrawCalls++; mDeviceStatistics.mDrawCalls++;
mDeviceStatistics.mPolyCount += primitiveCount; mDeviceStatistics.mPolyCount += primitiveCount;
mVolatileVBs.clear();
mVolatilePBs.clear();
} }
void GFXGLDevice::drawPrimitive( GFXPrimitiveType primType, U32 vertexStart, U32 primitiveCount ) void GFXGLDevice::drawPrimitive( GFXPrimitiveType primType, U32 vertexStart, U32 primitiveCount )