WIP: REAL 3D object parsing
This commit is contained in:
9
Makefile
9
Makefile
@@ -2,8 +2,8 @@ CXX=g++
|
|||||||
CXXOPTS=-Og -ggdb -fvar-tracking-assignments -Wall -Wextra -Wno-unused-function -pedantic -std=c++14 -march=native -fstack-protector-strong --param=ssp-buffer-size=4 -flto -I.
|
CXXOPTS=-Og -ggdb -fvar-tracking-assignments -Wall -Wextra -Wno-unused-function -pedantic -std=c++14 -march=native -fstack-protector-strong --param=ssp-buffer-size=4 -flto -I.
|
||||||
LDOPTS=-Wl,--sort-common,--as-needed
|
LDOPTS=-Wl,--sort-common,--as-needed
|
||||||
|
|
||||||
render_CXXSRCS ::= render/Renderer.cc render/GlResource.cc render/ProgramProvider.cc render/renderutil.cc render/Overlay.cc render/VBOManager.cc
|
render_CXXSRCS ::= render/Renderer.cc render/GlResource.cc render/ProgramProvider.cc render/renderutil.cc render/Overlay.cc render/VBOManager.cc render/Object.cc
|
||||||
game_CXXSRCS ::= game/GSMvePlay.cc
|
game_CXXSRCS ::= game/GSMvePlay.cc game/GSShowObject.cc
|
||||||
|
|
||||||
iffexplore_CXXSRCS ::= iffexplore.cc IffFile.cc util.cc exceptions.cc
|
iffexplore_CXXSRCS ::= iffexplore.cc IffFile.cc util.cc exceptions.cc
|
||||||
iffexplore_LIBS ::=
|
iffexplore_LIBS ::=
|
||||||
@@ -17,7 +17,10 @@ font2png_LIBS ::= -lpng
|
|||||||
mvedecode_CXXSRCS ::= mvedecode.cc TreFile.cc IffFile.cc util.cc MveDecoder.cc exceptions.cc decompress.cc $(render_CXXSRCS) $(game_CXXSRCS)
|
mvedecode_CXXSRCS ::= mvedecode.cc TreFile.cc IffFile.cc util.cc MveDecoder.cc exceptions.cc decompress.cc $(render_CXXSRCS) $(game_CXXSRCS)
|
||||||
mvedecode_LIBS ::= -lSDL2 -lglbinding
|
mvedecode_LIBS ::= -lSDL2 -lglbinding
|
||||||
|
|
||||||
progs ::= iffexplore treexplore mvedecode
|
objdecode_CXXSRCS ::= objdecode.cc TreFile.cc IffFile.cc util.cc ObjDecoder.cc exceptions.cc decompress.cc $(render_CXXSRCS) $(game_CXXSRCS)
|
||||||
|
objdecode_LIBS ::= -lSDL2 -lglbinding
|
||||||
|
|
||||||
|
progs ::= iffexplore treexplore mvedecode objdecode
|
||||||
|
|
||||||
all: $(progs)
|
all: $(progs)
|
||||||
|
|
||||||
|
|||||||
203
ObjDecoder.cc
Normal file
203
ObjDecoder.cc
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "ObjDecoder.hh"
|
||||||
|
#include "exceptions.hh"
|
||||||
|
#include "util.hh"
|
||||||
|
|
||||||
|
ObjDecoder::ObjDecoder(uint8_t const* base, size_t length)
|
||||||
|
: iff_(base, length)
|
||||||
|
{
|
||||||
|
auto& root = iff_.getRoot();
|
||||||
|
if (!root.isForm())
|
||||||
|
throw FormatException{"Root node not FORM"};
|
||||||
|
|
||||||
|
auto& rootForm = dynamic_cast<IffFile::Form const&>(root);
|
||||||
|
if (rootForm.getSubtype() != "REAL")
|
||||||
|
throw FormatException{"Root form not REAL"};
|
||||||
|
|
||||||
|
for (auto realIt = rootForm.childrenBegin();realIt != rootForm.childrenEnd();++realIt) {
|
||||||
|
if (realIt->getType() == "INFO") {
|
||||||
|
name_ = *realIt;
|
||||||
|
printf("Name: %s\n", name_.c_str());
|
||||||
|
} else if (realIt->isForm()) {
|
||||||
|
auto& itForm = dynamic_cast<IffFile::Form const&>(*realIt);
|
||||||
|
if (itForm.getSubtype() == "OBJT")
|
||||||
|
parseOBJT_(itForm);
|
||||||
|
else if (itForm.getSubtype() == "APPR")
|
||||||
|
parseAPPR_(itForm);
|
||||||
|
else
|
||||||
|
throw FormatException{"Unknown FORM type " + itForm.getSubtype()};
|
||||||
|
} else
|
||||||
|
throw FormatException{"Unknown chunk type " + realIt->getType()};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjDecoder::parseOBJT_(IffFile::Form const& form)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjDecoder::parseAPPR_(IffFile::Form const& form)
|
||||||
|
{
|
||||||
|
if (form.getChildCount() != 1)
|
||||||
|
throw FormatException{"Unexpected child count in APPR"};
|
||||||
|
|
||||||
|
auto& child = *form.childrenBegin();
|
||||||
|
if (!child.isForm())
|
||||||
|
throw FormatException{"APPR child not FORM"};
|
||||||
|
|
||||||
|
auto& childForm = dynamic_cast<IffFile::Form const&>(child);
|
||||||
|
if (childForm.getSubtype() != "POLY")
|
||||||
|
throw FormatException{"APPR child form not POLY"};
|
||||||
|
|
||||||
|
parsePOLY_(childForm);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjDecoder::parsePOLY_(IffFile::Form const& form)
|
||||||
|
{
|
||||||
|
for (auto it = form.childrenBegin();it != form.childrenEnd();++it) {
|
||||||
|
if (it->getType() == "INFO") {
|
||||||
|
} else if (it->getType() == "VERT") {
|
||||||
|
if (it->getSize()%12 != 0)
|
||||||
|
throw FormatException{"Unexpected VERT size"};
|
||||||
|
for (size_t i = 0;i < it->getSize();i+=12) {
|
||||||
|
std::array<int32_t, 3> vertex;
|
||||||
|
for (size_t j = 0;j < 3;++j)
|
||||||
|
vertex[j] = readU32LE(it->begin()+i+j*4);
|
||||||
|
printf("V: %d %d %d\n", vertex[0], vertex[1], vertex[2]);
|
||||||
|
vertices_.push_back(vertex);
|
||||||
|
}
|
||||||
|
} else if (it->isForm()) {
|
||||||
|
auto& itForm = dynamic_cast<IffFile::Form const&>(*it);
|
||||||
|
if (itForm.getSubtype() == "TRIS") {
|
||||||
|
parseTRIS_(itForm);
|
||||||
|
} else if (itForm.getSubtype() == "QUAD") {
|
||||||
|
parseQUAD_(itForm);
|
||||||
|
} else if (itForm.getSubtype() == "DETA") {
|
||||||
|
// NYI
|
||||||
|
} else if (itForm.getSubtype() == "TXMS") {
|
||||||
|
parseTXMS_(itForm);
|
||||||
|
} else if (itForm.getSubtype() == "GRUP") {
|
||||||
|
// NYI
|
||||||
|
} else
|
||||||
|
throw FormatException{"Unknown POLY subform " + itForm.getSubtype()};
|
||||||
|
} else if (it->getType() == "ATTR") {
|
||||||
|
// NYI
|
||||||
|
} else if (it->getType() == "XATR") {
|
||||||
|
// NYI
|
||||||
|
} else
|
||||||
|
throw FormatException{"Unknown POLY child " + it->getType()};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjDecoder::parseTRIS_(IffFile::Form const& form)
|
||||||
|
{
|
||||||
|
if (form.getChildCount() != 2)
|
||||||
|
throw FormatException{"Unexpected child count in TRIS"};
|
||||||
|
|
||||||
|
auto vertCount = vertices_.size();
|
||||||
|
printf("VC: %lu\n", vertCount);
|
||||||
|
|
||||||
|
IffFile::Object const *face = nullptr, *maps = nullptr;
|
||||||
|
for (auto it = form.childrenBegin();it != form.childrenEnd();++it) {
|
||||||
|
if (it->getType() == "FACE") {
|
||||||
|
if (face)
|
||||||
|
throw FormatException{"Multiple FACE in TRIS"};
|
||||||
|
face = &*it;
|
||||||
|
} else if (it->getType() == "MAPS") {
|
||||||
|
if (maps)
|
||||||
|
throw FormatException{"Multiple MAPS in TRIS"};
|
||||||
|
maps = &*it;
|
||||||
|
} else
|
||||||
|
throw FormatException{"Unknown TRIS child " + it->getType()};
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(face && maps);
|
||||||
|
|
||||||
|
if (face->getSize()%8 != 0)
|
||||||
|
throw FormatException{"Unexpected FACE size"};
|
||||||
|
auto numTriangles = face->getSize()/8;
|
||||||
|
if (maps->getSize() != numTriangles*16)
|
||||||
|
throw FormatException{"Unexpected MAPS size"};
|
||||||
|
|
||||||
|
for (unsigned i = 0;i < numTriangles;++i) {
|
||||||
|
Triangle tri;
|
||||||
|
for (unsigned j = 0;j < 3;++j)
|
||||||
|
tri.vertIdx[j] = readU16LE(face->begin()+i*8+2+j*2);
|
||||||
|
tri.id = readU16LE(maps->begin()+i*16);
|
||||||
|
tri.tex = readU16LE(maps->begin()+i*16+2);
|
||||||
|
for (unsigned j = 0;j < 3;++j) {
|
||||||
|
tri.texCoords[j][0] = readU16LE(maps->begin()+i*16+4+j*4);
|
||||||
|
tri.texCoords[j][1] = readU16LE(maps->begin()+i*16+4+j*4+2);
|
||||||
|
}
|
||||||
|
printf("T%u: (%hu (%hu %hu)), (%hu (%hu %hu)), (%hu (%hu %hu))\n", tri.id,
|
||||||
|
tri.vertIdx[0], tri.texCoords[0][0], tri.texCoords[0][1],
|
||||||
|
tri.vertIdx[1], tri.texCoords[1][0], tri.texCoords[1][1],
|
||||||
|
tri.vertIdx[2], tri.texCoords[2][0], tri.texCoords[2][1]);
|
||||||
|
triangles_.push_back(tri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjDecoder::parseQUAD_(IffFile::Form const& form)
|
||||||
|
{
|
||||||
|
if (form.getChildCount() != 2)
|
||||||
|
throw FormatException{"Unexpected child count in QUAD"};
|
||||||
|
|
||||||
|
IffFile::Object const *face = nullptr, *maps = nullptr;
|
||||||
|
for (auto it = form.childrenBegin();it != form.childrenEnd();++it) {
|
||||||
|
if (it->getType() == "FACE") {
|
||||||
|
if (face)
|
||||||
|
throw FormatException{"Multiple FACE in QUAD"};
|
||||||
|
face = &*it;
|
||||||
|
} else if (it->getType() == "MAPS") {
|
||||||
|
if (maps)
|
||||||
|
throw FormatException{"Multiple MAPS in QUAD"};
|
||||||
|
maps = &*it;
|
||||||
|
} else
|
||||||
|
throw FormatException{"Unknown TRIS child " + it->getType()};
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(face && maps);
|
||||||
|
|
||||||
|
if (face->getSize()%10 != 0)
|
||||||
|
throw FormatException{"Unexpected FACE size"};
|
||||||
|
auto numQuads = face->getSize()/10;
|
||||||
|
if (maps->getSize() != numQuads*20)
|
||||||
|
throw FormatException{"Unexpected MAPS size"};
|
||||||
|
|
||||||
|
for (unsigned i = 0;i < numQuads;++i) {
|
||||||
|
Quad quad;
|
||||||
|
for (unsigned j = 0;j < 4;++j)
|
||||||
|
quad.vertIdx[j] = readU16LE(face->begin()+i*10+2+j*2);
|
||||||
|
quad.id = readU16LE(maps->begin()+i*20);
|
||||||
|
quad.tex = readU16LE(maps->begin()+i*20+2);
|
||||||
|
for (unsigned j = 0;j < 4;++j) {
|
||||||
|
quad.texCoords[j][0] = readU16LE(maps->begin()+i*20+4+j*4);
|
||||||
|
quad.texCoords[j][1] = readU16LE(maps->begin()+i*20+4+j*4+2);
|
||||||
|
}
|
||||||
|
printf("Q%u: (%hu (%hu %hu)), (%hu (%hu %hu)), (%hu (%hu %hu)), (%hu (%hu %hu))\n", quad.id,
|
||||||
|
quad.vertIdx[0], quad.texCoords[0][0], quad.texCoords[0][1],
|
||||||
|
quad.vertIdx[1], quad.texCoords[1][0], quad.texCoords[1][1],
|
||||||
|
quad.vertIdx[2], quad.texCoords[2][0], quad.texCoords[2][1],
|
||||||
|
quad.vertIdx[3], quad.texCoords[3][0], quad.texCoords[3][1]);
|
||||||
|
quads_.push_back(quad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjDecoder::parseTXMS_(IffFile::Form const& form)
|
||||||
|
{
|
||||||
|
if (form.getChildCount() < 1)
|
||||||
|
throw FormatException{"Unexpected child count in TXMS"};
|
||||||
|
|
||||||
|
auto it = form.childrenBegin();
|
||||||
|
auto& info = *it;
|
||||||
|
if (info.getType() != "INFO")
|
||||||
|
throw FormatException{"Missing INFO in TXMS"};
|
||||||
|
if (info.getSize() != 4)
|
||||||
|
throw FormatException{"Unexpected INFO size in TXMS"};
|
||||||
|
|
||||||
|
uint16_t numTXMP, numTXMA;
|
||||||
|
numTXMP = readU16LE(info.begin());
|
||||||
|
numTXMA = readU16LE(info.begin()+2);
|
||||||
|
if (form.getChildCount() != 1+numTXMP+numTXMA)
|
||||||
|
throw FormatException{"Unexpected child count in TXMS"};
|
||||||
|
}
|
||||||
62
ObjDecoder.hh
Normal file
62
ObjDecoder.hh
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
#ifndef WC3RE_OBJDECODER_HH__
|
||||||
|
#define WC3RE_OBJDECODER_HH__
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
#include "IffFile.hh"
|
||||||
|
|
||||||
|
class ObjDecoder {
|
||||||
|
public:
|
||||||
|
ObjDecoder(uint8_t const* base, size_t length);
|
||||||
|
|
||||||
|
using Vertex = std::array<int32_t, 3>;
|
||||||
|
using Vertices = std::vector<Vertex>;
|
||||||
|
using TexCoord = std::array<uint16_t, 2>;
|
||||||
|
|
||||||
|
struct Triangle {
|
||||||
|
uint16_t id;
|
||||||
|
uint16_t tex;
|
||||||
|
std::array<uint16_t, 3> vertIdx;
|
||||||
|
std::array<TexCoord, 3> texCoords;
|
||||||
|
};
|
||||||
|
using Triangles = std::vector<Triangle>;
|
||||||
|
|
||||||
|
struct Quad {
|
||||||
|
uint16_t id;
|
||||||
|
uint16_t tex;
|
||||||
|
std::array<uint16_t, 4> vertIdx;
|
||||||
|
std::array<TexCoord, 4> texCoords;
|
||||||
|
};
|
||||||
|
using Quads = std::vector<Quad>;
|
||||||
|
|
||||||
|
Vertices const& getVertices() const {
|
||||||
|
return vertices_;
|
||||||
|
}
|
||||||
|
|
||||||
|
Triangles const& getTriangles() const {
|
||||||
|
return triangles_;
|
||||||
|
}
|
||||||
|
|
||||||
|
Quads const& getQuads() const {
|
||||||
|
return quads_;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
IffFile iff_;
|
||||||
|
std::string name_;
|
||||||
|
|
||||||
|
void parseOBJT_(IffFile::Form const& form);
|
||||||
|
void parseAPPR_(IffFile::Form const& form);
|
||||||
|
void parsePOLY_(IffFile::Form const& form);
|
||||||
|
void parseTRIS_(IffFile::Form const& form);
|
||||||
|
void parseQUAD_(IffFile::Form const& form);
|
||||||
|
void parseTXMS_(IffFile::Form const& form);
|
||||||
|
|
||||||
|
Vertices vertices_;
|
||||||
|
Triangles triangles_;
|
||||||
|
Quads quads_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -2,7 +2,6 @@
|
|||||||
#define WC3RE_GAME_GSMVEPLAY_HH__
|
#define WC3RE_GAME_GSMVEPLAY_HH__
|
||||||
|
|
||||||
#include "GameState.hh"
|
#include "GameState.hh"
|
||||||
#include "render/sdlutil.hh"
|
|
||||||
|
|
||||||
class MveDecoder;
|
class MveDecoder;
|
||||||
namespace render {
|
namespace render {
|
||||||
|
|||||||
22
game/GSShowObject.cc
Normal file
22
game/GSShowObject.cc
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#include "ObjDecoder.hh"
|
||||||
|
|
||||||
|
#include "GSShowObject.hh"
|
||||||
|
#include "render/Object.hh"
|
||||||
|
|
||||||
|
namespace game {
|
||||||
|
GSShowObject::GSShowObject(render::Renderer& renderer, ObjDecoder& obj)
|
||||||
|
: GameState(renderer), obj_(obj),
|
||||||
|
object_(nullptr), delta_(0)
|
||||||
|
{
|
||||||
|
object_ = std::make_unique<render::Object>(renderer, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
GSShowObject::~GSShowObject()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void GSShowObject::draw(unsigned delta_ms)
|
||||||
|
{
|
||||||
|
object_->draw();
|
||||||
|
}
|
||||||
|
}
|
||||||
27
game/GSShowObject.hh
Normal file
27
game/GSShowObject.hh
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#ifndef WC3RE_GAME_GSSHOWOBJECT_HH__
|
||||||
|
#define WC3RE_GAME_GSSHOWOBJECT_HH__
|
||||||
|
|
||||||
|
#include "GameState.hh"
|
||||||
|
|
||||||
|
class ObjDecoder;
|
||||||
|
namespace render {
|
||||||
|
class Object;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace game {
|
||||||
|
class GSShowObject : public GameState {
|
||||||
|
public:
|
||||||
|
GSShowObject(render::Renderer& renderer, ObjDecoder& obj);
|
||||||
|
|
||||||
|
~GSShowObject() override;
|
||||||
|
|
||||||
|
void draw(unsigned delta_ms) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ObjDecoder& obj_;
|
||||||
|
std::unique_ptr<render::Object> object_;
|
||||||
|
unsigned delta_;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
95
objdecode.cc
Normal file
95
objdecode.cc
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include <cerrno>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "common.hh"
|
||||||
|
#include "util.hh"
|
||||||
|
#include "TreFile.hh"
|
||||||
|
#include "IffFile.hh"
|
||||||
|
#include "ObjDecoder.hh"
|
||||||
|
#include "render/Renderer.hh"
|
||||||
|
#include "game/GSShowObject.hh"
|
||||||
|
|
||||||
|
void usage(char *argv0) {
|
||||||
|
fprintf(stderr, "Usage: %s [-h] (tre-file name/crc)/iff-file\n", argv0);
|
||||||
|
fprintf(stderr, "\tAttempt to decode the object stored in iff-file, or in the\n\tiff-object \"name\"/\"crc\" contained in tre-file\n");
|
||||||
|
fprintf(stderr, "\t-h\tPrint this help\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
std::string inFile, objectSpec;
|
||||||
|
bool useTre = false;
|
||||||
|
{
|
||||||
|
int opt;
|
||||||
|
while ((opt = getopt(argc, argv, "h")) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'h':
|
||||||
|
usage(argv[0]);
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
usage(argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optind >= argc) {
|
||||||
|
usage(argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
inFile = argv[optind++];
|
||||||
|
|
||||||
|
if (optind < argc) {
|
||||||
|
useTre = true;
|
||||||
|
objectSpec = argv[optind];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
MmapFile mmap{inFile};
|
||||||
|
|
||||||
|
std::unique_ptr<TreFile> tre;
|
||||||
|
TreFile::Object object;
|
||||||
|
std::unique_ptr<ObjDecoder> obj;
|
||||||
|
if (useTre) {
|
||||||
|
tre = std::make_unique<TreFile>(mmap.data(), mmap.size());
|
||||||
|
|
||||||
|
// Try to parse objectSpec as CRC
|
||||||
|
try {
|
||||||
|
unsigned long CRC = std::stoul(objectSpec, nullptr, 16);
|
||||||
|
if (CRC <= std::numeric_limits<uint32_t>::max()) {
|
||||||
|
object = tre->openCRC(CRC);
|
||||||
|
}
|
||||||
|
} catch (std::invalid_argument &ex) {
|
||||||
|
} catch (std::out_of_range &ex) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!object) // Wasn't a CRC, try as name
|
||||||
|
object = tre->openName(objectSpec);
|
||||||
|
|
||||||
|
obj = std::make_unique<ObjDecoder>(object.data(), object.size());
|
||||||
|
} else
|
||||||
|
obj = std::make_unique<ObjDecoder>(mmap.data(), mmap.size());
|
||||||
|
|
||||||
|
render::Renderer renderer;
|
||||||
|
renderer.pushGS(std::make_unique<game::GSShowObject>(renderer, *obj));
|
||||||
|
|
||||||
|
renderer.run();
|
||||||
|
} catch (POSIXException &ex) {
|
||||||
|
fflush(stdout);
|
||||||
|
fprintf(stderr, "%s\n", ex.toString().c_str());
|
||||||
|
return 2;
|
||||||
|
} catch (Exception &ex) {
|
||||||
|
fflush(stdout);
|
||||||
|
fprintf(stderr, "%s\n", ex.toString().c_str());
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
107
render/Object.cc
Normal file
107
render/Object.cc
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
#include <glbinding/gl/gl.h>
|
||||||
|
|
||||||
|
#include <glm/gtx/transform.hpp>
|
||||||
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
|
||||||
|
#include "Object.hh"
|
||||||
|
#include "ProgramProvider.hh"
|
||||||
|
#include "Renderer.hh"
|
||||||
|
#include "ObjDecoder.hh"
|
||||||
|
|
||||||
|
using namespace gl;
|
||||||
|
|
||||||
|
namespace render {
|
||||||
|
namespace {
|
||||||
|
struct VertexAttribs {
|
||||||
|
int32_t vertex[3];
|
||||||
|
uint16_t texCoords[2];
|
||||||
|
} __attribute__((__packed__));
|
||||||
|
}
|
||||||
|
|
||||||
|
Object::Object(Renderer& renderer, ObjDecoder& obj)
|
||||||
|
: Drawable(renderer),
|
||||||
|
vbo_()
|
||||||
|
{
|
||||||
|
program_ = ProgramProvider::getInstance().getProgram("object", "object");
|
||||||
|
auto& tris = obj.getTriangles();
|
||||||
|
auto& quads = obj.getQuads();
|
||||||
|
numVertices_ = (tris.size()*3+quads.size()*6);
|
||||||
|
vbo_ = VBOManager::getInstance().alloc(sizeof(VertexAttribs)*numVertices_);
|
||||||
|
|
||||||
|
glGenVertexArrays(1, &vertexArray_.get());
|
||||||
|
std::vector<VertexAttribs> vertexAttribs;
|
||||||
|
vertexAttribs.reserve(numVertices_);
|
||||||
|
|
||||||
|
auto& vertices = obj.getVertices();
|
||||||
|
for (auto& tri : tris) {
|
||||||
|
for (unsigned i = 0;i < 3;++i) {
|
||||||
|
VertexAttribs attrs;
|
||||||
|
std::copy(vertices.at(tri.vertIdx[i]).begin(), vertices.at(tri.vertIdx[i]).end(),
|
||||||
|
attrs.vertex);
|
||||||
|
std::copy(tri.texCoords[i].begin(), tri.texCoords[i].end(),
|
||||||
|
attrs.texCoords);
|
||||||
|
|
||||||
|
vertexAttribs.push_back(attrs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& quad : quads) {
|
||||||
|
for (unsigned i = 0;i < 3;++i) {
|
||||||
|
VertexAttribs attrs;
|
||||||
|
std::copy(vertices.at(quad.vertIdx[i]).begin(), vertices.at(quad.vertIdx[i]).end(),
|
||||||
|
attrs.vertex);
|
||||||
|
std::copy(quad.texCoords[i].begin(), quad.texCoords[i].end(),
|
||||||
|
attrs.texCoords);
|
||||||
|
|
||||||
|
vertexAttribs.push_back(attrs);
|
||||||
|
}
|
||||||
|
for (unsigned i = 0;i < 3;++i) {
|
||||||
|
VertexAttribs attrs;
|
||||||
|
std::copy(vertices.at(quad.vertIdx[i+1]).begin(), vertices.at(quad.vertIdx[i+1]).end(),
|
||||||
|
attrs.vertex);
|
||||||
|
std::copy(quad.texCoords[i+1].begin(), quad.texCoords[i+1].end(),
|
||||||
|
attrs.texCoords);
|
||||||
|
|
||||||
|
vertexAttribs.push_back(attrs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// std::vector<VertexAttribs> vertexAttribs = {
|
||||||
|
// {{-1500, -1500, 0}, {0, 0}},
|
||||||
|
// {{-1500, 1500, 0}, {0, 0}},
|
||||||
|
// {{1500, -1500, 0}, {0, 0}},
|
||||||
|
// {{1500, 1500, 0}, {0, 0}}};
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, vbo_.getVBOId());
|
||||||
|
glBindVertexArray(vertexArray_);
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glVertexAttribPointer(0, 3, GL_INT, GL_FALSE, sizeof(VertexAttribs),
|
||||||
|
vbo_.getOfs(offsetof(VertexAttribs, vertex)));
|
||||||
|
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, vbo_.getBase(),
|
||||||
|
sizeof(VertexAttribs)*numVertices_,
|
||||||
|
vertexAttribs.data());
|
||||||
|
|
||||||
|
mvp_ = glm::perspectiveFov(75.0f, static_cast<float>(renderer.getWidth()),
|
||||||
|
static_cast<float>(renderer.getHeight()),
|
||||||
|
100.f, 20000.0f) *
|
||||||
|
glm::lookAt(glm::vec3(0.0f, 0.0f, 10000),
|
||||||
|
glm::vec3(0.0f, 0.0f, 0),
|
||||||
|
glm::vec3(0, 1, 0));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Object::draw()
|
||||||
|
{
|
||||||
|
glDisable(GL_CULL_FACE);
|
||||||
|
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||||
|
glUseProgram(program_);
|
||||||
|
glUniformMatrix4fv(0, 1, GL_FALSE, glm::value_ptr(mvp_));
|
||||||
|
glBindVertexArray(vertexArray_);
|
||||||
|
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, numVertices_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
29
render/Object.hh
Normal file
29
render/Object.hh
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#ifndef WC3RE_RENDER_OBJECT_HH__
|
||||||
|
#define WC3RE_RENDER_OBJECT_HH__
|
||||||
|
|
||||||
|
#define GLM_FORCE_RADIANS
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
#include "Drawable.hh"
|
||||||
|
#include "GlResource.hh"
|
||||||
|
#include "VBOManager.hh"
|
||||||
|
|
||||||
|
class ObjDecoder;
|
||||||
|
|
||||||
|
namespace render {
|
||||||
|
class Object : public Drawable {
|
||||||
|
public:
|
||||||
|
Object(Renderer& renderer, ObjDecoder& obj);
|
||||||
|
|
||||||
|
void draw() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
VertexArrayResource vertexArray_;
|
||||||
|
gl::GLuint program_;
|
||||||
|
VBOManager::VBOAlloc vbo_;
|
||||||
|
glm::mat4 mvp_;
|
||||||
|
unsigned numVertices_;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
8
shaders/object.fs
Normal file
8
shaders/object.fs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#version 330 core
|
||||||
|
#extension GL_ARB_explicit_uniform_location : enable
|
||||||
|
|
||||||
|
out vec4 color;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
color = vec4(1.0, 1.0, 1.0, 1.0);
|
||||||
|
}
|
||||||
16
shaders/object.vs
Normal file
16
shaders/object.vs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#version 330 core
|
||||||
|
#extension GL_ARB_shading_language_420pack : enable
|
||||||
|
#extension GL_ARB_explicit_uniform_location : enable
|
||||||
|
|
||||||
|
layout(location = 0) uniform mat4 mvp_matrix;
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 vertex;
|
||||||
|
layout(location = 1) in vec2 vertexTC;
|
||||||
|
|
||||||
|
out vec2 fragTC;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
gl_Position = mvp_matrix * vec4(vertex, 1.0);
|
||||||
|
|
||||||
|
fragTC = vertexTC;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user