143 lines
4.0 KiB
C++
143 lines
4.0 KiB
C++
/*
|
|
Copyright (c) 2013 yvt
|
|
|
|
This file is part of OpenSpades.
|
|
|
|
OpenSpades 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.
|
|
|
|
OpenSpades 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 OpenSpades. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
#include "SWModel.h"
|
|
#include <Core/FileManager.h>
|
|
#include <Core/IStream.h>
|
|
|
|
namespace spades {
|
|
namespace draw {
|
|
SWModel::SWModel(VoxelModel *m) : rawModel(m) {
|
|
center.x = m->GetWidth();
|
|
center.y = m->GetHeight();
|
|
center.z = m->GetDepth();
|
|
center *= 0.5f;
|
|
radius = center.GetLength();
|
|
|
|
int w = m->GetWidth();
|
|
int h = m->GetHeight();
|
|
int d = m->GetDepth();
|
|
|
|
for (int y = 0; y < h; y++) {
|
|
for (int x = 0; x < w; x++) {
|
|
|
|
renderDataAddr.push_back(static_cast<uint32_t>(renderData.size()));
|
|
|
|
uint64_t map = m->GetSolidBitsAt(x, y);
|
|
uint64_t map1 = x > 0 ? m->GetSolidBitsAt(x - 1, y) : 0;
|
|
uint64_t map2 = x < (w - 1) ? m->GetSolidBitsAt(x + 1, y) : 0;
|
|
uint64_t map3 = y > 0 ? m->GetSolidBitsAt(x, y - 1) : 0;
|
|
uint64_t map4 = y < (h - 1) ? m->GetSolidBitsAt(x, y + 1) : 0;
|
|
map1 &= map2;
|
|
map1 &= map3;
|
|
map1 &= map4;
|
|
|
|
for (int z = 0; z < d; z++) {
|
|
if (!(map & (1ULL << z)))
|
|
continue;
|
|
if (z == 0 || z == (d - 1) || ((map >> (z - 1)) & 7ULL) != 7ULL ||
|
|
(map1 & (1ULL << z)) == 0) {
|
|
uint32_t col = m->GetColor(x, y, z);
|
|
SPAssert(col != 0xddbeef);
|
|
col = (col & 0xff00) | ((col & 0xff) << 16) | ((col & 0xff0000) >> 16);
|
|
col |= z << 24;
|
|
renderData.push_back(col);
|
|
|
|
// store normal
|
|
int nx = 0, ny = 0, nz = 0;
|
|
for (int cx = -1; cx <= 1; cx++)
|
|
for (int cy = -1; cy <= 1; cy++)
|
|
for (int cz = -1; cz <= 1; cz++) {
|
|
if (m->IsSolid(x + cx, y + cy, z + cz)) {
|
|
nx -= cx;
|
|
ny -= cy;
|
|
nz -= cz;
|
|
} else {
|
|
nx += cx;
|
|
ny += cy;
|
|
nz += cz;
|
|
}
|
|
}
|
|
nx = std::max(std::min(nx, 1), -1);
|
|
ny = std::max(std::min(ny, 1), -1);
|
|
nz = std::max(std::min(nz, 1), -1);
|
|
nx++;
|
|
ny++;
|
|
nz++;
|
|
renderData.push_back(nx + ny * 3 + nz * 9);
|
|
}
|
|
}
|
|
|
|
renderData.push_back(0xffffffffU);
|
|
}
|
|
}
|
|
}
|
|
|
|
SWModel::~SWModel() {}
|
|
|
|
AABB3 SWModel::GetBoundingBox() {
|
|
VoxelModel *m = rawModel;
|
|
Vector3 minPos = {0, 0, 0};
|
|
Vector3 maxPos = {(float)m->GetWidth(), (float)m->GetHeight(), (float)m->GetDepth()};
|
|
auto origin = rawModel->GetOrigin() - .5f;
|
|
minPos += origin;
|
|
maxPos += origin;
|
|
Vector3 maxDiff = {std::max(fabsf(minPos.x), fabsf(maxPos.x)),
|
|
std::max(fabsf(minPos.y), fabsf(maxPos.y)),
|
|
std::max(fabsf(minPos.z), fabsf(maxPos.z))};
|
|
radius = maxDiff.GetLength();
|
|
|
|
AABB3 boundingBox;
|
|
boundingBox.min = minPos;
|
|
boundingBox.max = maxPos;
|
|
return boundingBox;
|
|
}
|
|
|
|
SWModelManager::~SWModelManager() {
|
|
for (auto it = models.begin(); it != models.end(); it++)
|
|
it->second->Release();
|
|
}
|
|
|
|
SWModel *SWModelManager::RegisterModel(const std::string &name) {
|
|
auto it = models.find(name);
|
|
if (it == models.end()) {
|
|
auto *str = FileManager::OpenForReading(name.c_str());
|
|
Handle<VoxelModel> vm;
|
|
try {
|
|
vm.Set(VoxelModel::LoadKV6(str), false);
|
|
auto *m = CreateModel(vm);
|
|
models.insert(std::make_pair(name, m));
|
|
m->AddRef();
|
|
return m;
|
|
} catch (...) {
|
|
delete str;
|
|
throw;
|
|
}
|
|
} else {
|
|
auto *model = it->second;
|
|
model->AddRef();
|
|
return model;
|
|
}
|
|
}
|
|
|
|
SWModel *SWModelManager::CreateModel(spades::VoxelModel *vm) { return new SWModel(vm); }
|
|
}
|
|
}
|