485 lines
18 KiB
C++
485 lines
18 KiB
C++
/**
|
|
@file JCWebGLPlus.cpp
|
|
@brief
|
|
@author James
|
|
@version 1.0
|
|
@date 2019_8_24
|
|
*/
|
|
|
|
#include "JCWebGLPlus.h"
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include "math/JCBoundingFrustum.h"
|
|
#include "math/JCBoundingBox.h"
|
|
#include "math/JCBoundingSphere.h"
|
|
#include "Log.h"
|
|
|
|
|
|
namespace laya
|
|
{
|
|
JCWebGLPlus* JCWebGLPlus::s_pWebGLPlus = NULL;
|
|
JCWebGLPlus::JCWebGLPlus()
|
|
{
|
|
m_pJSArrayBufferManager = NULL;
|
|
m_pJSABManagerSyncToRender = NULL;
|
|
m_pRArrayBufferManager = NULL;
|
|
m_nThreadMODE = THREAD_MODE_DOUBLE;
|
|
s_pWebGLPlus = this;
|
|
}
|
|
JCWebGLPlus::~JCWebGLPlus()
|
|
{
|
|
s_pWebGLPlus = NULL;
|
|
|
|
if (m_pJSArrayBufferManager)
|
|
{
|
|
delete m_pJSArrayBufferManager;
|
|
m_pJSArrayBufferManager = NULL;
|
|
}
|
|
if (m_pJSABManagerSyncToRender)
|
|
{
|
|
delete m_pJSABManagerSyncToRender;
|
|
m_pJSABManagerSyncToRender = NULL;
|
|
}
|
|
if (m_nThreadMODE == THREAD_MODE_DOUBLE)
|
|
{
|
|
if (m_pRArrayBufferManager)
|
|
{
|
|
delete m_pRArrayBufferManager;
|
|
m_pRArrayBufferManager = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_pRArrayBufferManager = NULL;
|
|
}
|
|
|
|
clean();
|
|
}
|
|
JCWebGLPlus* JCWebGLPlus::getInstance()
|
|
{
|
|
return s_pWebGLPlus ? s_pWebGLPlus : new JCWebGLPlus();
|
|
}
|
|
void JCWebGLPlus::releaseInstance()
|
|
{
|
|
if (s_pWebGLPlus)
|
|
{
|
|
delete s_pWebGLPlus;
|
|
s_pWebGLPlus = NULL;
|
|
}
|
|
}
|
|
void JCWebGLPlus::init(int nThreadMode)
|
|
{
|
|
if (m_pJSArrayBufferManager == NULL)
|
|
{
|
|
m_nThreadMODE = nThreadMode;
|
|
m_pJSArrayBufferManager = new JCArrayBufferManager();
|
|
m_pJSABManagerSyncToRender = new JCArrayBufferManager();
|
|
|
|
if (nThreadMode == THREAD_MODE_SINGLE)
|
|
{
|
|
m_pRArrayBufferManager = m_pJSArrayBufferManager;
|
|
}
|
|
else if(nThreadMode == THREAD_MODE_DOUBLE)
|
|
{
|
|
m_pRArrayBufferManager = new JCArrayBufferManager();
|
|
}
|
|
else
|
|
{
|
|
LOGE("JCWebGLPlus::init thread mode error");
|
|
m_nThreadMODE = THREAD_MODE_DOUBLE;
|
|
m_pRArrayBufferManager = new JCArrayBufferManager();
|
|
}
|
|
}
|
|
}
|
|
void JCWebGLPlus::matrix4x4MultiplyFFF(float* a, float* b, float* e)
|
|
{
|
|
int i = 0;
|
|
float ai0, ai1, ai2, ai3;
|
|
float b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
|
|
float b4 = b[4], b5 = b[5], b6 = b[6], b7 = b[7];
|
|
float b8 = b[8], b9 = b[9], b10 = b[10], b11 = b[11];
|
|
float b12 = b[12], b13 = b[13], b14 = b[14], b15 = b[15];
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
ai0 = a[i];
|
|
ai1 = a[i + 4];
|
|
ai2 = a[i + 8];
|
|
ai3 = a[i + 12];
|
|
e[i] = ai0 * b0 + ai1 * b1 + ai2 * b2 + ai3 * b3;
|
|
e[i + 4] = ai0 * b4 + ai1 * b5 + ai2 * b6 + ai3 * b7;
|
|
e[i + 8] = ai0 * b8 + ai1 * b9 + ai2 * b10 + ai3 * b11;
|
|
e[i + 12] = ai0 * b12 + ai1 * b13 + ai2 * b14 + ai3 * b15;
|
|
}
|
|
}
|
|
void JCWebGLPlus::calcMatrix(float* pos, float* scale, float* quat, float* outE) {
|
|
float x = quat[0], y = quat[1], z = quat[2], w = quat[3],
|
|
x2 = x + x,
|
|
y2 = y + y,
|
|
z2 = z + z;
|
|
float xx = x * x2,
|
|
xy = x * y2,
|
|
xz = x * z2,
|
|
yy = y * y2,
|
|
yz = y * z2,
|
|
zz = z * z2;
|
|
|
|
float wx = w * x2,
|
|
wy = w * y2,
|
|
wz = w * z2,
|
|
sx = scale[0],
|
|
sy = scale[1],
|
|
sz = scale[2];
|
|
|
|
outE[0] = (1 - (yy + zz)) * sx;
|
|
outE[1] = (xy + wz) * sx;
|
|
outE[2] = (xz - wy) * sx;
|
|
outE[3] = 0;
|
|
outE[4] = (xy - wz) * sy;
|
|
outE[5] = (1 - (xx + zz)) * sy;
|
|
outE[6] = (yz + wx) * sy;
|
|
outE[7] = 0;
|
|
outE[8] = (xz + wy) * sz;
|
|
outE[9] = (yz - wx) * sz;
|
|
outE[10] = (1 - (xx + yy)) * sz;
|
|
outE[11] = 0;
|
|
outE[12] = pos[0];
|
|
outE[13] = pos[1];
|
|
outE[14] = pos[2];
|
|
outE[15] = 1;
|
|
}
|
|
|
|
int JCWebGLPlus::culling3D(int cullingCount, char* pFrustumBuffer, int nFrustumLen, char* pCullingBuffer, int nCullingBufferLen,
|
|
char* pCullingBufferIndices, int nCullingBufferIndicesLen, char* pCullingBufferResult, int nCullingBufferResultLen)
|
|
{
|
|
float* pF32FrustumBuffer = (float*)pFrustumBuffer;
|
|
float* pF32CullingBuffer = (float*)pCullingBuffer;
|
|
int* pI32CullingBufferIndices = (int*)pCullingBufferIndices;
|
|
int* pI32CullingBufferResult = (int*)pCullingBufferResult;
|
|
int nResultCount = cullingCount;
|
|
JCBoundingFrustum kFrustum;
|
|
kFrustum.setValues(pF32FrustumBuffer);
|
|
JCBoundingBox kBox;
|
|
JCBoundingSphere kSphere;
|
|
for (int i = 0; i < cullingCount; i++)
|
|
{
|
|
int nIndex = pI32CullingBufferIndices[i];
|
|
int nType = (int)(pF32CullingBuffer[nIndex]);
|
|
bool bSucess = true;
|
|
switch (nType)
|
|
{
|
|
case 0:
|
|
bSucess = true;
|
|
break;
|
|
case 1:
|
|
kSphere.setValues(pF32CullingBuffer + nIndex + 1);
|
|
bSucess = kFrustum.containsBoundingSphere(kSphere) != CT_DISJOINT;
|
|
break;
|
|
case 2:
|
|
kBox.setValues(pF32CullingBuffer + nIndex + 1);
|
|
//bSucess = kFrustum.containsAxisAlignedBouningBox(kBox) != CT_DISJOINT;
|
|
bSucess = kFrustum.intersects(kBox);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if (bSucess)
|
|
{
|
|
pI32CullingBufferResult[i] = 1;
|
|
}
|
|
else
|
|
{
|
|
pI32CullingBufferResult[i] = 0;
|
|
}
|
|
}
|
|
return nResultCount;
|
|
}
|
|
bool JCWebGLPlus::updateAnimationNodeWorldMatix3D(char* pLocPosition, int nLocPosLen, char* pLocRotation, int nLocRotLen, char* pLocScaling, int nLocScaLen,
|
|
char* pParentIndices, int nLocParentLen, char* pOutWorldMatrix, int nOutWorldLen)
|
|
{
|
|
float* pfLocPosition = (float*)pLocPosition; //vec3
|
|
float* pfLocRotation = (float*)pLocRotation; //
|
|
float* pfLocScaling = (float*)pLocScaling;
|
|
signed short* pfParentIndices = (signed short*)pParentIndices;
|
|
float* pfOutWorldMatrix = (float*)pOutWorldMatrix;
|
|
|
|
int boneNum = nLocParentLen / sizeof(signed short);
|
|
int matOutNum = nOutWorldLen / (sizeof(float) * 16);
|
|
if (boneNum > matOutNum)
|
|
{
|
|
//错误了
|
|
LOGE("输出矩阵空间太小,结果会不正确!");
|
|
boneNum = matOutNum;
|
|
}
|
|
float* pCurPos = pfLocPosition;
|
|
float* pCurScale = pfLocScaling;
|
|
float* pCurQuat = pfLocRotation;
|
|
float* pCurMat = pfOutWorldMatrix;
|
|
signed short* pCurPar = pfParentIndices;
|
|
float tmpMat[16];
|
|
for (int i = 0; i < boneNum; i++) {
|
|
calcMatrix(pCurPos, pCurScale, pCurQuat, pCurMat);
|
|
int par = *(pCurPar++);
|
|
if (par >= 0) {
|
|
if (par >= boneNum) {
|
|
LOGE("boneParent too big!");
|
|
}
|
|
else {
|
|
float* pParMat = pfOutWorldMatrix + par * 16;
|
|
matrix4x4MultiplyFFF(pParMat, pCurMat, tmpMat);
|
|
memcpy(pCurMat, tmpMat, 16 * sizeof(float));//用一个一个赋值吗
|
|
}
|
|
}
|
|
else {
|
|
pCurMat[1] = pCurMat[2] = pCurMat[3] = pCurMat[4] = pCurMat[6] = pCurMat[7] = pCurMat[8] = pCurMat[9] = pCurMat[11] = pCurMat[12] = pCurMat[13] = pCurMat[14] = 0;
|
|
pCurMat[0] = pCurMat[5] = pCurMat[10] = pCurMat[15] = 1;
|
|
}
|
|
pCurPos += 3;
|
|
pCurScale += 3;
|
|
pCurQuat += 4;
|
|
pCurMat += 16;
|
|
}
|
|
return true;
|
|
}
|
|
bool JCWebGLPlus::computeSubSkinnedData3D(char* pWorldMatrixs, int nWorldMatLen, char* pWorldMatrixIndex, int nWorldMatIndeLen,
|
|
char* pInverseBindPoses, int nInverseBindPosesLen, char* pBoneIndices, int nBoneIndicesLen,
|
|
char* pBindPoseIndices, int nBindPoseIndicesLen, char* pResultData, int nResultDataLen)
|
|
{
|
|
float* pF32WorldMatrixs = (float*)pWorldMatrixs;
|
|
unsigned short* pU16WorldMatrixIndex = (unsigned short*)pWorldMatrixIndex;
|
|
float* pF32InverseBindPoses = (float*)pInverseBindPoses;
|
|
unsigned short* pU16BoneIndices = (unsigned short*)pBoneIndices;
|
|
nBoneIndicesLen /= sizeof(unsigned short);
|
|
unsigned short* pU16BindPoseIndices = (unsigned short*)pBindPoseIndices;
|
|
float* pf32ResultData = (float*)pResultData;
|
|
//当前的骨头数量
|
|
for (int i = 0; i < nBoneIndicesLen; i++)
|
|
{
|
|
int nBoneIndex = pU16BoneIndices[i];//骨头的ID
|
|
//worldMartix的ID
|
|
int nWorldMatrixID = pU16WorldMatrixIndex[nBoneIndex];
|
|
//当前world Matrix
|
|
float* pCurWorldMatrix = pF32WorldMatrixs + nWorldMatrixID * 16;
|
|
//当前bindPoseID
|
|
int nBindPoseID = pU16BindPoseIndices[nBoneIndex];
|
|
//当前bind Pose Matrix
|
|
float* pCurBindMatrix = pF32InverseBindPoses + nBindPoseID * 16;
|
|
|
|
//计算
|
|
float* pResultMatrix = pf32ResultData + i * 16;
|
|
matrix4x4MultiplyFFF(pCurWorldMatrix, pCurBindMatrix, pResultMatrix);
|
|
}
|
|
return true;
|
|
}
|
|
void JCWebGLPlus::uniformMatrix2fvEx(GLuint location, GLboolean transpose, int id)
|
|
{
|
|
JCArrayBufferManager::ArrayBufferContent* pData = m_pRArrayBufferManager->getArrayBuffer(id);
|
|
if (pData)
|
|
{
|
|
uniformMatrix2fv(location, pData->m_nLength / sizeof(float) / 4, transpose, (float*)pData->m_pBuffer);
|
|
}
|
|
}
|
|
void JCWebGLPlus::uniformMatrix3fvEx(GLuint location, GLboolean transpose, int id)
|
|
{
|
|
JCArrayBufferManager::ArrayBufferContent* pData = m_pRArrayBufferManager->getArrayBuffer(id);
|
|
if (pData)
|
|
{
|
|
uniformMatrix3fv(location, pData->m_nLength / sizeof(float) / 9, transpose, (float*)pData->m_pBuffer);
|
|
}
|
|
}
|
|
void JCWebGLPlus::uniformMatrix4fvEx(GLuint location, GLboolean transpose, int id)
|
|
{
|
|
JCArrayBufferManager::ArrayBufferContent* pData = m_pRArrayBufferManager->getArrayBuffer(id);
|
|
if (pData)
|
|
{
|
|
uniformMatrix4fv(location, pData->m_nLength / sizeof(float) / 16, transpose, (float*)pData->m_pBuffer);
|
|
}
|
|
}
|
|
void JCWebGLPlus::uploadShaderUniforms(int nCmdID, int nDataID)
|
|
{
|
|
JCArrayBufferManager::ArrayBufferContent* pCmd = m_pRArrayBufferManager->getArrayBuffer(nCmdID);
|
|
JCArrayBufferManager::ArrayBufferContent* pData = m_pRArrayBufferManager->getArrayBuffer(nDataID);
|
|
if (pCmd && pData)
|
|
{
|
|
_uploadShaderUniforms(pCmd->getCommandEncoderBuffer(), pData->m_pBuffer, pData->m_nLength);
|
|
}
|
|
}
|
|
void JCWebGLPlus::uploadShaderUniformsBuffer(int nCmdID, char* pData, int nDataSize)
|
|
{
|
|
JCArrayBufferManager::ArrayBufferContent* pCmd = m_pRArrayBufferManager->getArrayBuffer(nCmdID);
|
|
if (pCmd && pData)
|
|
{
|
|
_uploadShaderUniforms(pCmd->getCommandEncoderBuffer(), pData, nDataSize);
|
|
}
|
|
}
|
|
void JCWebGLPlus::_uploadShaderUniforms(JCCommandEncoderBuffer* pCmd, char* data, int dataSize)
|
|
{
|
|
if (pCmd == NULL)return;
|
|
pCmd->setReadPos(0);
|
|
int nLen = pCmd->getDataSize();
|
|
while (pCmd->getReadPos() < (size_t)nLen)
|
|
{
|
|
//i=funID j=uniformFunID k=location l=type m=offset
|
|
WEBGLPLUS_iiiiii* pParam = pCmd->popp<WEBGLPLUS_iiiiii>();
|
|
UNIFORM_FUN nFun = (UNIFORM_FUN)pParam->c;
|
|
int nLocation = pParam->d;
|
|
int nType = pParam->e;
|
|
int nOffset = pParam->f * 4;
|
|
int nTextureLocation = pParam->g;
|
|
switch (nFun)
|
|
{
|
|
case laya::UNIFORM1F:
|
|
{
|
|
float value = *(float*)(data + nOffset);
|
|
this->uniform1f(nLocation, value);
|
|
break;
|
|
}
|
|
case laya::UNIFORM1FV:
|
|
{
|
|
int value = *(int*)(data + nOffset);
|
|
JCArrayBufferManager::ArrayBufferContent* pBuffer = m_pRArrayBufferManager->getArrayBuffer(value);
|
|
if (pBuffer)
|
|
{
|
|
this->uniform1fv(nLocation, pBuffer->m_nLength / sizeof(float), (GLfloat*)pBuffer->m_pBuffer);
|
|
}
|
|
break;
|
|
}
|
|
case laya::UNIFORM1I:
|
|
{
|
|
int value = *(int*)(data + nOffset);
|
|
this->uniform1i(nLocation, value);
|
|
break;
|
|
}
|
|
case laya::UNIFORM1IV:
|
|
{
|
|
int value = *(int*)(data + nOffset);
|
|
JCArrayBufferManager::ArrayBufferContent* pBuffer = m_pRArrayBufferManager->getArrayBuffer(value);
|
|
if (pBuffer)
|
|
{
|
|
this->uniform1iv(nLocation, pBuffer->m_nLength / sizeof(int), (GLint*)pBuffer->m_pBuffer);
|
|
}
|
|
break;
|
|
}
|
|
case laya::UNIFORM2F:
|
|
case laya::UNIFORM2FV:
|
|
{
|
|
int value = *(int*)(data + nOffset);
|
|
JCArrayBufferManager::ArrayBufferContent* pBuffer = m_pRArrayBufferManager->getArrayBuffer(value);
|
|
if (pBuffer)
|
|
{
|
|
this->uniform2fv(nLocation, pBuffer->m_nLength / sizeof(float) / 2, (GLfloat*)pBuffer->m_pBuffer);
|
|
}
|
|
break;
|
|
}
|
|
case laya::UNIFORM2I:
|
|
case laya::UNIFORM2IV:
|
|
{
|
|
int value = *(int*)(data + nOffset);
|
|
JCArrayBufferManager::ArrayBufferContent* pBuffer = m_pRArrayBufferManager->getArrayBuffer(value);
|
|
if (pBuffer)
|
|
{
|
|
this->uniform2iv(nLocation, pBuffer->m_nLength / sizeof(int) / 2, (GLint*)pBuffer->m_pBuffer);
|
|
}
|
|
break;
|
|
}
|
|
case laya::UNIFORM3F:
|
|
case laya::UNIFORM3FV:
|
|
{
|
|
int value = *(int*)(data + nOffset);
|
|
JCArrayBufferManager::ArrayBufferContent* pBuffer = m_pRArrayBufferManager->getArrayBuffer(value);
|
|
if (pBuffer)
|
|
{
|
|
this->uniform3fv(nLocation, pBuffer->m_nLength / sizeof(float) / 3, (GLfloat*)pBuffer->m_pBuffer);
|
|
}
|
|
break;
|
|
}
|
|
case laya::UNIFORM3I:
|
|
case laya::UNIFORM3IV:
|
|
{
|
|
int value = *(int*)(data + nOffset);
|
|
JCArrayBufferManager::ArrayBufferContent* pBuffer = m_pRArrayBufferManager->getArrayBuffer(value);
|
|
if (pBuffer)
|
|
{
|
|
this->uniform3iv(nLocation, pBuffer->m_nLength / sizeof(int) / 3, (GLint*)pBuffer->m_pBuffer);
|
|
}
|
|
break;
|
|
}
|
|
case laya::UNIFORM4F:
|
|
case laya::UNIFORM4FV:
|
|
{
|
|
int value = *(int*)(data + nOffset);
|
|
JCArrayBufferManager::ArrayBufferContent* pBuffer = m_pRArrayBufferManager->getArrayBuffer(value);
|
|
if (pBuffer)
|
|
{
|
|
int nLength = pBuffer->m_nLength > 16 ? pBuffer->m_nLength : 16;
|
|
this->uniform4fv(nLocation, nLength / sizeof(float) / 4, (GLfloat*)pBuffer->m_pBuffer);
|
|
}
|
|
break;
|
|
}
|
|
case laya::UNIFORM4I:
|
|
case laya::UNIFORM4IV:
|
|
{
|
|
int value = *(int*)(data + nOffset);
|
|
JCArrayBufferManager::ArrayBufferContent* pBuffer = m_pRArrayBufferManager->getArrayBuffer(value);
|
|
if (pBuffer)
|
|
{
|
|
int nLength = pBuffer->m_nLength > 16 ? pBuffer->m_nLength : 16;
|
|
this->uniform4iv(nLocation, nLength / sizeof(int) / 4, (GLint*)pBuffer->m_pBuffer);
|
|
}
|
|
break;
|
|
}
|
|
case laya::UNIFORMMATRIX2FV:
|
|
{
|
|
int value = *(int*)(data + nOffset);
|
|
JCArrayBufferManager::ArrayBufferContent* pBuffer = m_pRArrayBufferManager->getArrayBuffer(value);
|
|
if (pBuffer)
|
|
{
|
|
this->uniformMatrix2fv(nLocation, pBuffer->m_nLength / sizeof(float) / 4, false, (GLfloat*)pBuffer->m_pBuffer);
|
|
}
|
|
break;
|
|
}
|
|
case laya::UNIFORMMATRIX3FV:
|
|
{
|
|
int value = *(int*)(data + nOffset);
|
|
JCArrayBufferManager::ArrayBufferContent* pBuffer = m_pRArrayBufferManager->getArrayBuffer(value);
|
|
if (pBuffer)
|
|
{
|
|
this->uniformMatrix3fv(nLocation, pBuffer->m_nLength / sizeof(float) / 9, false, (GLfloat*)pBuffer->m_pBuffer);
|
|
}
|
|
break;
|
|
}
|
|
case laya::UNIFORMMATRIX4FV:
|
|
{
|
|
int value = *(int*)(data + nOffset);
|
|
JCArrayBufferManager::ArrayBufferContent* pBuffer = m_pRArrayBufferManager->getArrayBuffer(value);
|
|
if (pBuffer)
|
|
{
|
|
this->uniformMatrix4fv(nLocation, pBuffer->m_nLength / sizeof(float) / 16, false, (GLfloat*)pBuffer->m_pBuffer);
|
|
}
|
|
break;
|
|
}
|
|
case laya::UNIFORMSAMPLER_2D:
|
|
{
|
|
int nGpuTextureID = *(int*)(data + nOffset);
|
|
this->activeTexture(nTextureLocation);
|
|
this->bindTexture(GL_TEXTURE_2D, nGpuTextureID);
|
|
this->uniform1i(nLocation, nTextureLocation - GL_TEXTURE0);
|
|
break;
|
|
}
|
|
case laya::UNIFORMSAMPLER_CUBE:
|
|
{
|
|
int nGpuTextureID = *(int*)(data + nOffset);
|
|
this->activeTexture(nTextureLocation);
|
|
this->bindTexture(GL_TEXTURE_CUBE_MAP, nGpuTextureID);
|
|
this->uniform1i(nLocation, nTextureLocation - GL_TEXTURE0);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------END FILE--------------------------------
|