343 lines
9.2 KiB
C++
343 lines
9.2 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2006-2010 - Frictional Games
|
|
*
|
|
* This file is part of HPL1 Engine.
|
|
*/
|
|
|
|
#include "hpl1/engine/graphics/MeshCreator.h"
|
|
#include "hpl1/engine/graphics/LowLevelGraphics.h"
|
|
#include "hpl1/engine/graphics/Mesh.h"
|
|
#include "hpl1/engine/graphics/Mesh2d.h"
|
|
#include "hpl1/engine/graphics/SubMesh.h"
|
|
#include "hpl1/engine/graphics/VertexBuffer.h"
|
|
#include "hpl1/engine/resources/AnimationManager.h"
|
|
#include "hpl1/engine/resources/MaterialManager.h"
|
|
#include "hpl1/engine/resources/Resources.h"
|
|
#include "hpl1/engine/system/String.h"
|
|
#include "hpl1/engine/system/low_level_system.h"
|
|
|
|
namespace hpl {
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// CONSTRUCTORS
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
cMeshCreator::cMeshCreator(iLowLevelGraphics *apLowLevelGraphics, cResources *apResources) {
|
|
mpLowLevelGraphics = apLowLevelGraphics;
|
|
mpResources = apResources;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
cMeshCreator::~cMeshCreator() {
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// PUBLIC METHODS
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
cMesh *cMeshCreator::CreateBox(const tString &asName, cVector3f avSize, const tString &asMaterial) {
|
|
cMesh *pMesh = hplNew(cMesh, (asName, mpResources->GetMaterialManager(),
|
|
mpResources->GetAnimationManager()));
|
|
|
|
cSubMesh *pSubMesh = pMesh->CreateSubMesh("Main");
|
|
|
|
iMaterial *pMat = mpResources->GetMaterialManager()->CreateMaterial(asMaterial);
|
|
pSubMesh->SetMaterial(pMat);
|
|
iVertexBuffer *pVtxBuff = CreateBoxVertexBuffer(avSize);
|
|
pSubMesh->SetVertexBuffer(pVtxBuff);
|
|
|
|
return pMesh;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
iVertexBuffer *cMeshCreator::CreateSkyBoxVertexBuffer(float afSize) {
|
|
iVertexBuffer *pSkyBox = mpLowLevelGraphics->CreateVertexBuffer(
|
|
eVertexFlag_Color0 | eVertexFlag_Position | eVertexFlag_Texture0,
|
|
eVertexBufferDrawType_Quad, eVertexBufferUsageType_Static);
|
|
|
|
float fSize = afSize;
|
|
|
|
for (int x = -1; x <= 1; x++)
|
|
for (int y = -1; y <= 1; y++)
|
|
for (int z = -1; z <= 1; z++) {
|
|
if (x == 0 && y == 0 && z == 0)
|
|
continue;
|
|
if (ABS(x) + ABS(y) + ABS(z) > 1)
|
|
continue;
|
|
|
|
// Direction (could say inverse normal) of the quad.
|
|
cVector3f vDir;
|
|
cVector3f vSide;
|
|
|
|
cVector3f vAdd[4];
|
|
if (ABS(x)) {
|
|
vDir.x = (float)x;
|
|
|
|
vAdd[0].y = 1;
|
|
vAdd[0].z = 1;
|
|
vAdd[1].y = -1;
|
|
vAdd[1].z = 1;
|
|
vAdd[2].y = -1;
|
|
vAdd[2].z = -1;
|
|
vAdd[3].y = 1;
|
|
vAdd[3].z = -1;
|
|
} else if (ABS(y)) {
|
|
vDir.y = (float)y;
|
|
|
|
vAdd[0].z = 1;
|
|
vAdd[0].x = 1;
|
|
vAdd[1].z = -1;
|
|
vAdd[1].x = 1;
|
|
vAdd[2].z = -1;
|
|
vAdd[2].x = -1;
|
|
vAdd[3].z = 1;
|
|
vAdd[3].x = -1;
|
|
} else if (ABS(z)) {
|
|
vAdd[0].y = 1;
|
|
vAdd[0].x = 1;
|
|
vAdd[1].y = 1;
|
|
vAdd[1].x = -1;
|
|
vAdd[2].y = -1;
|
|
vAdd[2].x = -1;
|
|
vAdd[3].y = -1;
|
|
vAdd[3].x = 1;
|
|
|
|
vDir.z = (float)z;
|
|
}
|
|
|
|
// Log("Side: (%.0f : %.0f : %.0f) [ ", vDir.x, vDir.y,vDir.z);
|
|
for (int i = 0; i < 4; i++) {
|
|
int idx = i;
|
|
if (x + y + z < 0)
|
|
idx = 3 - i;
|
|
|
|
pSkyBox->AddColor(eVertexFlag_Color0, cColor(1, 1, 1, 1));
|
|
pSkyBox->AddVertex(eVertexFlag_Position, (vDir + vAdd[idx]) * fSize);
|
|
pSkyBox->AddVertex(eVertexFlag_Texture0, vDir + vAdd[idx]);
|
|
|
|
vSide = vDir + vAdd[idx];
|
|
// Log("%d: (%.1f : %.1f : %.1f) ", i,vSide.x, vSide.y,vSide.z);
|
|
}
|
|
// Log("\n");
|
|
}
|
|
|
|
for (int i = 0; i < 24; i++)
|
|
pSkyBox->AddIndex(i);
|
|
|
|
if (!pSkyBox->Compile(0)) {
|
|
hplDelete(pSkyBox);
|
|
return NULL;
|
|
}
|
|
return pSkyBox;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
iVertexBuffer *cMeshCreator::CreateBoxVertexBuffer(cVector3f avSize) {
|
|
iVertexBuffer *pBox = mpLowLevelGraphics->CreateVertexBuffer(
|
|
eVertexFlag_Color0 | eVertexFlag_Position | eVertexFlag_Texture0 |
|
|
eVertexFlag_Texture1 | eVertexFlag_Normal,
|
|
eVertexBufferDrawType_Tri, eVertexBufferUsageType_Static);
|
|
|
|
avSize = avSize * 0.5;
|
|
|
|
int lVtxIdx = 0;
|
|
|
|
for (int x = -1; x <= 1; x++)
|
|
for (int y = -1; y <= 1; y++)
|
|
for (int z = -1; z <= 1; z++) {
|
|
if (x == 0 && y == 0 && z == 0)
|
|
continue;
|
|
if (ABS(x) + ABS(y) + ABS(z) > 1)
|
|
continue;
|
|
|
|
// Direction (could say inverse normal) of the quad.
|
|
cVector3f vDir;
|
|
cVector3f vSide;
|
|
|
|
cVector3f vAdd[4];
|
|
if (ABS(x)) {
|
|
vDir.x = (float)x;
|
|
|
|
vAdd[0].y = 1;
|
|
vAdd[0].z = 1;
|
|
vAdd[1].y = -1;
|
|
vAdd[1].z = 1;
|
|
vAdd[2].y = -1;
|
|
vAdd[2].z = -1;
|
|
vAdd[3].y = 1;
|
|
vAdd[3].z = -1;
|
|
} else if (ABS(y)) {
|
|
vDir.y = (float)y;
|
|
|
|
vAdd[0].z = 1;
|
|
vAdd[0].x = 1;
|
|
vAdd[1].z = -1;
|
|
vAdd[1].x = 1;
|
|
vAdd[2].z = -1;
|
|
vAdd[2].x = -1;
|
|
vAdd[3].z = 1;
|
|
vAdd[3].x = -1;
|
|
} else if (ABS(z)) {
|
|
vAdd[0].y = 1;
|
|
vAdd[0].x = 1;
|
|
vAdd[1].y = 1;
|
|
vAdd[1].x = -1;
|
|
vAdd[2].y = -1;
|
|
vAdd[2].x = -1;
|
|
vAdd[3].y = -1;
|
|
vAdd[3].x = 1;
|
|
|
|
vDir.z = (float)z;
|
|
}
|
|
|
|
// Log("Side: (%.0f : %.0f : %.0f) [ ", vDir.x, vDir.y,vDir.z);
|
|
for (int i = 0; i < 4; i++) {
|
|
int idx = GetBoxIdx(i, x, y, z);
|
|
cVector3f vTex = GetBoxTex(i, x, y, z, vAdd);
|
|
|
|
pBox->AddColor(eVertexFlag_Color0, cColor(1, 1, 1, 1));
|
|
pBox->AddVertex(eVertexFlag_Position, (vDir + vAdd[idx]) * avSize);
|
|
pBox->AddVertex(eVertexFlag_Normal, vDir);
|
|
|
|
// texture coord
|
|
cVector3f vCoord = cVector3f((vTex.x + 1) * 0.5f, (vTex.y + 1) * 0.5f, 0);
|
|
pBox->AddVertex(eVertexFlag_Texture0, vCoord);
|
|
|
|
vSide = vDir + vAdd[idx];
|
|
// Log("%d: Tex: (%.1f : %.1f : %.1f) ", i,vTex.x, vTex.y,vTex.z);
|
|
// Log("%d: (%.1f : %.1f : %.1f) ", i,vSide.x, vSide.y,vSide.z);
|
|
}
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
pBox->AddIndex(lVtxIdx + i);
|
|
pBox->AddIndex(lVtxIdx + 2);
|
|
pBox->AddIndex(lVtxIdx + 3);
|
|
pBox->AddIndex(lVtxIdx + 0);
|
|
|
|
lVtxIdx += 4;
|
|
|
|
// Log("\n");
|
|
}
|
|
|
|
if (!pBox->Compile(eVertexCompileFlag_CreateTangents)) {
|
|
hplDelete(pBox);
|
|
return NULL;
|
|
}
|
|
return pBox;
|
|
}
|
|
|
|
cVector3f cMeshCreator::GetBoxTex(int i, int x, int y, int z, cVector3f *vAdd) {
|
|
cVector3f vTex;
|
|
|
|
if (ABS(x)) {
|
|
vTex.x = vAdd[i].z;
|
|
vTex.y = vAdd[i].y;
|
|
} else if (ABS(y)) {
|
|
vTex.x = vAdd[i].x;
|
|
vTex.y = vAdd[i].z;
|
|
} else if (ABS(z)) {
|
|
vTex.x = vAdd[i].x;
|
|
vTex.y = vAdd[i].y;
|
|
}
|
|
|
|
// Inverse for negative directions
|
|
if (x + y + z < 0) {
|
|
vTex.x = -vTex.x;
|
|
vTex.y = -vTex.y;
|
|
}
|
|
|
|
return vTex;
|
|
}
|
|
int cMeshCreator::GetBoxIdx(int i, int x, int y, int z) {
|
|
int idx = i;
|
|
if (x + y + z > 0)
|
|
idx = 3 - i;
|
|
|
|
return idx;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
cMesh2D *cMeshCreator::Create2D(tString asName, cVector2f mvSize) {
|
|
int i;
|
|
tString sMeshName = cString::ToLowerCase(asName);
|
|
cMesh2D *pMesh;
|
|
|
|
/// SQUARE ///////////////////////
|
|
if (sMeshName == "square") {
|
|
cVector2f vPos[4] = {cVector2f(mvSize.x / 2, -mvSize.y / 2), cVector2f(mvSize.x / 2, mvSize.y / 2), cVector2f(-mvSize.x / 2, mvSize.y / 2), cVector2f(-mvSize.x / 2, -mvSize.y / 2)};
|
|
|
|
pMesh = hplNew(cMesh2D, ());
|
|
for (i = 0; i < 4; i++) {
|
|
pMesh->AddVertex(vPos[i], 0, 1);
|
|
pMesh->AddEdgeIndex(i);
|
|
}
|
|
for (i = 1; i < 4; i++)
|
|
pMesh->AddIndex(i);
|
|
for (i = 0; i < 3; i++)
|
|
pMesh->AddIndex(i < 2 ? i : 3);
|
|
|
|
return pMesh;
|
|
}
|
|
/// TRIANGLE ///////////////////////
|
|
else if (sMeshName == "tri_1_to_1") {
|
|
cVector2f vPos[3] = {cVector2f(mvSize.x / 2, -mvSize.y / 2), cVector2f(mvSize.x / 2, mvSize.y / 2), cVector2f(-mvSize.x / 2, mvSize.y / 2)};
|
|
|
|
pMesh = hplNew(cMesh2D, ());
|
|
for (i = 0; i < 3; i++) {
|
|
pMesh->AddVertex(vPos[i], 0, 1);
|
|
pMesh->AddEdgeIndex(i);
|
|
pMesh->AddIndex(i);
|
|
}
|
|
|
|
return pMesh;
|
|
}
|
|
/// OTHER PRIMITIVE ///////////////////////
|
|
else {
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// PRIVATE METHODS
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
} // namespace hpl
|