Files
PhysX4.1/kaplademo/source/kaplaDemo/Fracture/ConvexRenderer.cpp
2025-11-28 23:13:44 +05:30

403 lines
12 KiB
C++

//
// 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) 2018 NVIDIA Corporation. All rights reserved.
#include "Shader.h"
#include "ConvexRenderer.h"
#include "Compound.h"
#include <foundation/PxMat44.h>
//--------------------------------------------------------
ConvexRenderer::ConvexRenderer()
{
init();
}
//--------------------------------------------------------
ConvexRenderer::~ConvexRenderer()
{
}
//--------------------------------------------------------
void ConvexRenderer::init()
{
mShader = NULL;
mShaderMat.init();
mBumpTextureUVScale = 0.1f;
mExtraNoiseScale = 2.0f;
mRoughnessScale = 0.2f;
mDiffuseTexArray = 0;
mBumpTexArray = 0;
mSpecularTexArray = 0;
mEmissiveReflectSpecPowerTexArray = 0;
mActive = true;
}
//--------------------------------------------------------
void ConvexRenderer::add(const base::Convex* convex, Shader* shader)
{
if (!mActive)
return;
ConvexGroup *g;
// int gnr = 0; // to search all groups
int gnr = 0;// !mGroups.empty() ? mGroups.size() - 1 : 0; // to search only last
int numNewVerts = convex->getVisVertices().size();
while (gnr < (int)mGroups.size() && (mGroups[gnr]->numVertices + numNewVerts >= maxVertsPerGroup || mGroups[gnr]->mShader != shader))
gnr++;
if (gnr == (int)mGroups.size()) { // create new group
g = new ConvexGroup();
g->init();
g->mShader = shader;
gnr = mGroups.size();
mGroups.push_back(g);
}
g = mGroups[gnr];
convex->setConvexRendererInfo(gnr, g->convexes.size());
g->convexes.push_back((Convex*)convex);
g->numIndices += convex->getVisTriIndices().size();
g->numVertices += convex->getVisVertices().size();
g->dirty = true;
}
//--------------------------------------------------------
void ConvexRenderer::remove(const base::Convex* convex)
{
if (!mActive)
return;
int gnr = convex->getConvexRendererGroupNr();
int pos = convex->getConvexRendererGroupPos();
if (gnr < 0 || gnr >= (int)mGroups.size())
return;
ConvexGroup *g = mGroups[gnr];
if (pos < 0 || pos > (int)g->convexes.size())
return;
if (g->convexes[pos] != convex)
return;
g->numIndices -= convex->getVisTriIndices().size();
g->numVertices -= convex->getVisVertices().size();
g->convexes[pos] = g->convexes[g->convexes.size()-1];
g->convexes[pos]->setConvexRendererInfo(gnr, pos);
g->convexes.pop_back();
g->dirty = true;
}
//--------------------------------------------------------
void ConvexRenderer::updateRenderBuffers()
{
/*
static int maxNumV = 0;
static int maxNumI = 0;
static int maxNumC = 0;
static int maxNumG = 0;
if (mGroups.size() > maxNumG) maxNumG = mGroups.size();
*/
for (int i = 0; i < (int)mGroups.size(); i++) {
ConvexGroup *g = mGroups[i];
if (!g->dirty)
continue;
if (g->numIndices == 0 || g->numVertices == 0)
continue;
if (!g->VBO) {
glGenBuffersARB(1, &g->VBO);
}
if (!g->IBO) {
glGenBuffersARB(1, &g->IBO);
}
if (!g->matTex) {
glGenTextures(1, &g->matTex);
glBindTexture(GL_TEXTURE_2D, g->matTex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glBindTexture(GL_TEXTURE_2D, 0);
}
if (g->numVertices == 0 || g->numIndices == 0)
return;
// recalculate in case they have changed
g->numVertices = 0;
g->numIndices = 0;
for (int i = 0; i < (int)g->convexes.size(); i++) {
g->numVertices += g->convexes[i]->getVisVertices().size();
g->numIndices += g->convexes[i]->getVisTriIndices().size();
}
g->vertices.resize(g->numVertices*12);
g->indices.resize(g->numIndices);
float* vp = &g->vertices[0];
unsigned int* ip = &g->indices[0];
int sumV = 0;
// Make cpu copy of VBO and IBO
int convexNr = 0;
for (int j = 0; j < (int)g->convexes.size(); j++, convexNr++) {
const Convex* c = g->convexes[j];
// PxVec3 matOff = c->getMaterialOffset();
int nv = c->getVisVertices().size();
int ni = c->getVisTriIndices().size();
if (nv > 0) {
float* cvp = (float*)&c->getVisVertices()[0]; // float3
float* cnp = (float*)&c->getVisNormals()[0]; // float3
// float* c3dtp = (float*)&c->getVisVertices()[0]; // float3
float* c2dtp = (float*)&c->getVisTexCoords()[0]; // float2
float* ctanp = (float*)&c->getVisTangents()[0]; // float3
int* cip = (int*)&c->getVisTriIndices()[0];
for (int k = 0; k < nv; k++) {
*(vp++) = *(cvp++);
*(vp++) = *(cvp++);
*(vp++) = *(cvp++);
*(vp++) = *(cnp++);
*(vp++) = *(cnp++);
*(vp++) = *(cnp++);
*(vp++) = *(ctanp++);
*(vp++) = *(ctanp++);
*(vp++) = *(ctanp++);
*(vp++) = (float)convexNr;
*(vp++) = *(c2dtp++);
*(vp++) = *(c2dtp++);
}
for (int k = 0; k < ni; k++) {
*(ip++) = *(cip++) + sumV;
}
}
//memcpy(ip, cip, sizeof(int)*ni);
//ip += 3*ni;
//std::vector<PxVec3> mTriVertices;
//std::vector<PxVec3> mTriNormals;
//std::vector<int> mTriIndices;
//std::vector<float> mTriTexCoords; // 3d + obj nr
sumV += nv;
}
/*
if (g->vertices.size() > maxNumV) maxNumV = g->vertices.size();
if (g->indices.size() > maxNumI) maxNumI = g->indices.size();
if (g->convexes.size() > maxNumC) maxNumC = g->convexes.size();
*/
glBindBufferARB(GL_ARRAY_BUFFER_ARB, g->VBO);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, g->vertices.size()*sizeof(float), &g->vertices[0], GL_DYNAMIC_DRAW);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, g->IBO);
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, g->indices.size()*sizeof(unsigned int), &g->indices[0], GL_DYNAMIC_DRAW);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
int oldTexSize = g->texSize;
if (g->texSize == 0) {
// First time
oldTexSize = 1;
g->texSize = 32;
}
while (1) {
int convexesPerRow = g->texSize / 4;
if (convexesPerRow * g->texSize >= (int)g->convexes.size()) {
break;
} else {
g->texSize *= 2;
}
}
if (g->texSize != oldTexSize) {
g->texCoords.resize(g->texSize*g->texSize*4);
// Let's allocate texture
glBindTexture(GL_TEXTURE_2D, g->matTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, g->texSize, g->texSize, 0, GL_RGBA, GL_FLOAT, 0);
glBindTexture(GL_TEXTURE_2D, 0);
}
g->dirty = false;
}
// printf("maxV = %d, maxI = %d, maxC = %d, maxG = %d\n", maxNumV, maxNumI, maxNumC, maxNumG);
}
//--------------------------------------------------------
void ConvexRenderer::updateTransformations()
{
for (int i = 0; i < (int)mGroups.size(); i++) {
ConvexGroup *g = mGroups[i];
if (g->texCoords.empty())
continue;
float* tt = &g->texCoords[0];
for (int j = 0; j < (int)g->convexes.size(); j++) {
const Convex* c = g->convexes[j];
PxMat44 pose(c->getGlobalPose());
float* mp = (float*)pose.front();
float* ta = tt;
for (int k = 0; k < 16; k++) {
*(tt++) = *(mp++);
}
PxVec3 matOff = c->getMaterialOffset();
ta[3] = matOff.x;
ta[7] = matOff.y;
ta[11] = matOff.z;
int idFor2DTex = c->getSurfaceMaterialId();
int idFor3DTex = c->getMaterialId();
const int MAX_3D_TEX = 8;
ta[15] = (float)(idFor2DTex*MAX_3D_TEX + idFor3DTex);
}
glBindTexture(GL_TEXTURE_2D, g->matTex);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, g->texSize, g->texSize,
GL_RGBA, GL_FLOAT, &g->texCoords[0]);
glBindTexture(GL_TEXTURE_2D, 0);
}
}
//--------------------------------------------------------
void ConvexRenderer::render()
{
if (!mActive)
return;
updateRenderBuffers();
updateTransformations();
for (int i = 0; i < (int)mGroups.size(); i++) {
ConvexGroup *g = mGroups[i];
Shader* shader = mShader;
if (g->mShader != NULL)
shader = g->mShader;
shader->activate(mShaderMat);
// Assume convex all use the same shader
glActiveTexture(GL_TEXTURE7);
glBindTexture(GL_TEXTURE_3D, volTex);
glActiveTexture(GL_TEXTURE8);
glBindTexture(GL_TEXTURE_2D, g->matTex);
glActiveTexture(GL_TEXTURE10);
glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, mDiffuseTexArray);
glActiveTexture(GL_TEXTURE11);
glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, mBumpTexArray);
glActiveTexture(GL_TEXTURE12);
glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, mSpecularTexArray);
glActiveTexture(GL_TEXTURE13);
glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, mEmissiveReflectSpecPowerTexArray);
glActiveTexture(GL_TEXTURE0);
float itt = 1.0f/g->texSize;
shader->setUniform("diffuseTexArray", 10);
shader->setUniform("bumpTexArray", 11);
shader->setUniform("specularTexArray", 12);
shader->setUniform("emissiveReflectSpecPowerTexArray", 13);
shader->setUniform("ttt3D", 7);
shader->setUniform("transTex", 8);
shader->setUniform("transTexSize", g->texSize);
shader->setUniform("iTransTexSize", itt);
shader->setUniform("bumpTextureUVScale", mBumpTextureUVScale);
shader->setUniform("extraNoiseScale", mExtraNoiseScale);
shader->setUniform("roughnessScale", mRoughnessScale);
if (mShaderMat.color[3] < 1.0f) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_DEPTH_TEST);
glColor4f(mShaderMat.color[0], mShaderMat.color[1], mShaderMat.color[2], mShaderMat.color[3]);
}
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glClientActiveTexture(GL_TEXTURE0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, g->VBO);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, g->IBO);
int stride = 12*sizeof(float);
glVertexPointer(3, GL_FLOAT, stride, 0);
glNormalPointer(GL_FLOAT, stride, (void*)(3*sizeof(float)));
glTexCoordPointer(4, GL_FLOAT, stride, (void*)(6*sizeof(float)));
glClientActiveTexture(GL_TEXTURE1);
glTexCoordPointer(2, GL_FLOAT, stride, (void*)(10*sizeof(float)));
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glDrawElements(GL_TRIANGLES, g->numIndices, GL_UNSIGNED_INT, 0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTexture(GL_TEXTURE0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
if (mShaderMat.color[3] < 1.0f) {
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
}
shader->deactivate();
}
}