Files
scummvm-cursorfix/engines/wintermute/base/gfx/3dmesh.cpp
2026-02-02 04:50:13 +01:00

173 lines
4.6 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/>.
*
*/
/*
* This file is based on WME.
* http://dead-code.org/redir.php?target=wme
* Copyright (c) 2003-2013 Jan Nedoma and contributors
*/
#include "common/file.h"
#include "engines/wintermute/base/base_game.h"
#include "engines/wintermute/base/gfx/3dloader_3ds.h"
#include "engines/wintermute/base/gfx/3dmesh.h"
#include "engines/wintermute/dcgf.h"
namespace Wintermute {
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
Mesh3DS::Mesh3DS(BaseGame *inGame) : BaseNamedObject(inGame) {
_vertices = nullptr;
_faces = nullptr;
_numFaces = _numVertices = 0;
_visible = true;
}
//////////////////////////////////////////////////////////////////////////
Mesh3DS::~Mesh3DS() {
cleanup();
}
//////////////////////////////////////////////////////////////////////////
void Mesh3DS::cleanup() {
SAFE_DELETE_ARRAY(_vertices);
_numVertices = 0;
SAFE_DELETE_ARRAY(_faces);
_numFaces = 0;
_vb.free();
}
//////////////////////////////////////////////////////////////////////////
bool Mesh3DS::createVertexBuffer() {
_vb.free();
if (_numFaces == 0)
return true;
int vbSize = _numFaces * sizeof(Mesh3DSVertex) * 3;
_vb = DXBuffer(vbSize);
if (_vb.ptr() == nullptr) {
_game->LOG(0, "Error creating vertex buffer.");
return false;
} else
return true;
}
//////////////////////////////////////////////////////////////////////////
bool Mesh3DS::fillVertexBuffer(uint32 color) {
_vb.free();
if (_numFaces == 0)
return true;
int vbSize = _numFaces * sizeof(Mesh3DSVertex) * 3;
_vb = DXBuffer(vbSize);
if (_vb.ptr() == nullptr) {
_game->LOG(0, "Error creating vertex buffer.");
return false;
}
Mesh3DSVertex *verts = (Mesh3DSVertex *)_vb.ptr();
for (int i = 0; i < _numFaces; i++) {
for (int j = 0; j < 3; j++) {
int outVert = i * 3 + j;
int vertex = _faces[i]._vertices[j];
verts[outVert]._x = _vertices[vertex]._pos._x;
verts[outVert]._y = _vertices[vertex]._pos._y;
verts[outVert]._z = _vertices[vertex]._pos._z;
verts[outVert]._nx = _faces[i]._normals[j]._x;
verts[outVert]._ny = _faces[i]._normals[j]._y;
verts[outVert]._nz = _faces[i]._normals[j]._z;
verts[outVert]._r = RGBCOLGetR(color) / 255.0f;
verts[outVert]._g = RGBCOLGetG(color) / 255.0f;
verts[outVert]._b = RGBCOLGetB(color) / 255.0f;
verts[outVert]._a = RGBCOLGetA(color) / 255.0f;
}
}
fillVertexBuffer();
return true;
}
//////////////////////////////////////////////////////////////////////////
void Mesh3DS::computeNormals() {
DXVector3 *normals = new DXVector3[_numVertices];
for (uint32 i = 0; i < _numVertices; i++) {
normals[i]._x = 0.0f;
normals[i]._y = 0.0f;
normals[i]._z = 0.0f;
}
for (uint32 i = 0; i < _numFaces; i++) {
uint16 a = _faces[i]._vertices[0];
uint16 b = _faces[i]._vertices[1];
uint16 c = _faces[i]._vertices[2];
DXVector3 *v1 = &_vertices[a]._pos;
DXVector3 *v2 = &_vertices[b]._pos;
DXVector3 *v3 = &_vertices[c]._pos;
DXVector3 edge1 = *v2 - *v1;
DXVector3 edge2 = *v3 - *v2;
DXVector3 normal;
DXVec3Cross(&normal, &edge1, &edge2);
DXVec3Normalize(&normal, &normal);
normals[a] += normal;
normals[b] += normal;
normals[c] += normal;
}
// Assign the newly computed normals back to the vertices
for (uint32 i = 0; i < _numFaces; i++) {
for (uint32 j = 0; j < 3; j++) {
DXVec3Normalize(&_faces[i]._normals[j], &normals[_faces[i]._vertices[j]]);
//_faces[i]._normals[j] = normals[_faces[i]._vertices[j]];
}
}
delete[] normals;
}
//////////////////////////////////////////////////////////////////////////
bool Mesh3DS::persist(BasePersistenceManager *persistMgr) {
persistMgr->transferBool(TMEMBER(_visible));
return true;
}
} // namespace Wintermute