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.
|
||||
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
|
||||
game_CXXSRCS ::= game/GSMvePlay.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/GSShowObject.cc
|
||||
|
||||
iffexplore_CXXSRCS ::= iffexplore.cc IffFile.cc util.cc exceptions.cc
|
||||
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_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)
|
||||
|
||||
|
||||
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__
|
||||
|
||||
#include "GameState.hh"
|
||||
#include "render/sdlutil.hh"
|
||||
|
||||
class MveDecoder;
|
||||
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