obj loader and general updates
This commit is contained in:
@@ -113,8 +113,8 @@ You can use the Renderer with the following functions, all of which are in the g
|
||||
- GetRenderWidth() : float result
|
||||
- GetRenderHeight(): float result
|
||||
- GetCamera() : Camera? result
|
||||
- LoadModel(string directory, string name, opt string identifier, opt Matrix transform) : Model? result
|
||||
- LoadWorldInfo(string directory, string name)
|
||||
- LoadModel(string fileName, opt string identifier, opt Matrix transform) : Model? result
|
||||
- LoadWorldInfo(string fileName)
|
||||
- FinishLoading()
|
||||
- SetEnvironmentMap(Texture cubemap)
|
||||
- SetColorGrading(Texture texture2D)
|
||||
|
||||
+4
-14
@@ -663,28 +663,18 @@ void EditorComponent::Load()
|
||||
// use the contents of szFile to initialize itself.
|
||||
ofn.lpstrFile[0] = '\0';
|
||||
ofn.nMaxFile = sizeof(szFile);
|
||||
ofn.lpstrFilter = "Wicked Model Format\0*.wimf;*.wio\0";
|
||||
ofn.lpstrFilter = "Model Formats\0*.wimf;*.wio;*.obj\0";
|
||||
ofn.nFilterIndex = 1;
|
||||
ofn.lpstrFileTitle = NULL;
|
||||
ofn.nMaxFileTitle = 0;
|
||||
ofn.lpstrInitialDir = NULL;
|
||||
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
|
||||
if (GetOpenFileNameA(&ofn) == TRUE) {
|
||||
if (GetOpenFileNameA(&ofn) == TRUE)
|
||||
{
|
||||
string fileName = ofn.lpstrFile;
|
||||
string dir, file;
|
||||
wiHelper::SplitPath(fileName, dir, file);
|
||||
|
||||
if (fileName.substr(fileName.length() - 5).compare(".wimf") == 0)
|
||||
{
|
||||
file = file.substr(0, file.length() - 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
file = file.substr(0, file.length() - 4);
|
||||
}
|
||||
|
||||
loader->addLoadingFunction([=] {
|
||||
wiRenderer::LoadModel(dir, file);
|
||||
wiRenderer::LoadModel(fileName);
|
||||
});
|
||||
loader->onFinished([=] {
|
||||
main->activateComponent(this);
|
||||
|
||||
+19
-1
@@ -1,6 +1,9 @@
|
||||
#include "stdafx.h"
|
||||
#include "MeshWindow.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
MeshWindow::MeshWindow(wiGUI* gui) : GUI(gui)
|
||||
{
|
||||
@@ -11,13 +14,20 @@ MeshWindow::MeshWindow(wiGUI* gui) : GUI(gui)
|
||||
|
||||
|
||||
meshWindow = new wiWindow(GUI, "Mesh Window");
|
||||
meshWindow->SetSize(XMFLOAT2(400, 300));
|
||||
meshWindow->SetSize(XMFLOAT2(800, 600));
|
||||
meshWindow->SetEnabled(false);
|
||||
GUI->AddWidget(meshWindow);
|
||||
|
||||
float x = 200;
|
||||
float y = 0;
|
||||
|
||||
meshInfoLabel = new wiLabel("Mesh Info");
|
||||
meshInfoLabel->SetPos(XMFLOAT2(x, y += 30));
|
||||
meshInfoLabel->SetSize(XMFLOAT2(400, 150));
|
||||
meshWindow->AddWidget(meshInfoLabel);
|
||||
|
||||
y += 160;
|
||||
|
||||
doubleSidedCheckBox = new wiCheckBox("Double Sided: ");
|
||||
doubleSidedCheckBox->SetTooltip("If enabled, the inside of the mesh will be visible.");
|
||||
doubleSidedCheckBox->SetPos(XMFLOAT2(x, y += 30));
|
||||
@@ -114,6 +124,13 @@ void MeshWindow::SetMesh(Mesh* mesh)
|
||||
this->mesh = mesh;
|
||||
if (mesh != nullptr)
|
||||
{
|
||||
stringstream ss("");
|
||||
ss << "Mesh name: " << mesh->name << endl;
|
||||
ss << "Vertex count: " << mesh->vertices_POS.size() << endl;
|
||||
ss << "Index count: " << mesh->indices.size() << endl;
|
||||
ss << "Subset count: " << mesh->subsets.size() << endl;
|
||||
meshInfoLabel->SetText(ss.str());
|
||||
|
||||
doubleSidedCheckBox->SetCheck(mesh->doubleSided);
|
||||
massSlider->SetValue(mesh->mass);
|
||||
frictionSlider->SetValue(mesh->friction);
|
||||
@@ -123,6 +140,7 @@ void MeshWindow::SetMesh(Mesh* mesh)
|
||||
}
|
||||
else
|
||||
{
|
||||
meshInfoLabel->SetText("Select a mesh...");
|
||||
meshWindow->SetEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ public:
|
||||
Mesh* mesh;
|
||||
|
||||
wiWindow* meshWindow;
|
||||
wiLabel* meshInfoLabel;
|
||||
wiCheckBox* doubleSidedCheckBox;
|
||||
wiSlider* massSlider;
|
||||
wiSlider* frictionSlider;
|
||||
|
||||
+1
-2
@@ -58,8 +58,7 @@ runProcess(function()
|
||||
local row = 16
|
||||
for i = 1, row do
|
||||
for j = 1, row do
|
||||
LoadModel("C:\\PROJECTS\\BLENDER\\Stormtrooper\\", "Stormtrooper", "_"..i..j,matrix.Translation(Vector(i*2-row,0,j*2-row)));
|
||||
--LoadModel("C:\\PROJECTS\\WickedEngine\\WickedEngine\\models\\Sample\\", "nosun", "_common",matrix.Translation(Vector(i*500-row*500,0,j*500-row*500)));
|
||||
LoadModel("C:\\PROJECTS\\BLENDER\\Stormtrooper\\Stormtrooper.wimf", "_"..i..j,matrix.Translation(Vector(i*2-row,0,j*2-row)));
|
||||
--waitSeconds(0.05)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -89,8 +89,9 @@ Test model and scene files are now available in the WickedEngine/models director
|
||||
|
||||
### Model import/export:
|
||||
|
||||
You can export models from Blender with the provided python script: io_export_wicked_wi_bin.py <br/>
|
||||
Common model formats like FBX are not supported currently, only the custom model format which is exportable from Blender.<br/>
|
||||
The only common model format supported right now is Wavefront OBJ.<br/>
|
||||
|
||||
For advanced model format capabilities, like skeletal animations, particle systems, physics, etc. use the provided Blender exporter python script: io_export_wicked_wi_bin.py <br/>
|
||||
|
||||
Notes on exporting:
|
||||
- Names should not contain spaces inside Blender<br/>
|
||||
|
||||
+3
-3
@@ -73,16 +73,16 @@ TestsRenderer::TestsRenderer()
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
wiRenderer::LoadModel("../models/Stormtrooper/", "Stormtrooper");
|
||||
wiRenderer::LoadModel("../models/Stormtrooper/Stormtrooper.wimf");
|
||||
break;
|
||||
case 2:
|
||||
wiLua::GetGlobal()->RunFile("test_script.lua");
|
||||
break;
|
||||
case 3:
|
||||
wiRenderer::LoadModel("../models/SoftBody/", "flag")->Translate(XMFLOAT3(0, -1, 2));
|
||||
wiRenderer::LoadModel("../models/SoftBody/flag.wimf")->Translate(XMFLOAT3(0, -1, 2));
|
||||
break;
|
||||
case 4:
|
||||
wiRenderer::LoadModel("../models/Emitter/", "emitter")->Translate(XMFLOAT3(0, 2, 2));
|
||||
wiRenderer::LoadModel("../models/Emitter/emitter.wimf")->Translate(XMFLOAT3(0, 2, 2));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ debugout("Begin script: test_script.lua");
|
||||
|
||||
|
||||
-- Load a model:
|
||||
local model = LoadModel("../models/Stormtrooper/", "Stormtrooper");
|
||||
local model = LoadModel("../models/Stormtrooper/Stormtrooper.wimf");
|
||||
|
||||
-- Load an image:
|
||||
local sprite = Sprite("images/HelloWorld.png");
|
||||
|
||||
@@ -343,6 +343,7 @@
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)wiMeshOptimizer.h" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)wiNetwork.h" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)wiNetwork_BindLua.h" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)wiOBJLoader.h" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)wiOcean.h" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)wiPHYSICS.h" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)wiProfiler.h" />
|
||||
|
||||
@@ -1140,6 +1140,9 @@
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)wiTGATextureLoader.h">
|
||||
<Filter>ENGINE\Helpers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)wiOBJLoader.h">
|
||||
<Filter>ENGINE\Helpers</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)LUA\lapi.c">
|
||||
|
||||
@@ -217,6 +217,30 @@ namespace wiHelper
|
||||
SplitPath(fullPath, ret, empty);
|
||||
return ret;
|
||||
}
|
||||
|
||||
string GetExtensionFromFileName(const string& filename)
|
||||
{
|
||||
size_t idx = filename.rfind('.');
|
||||
|
||||
if (idx != std::string::npos)
|
||||
{
|
||||
std::string extension = filename.substr(idx + 1);
|
||||
return extension;
|
||||
}
|
||||
|
||||
// No extension found
|
||||
return "";
|
||||
}
|
||||
|
||||
void RemoveExtensionFromFileName(std::string& filename)
|
||||
{
|
||||
string extension = GetExtensionFromFileName(filename);
|
||||
|
||||
if (!extension.empty())
|
||||
{
|
||||
filename = filename.substr(0, filename.length() - extension.length() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void Sleep(float milliseconds)
|
||||
{
|
||||
|
||||
@@ -54,6 +54,10 @@ namespace wiHelper
|
||||
|
||||
std::string GetDirectoryFromPath(const std::string& fullPath);
|
||||
|
||||
std::string GetExtensionFromFileName(const std::string& filename);
|
||||
|
||||
void RemoveExtensionFromFileName(std::string& filename);
|
||||
|
||||
void Sleep(float milliseconds);
|
||||
};
|
||||
|
||||
|
||||
+243
-39
@@ -10,12 +10,17 @@
|
||||
#include "wiTextureHelper.h"
|
||||
#include "wiPHYSICS.h"
|
||||
#include "wiArchive.h"
|
||||
#include "wiBackLog.h"
|
||||
|
||||
#define FORSYTH_IMPLEMENTATION
|
||||
#include "wiMeshOptimizer.h"
|
||||
|
||||
#define TINYOBJLOADER_IMPLEMENTATION
|
||||
#include "wiObjLoader.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
|
||||
using namespace std;
|
||||
using namespace wiGraphicsTypes;
|
||||
@@ -983,52 +988,71 @@ void LoadWiHitSpheres(const std::string& directory, const std::string& name, con
|
||||
// }
|
||||
//}
|
||||
}
|
||||
void LoadWiWorldInfo(const std::string&directory, const std::string& name, WorldInfo& worldInfo, Wind& wind){
|
||||
stringstream filename("");
|
||||
filename<<directory<<name;
|
||||
void LoadWiWorldInfo(const std::string& fileName, WorldInfo& worldInfo, Wind& wind)
|
||||
{
|
||||
string extension = wiHelper::GetExtensionFromFileName(fileName);
|
||||
|
||||
ifstream file(filename.str().c_str());
|
||||
if(file){
|
||||
while(!file.eof()){
|
||||
string realName;
|
||||
if (!extension.compare("wiw"))
|
||||
{
|
||||
realName = fileName;
|
||||
}
|
||||
else if (extension.empty())
|
||||
{
|
||||
realName = fileName + ".wiw";
|
||||
}
|
||||
else
|
||||
{
|
||||
realName = fileName;
|
||||
wiHelper::RemoveExtensionFromFileName(realName);
|
||||
realName += ".wiw";
|
||||
}
|
||||
|
||||
ifstream file(realName);
|
||||
if (file)
|
||||
{
|
||||
while (!file.eof())
|
||||
{
|
||||
string read = "";
|
||||
file>>read;
|
||||
switch(read[0]){
|
||||
file >> read;
|
||||
switch (read[0])
|
||||
{
|
||||
case 'h':
|
||||
file>>worldInfo.horizon.x>>worldInfo.horizon.y>>worldInfo.horizon.z;
|
||||
file >> worldInfo.horizon.x >> worldInfo.horizon.y >> worldInfo.horizon.z;
|
||||
// coming from blender, de-apply gamma correction:
|
||||
worldInfo.horizon.x = powf(worldInfo.horizon.x, 1.0f / 2.2f);
|
||||
worldInfo.horizon.y = powf(worldInfo.horizon.y, 1.0f / 2.2f);
|
||||
worldInfo.horizon.z = powf(worldInfo.horizon.z, 1.0f / 2.2f);
|
||||
break;
|
||||
case 'z':
|
||||
file>>worldInfo.zenith.x>>worldInfo.zenith.y>>worldInfo.zenith.z;
|
||||
file >> worldInfo.zenith.x >> worldInfo.zenith.y >> worldInfo.zenith.z;
|
||||
// coming from blender, de-apply gamma correction:
|
||||
worldInfo.zenith.x = powf(worldInfo.zenith.x, 1.0f / 2.2f);
|
||||
worldInfo.zenith.y = powf(worldInfo.zenith.y, 1.0f / 2.2f);
|
||||
worldInfo.zenith.z = powf(worldInfo.zenith.z, 1.0f / 2.2f);
|
||||
break;
|
||||
case 'a':
|
||||
file>>worldInfo.ambient.x>>worldInfo.ambient.y>>worldInfo.ambient.z;
|
||||
file >> worldInfo.ambient.x >> worldInfo.ambient.y >> worldInfo.ambient.z;
|
||||
// coming from blender, de-apply gamma correction:
|
||||
worldInfo.zenith.x = powf(worldInfo.zenith.x, 1.0f / 2.2f);
|
||||
worldInfo.zenith.y = powf(worldInfo.zenith.y, 1.0f / 2.2f);
|
||||
worldInfo.zenith.z = powf(worldInfo.zenith.z, 1.0f / 2.2f);
|
||||
break;
|
||||
case 'W':
|
||||
{
|
||||
XMFLOAT4 r;
|
||||
float s;
|
||||
file>>r.x>>r.y>>r.z>>r.w>>s;
|
||||
XMStoreFloat3(&wind.direction, XMVector3Transform( XMVectorSet(0,s,0,0),XMMatrixRotationQuaternion(XMLoadFloat4(&r)) ));
|
||||
}
|
||||
break;
|
||||
{
|
||||
XMFLOAT4 r;
|
||||
float s;
|
||||
file >> r.x >> r.y >> r.z >> r.w >> s;
|
||||
XMStoreFloat3(&wind.direction, XMVector3Transform(XMVectorSet(0, s, 0, 0), XMMatrixRotationQuaternion(XMLoadFloat4(&r))));
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
{
|
||||
float s,e,h;
|
||||
file>>s>>e>>h;
|
||||
worldInfo.fogSEH=XMFLOAT3(s,e,h);
|
||||
}
|
||||
break;
|
||||
{
|
||||
float s, e, h;
|
||||
file >> s >> e >> h;
|
||||
worldInfo.fogSEH = XMFLOAT3(s, e, h);
|
||||
}
|
||||
break;
|
||||
default:break;
|
||||
}
|
||||
}
|
||||
@@ -2557,21 +2581,201 @@ void Model::CleanUp()
|
||||
SAFE_DELETE(x);
|
||||
}
|
||||
}
|
||||
void Model::LoadFromDisk(const std::string& dir, const std::string& name, const std::string& identifier)
|
||||
void Model::LoadFromDisk(const std::string& fileName, const std::string& identifier)
|
||||
{
|
||||
wiArchive archive(dir + name + ".wimf", true);
|
||||
if (archive.IsOpen())
|
||||
string directory, name;
|
||||
wiHelper::SplitPath(fileName, directory, name);
|
||||
string extension = wiHelper::toUpper(wiHelper::GetExtensionFromFileName(name));
|
||||
wiHelper::RemoveExtensionFromFileName(name);
|
||||
|
||||
if (!extension.compare("WIMF"))
|
||||
{
|
||||
// New Import if wimf model is available
|
||||
this->Serialize(archive);
|
||||
wiArchive archive(fileName, true);
|
||||
if (archive.IsOpen())
|
||||
{
|
||||
this->Serialize(archive);
|
||||
}
|
||||
else
|
||||
{
|
||||
wiHelper::messageBox("Could not open archive!", "Error!");
|
||||
}
|
||||
}
|
||||
else if (!extension.compare("OBJ"))
|
||||
{
|
||||
tinyobj::attrib_t obj_attrib;
|
||||
vector<tinyobj::shape_t> obj_shapes;
|
||||
vector<tinyobj::material_t> obj_materials;
|
||||
string obj_errors;
|
||||
|
||||
bool success = tinyobj::LoadObj(&obj_attrib, &obj_shapes, &obj_materials, &obj_errors, fileName.c_str(), directory.c_str(), true);
|
||||
|
||||
if (success)
|
||||
{
|
||||
this->name = name + identifier;
|
||||
|
||||
// Load material library:
|
||||
vector<Material*> materialLibrary = {};
|
||||
for (auto& obj_material : obj_materials)
|
||||
{
|
||||
Material* material = new Material(obj_material.name + identifier);
|
||||
|
||||
material->diffuseColor = XMFLOAT3(obj_material.diffuse[0], obj_material.diffuse[1], obj_material.diffuse[2]);
|
||||
material->textureName = obj_material.diffuse_texname;
|
||||
material->displacementMapName = obj_material.displacement_texname;
|
||||
if (material->displacementMapName.empty())
|
||||
{
|
||||
material->displacementMapName = obj_material.bump_texname;
|
||||
}
|
||||
material->emissive = max(obj_material.emission[0], max(obj_material.emission[1], obj_material.emission[2]));
|
||||
//obj_material.emissive_texname;
|
||||
material->refractionIndex = obj_material.ior;
|
||||
material->metalness = obj_material.metallic;
|
||||
//obj_material.metallic_texname;
|
||||
material->normalMapName = obj_material.normal_texname;
|
||||
material->refMapName = obj_material.reflection_texname;
|
||||
material->roughness = obj_material.roughness;
|
||||
//obj_material.roughness_texname;
|
||||
material->specular_power = (int)obj_material.shininess;
|
||||
material->specular = XMFLOAT4(obj_material.specular[0], obj_material.specular[1], obj_material.specular[2], 1);
|
||||
material->specularMapName = obj_material.specular_texname;
|
||||
|
||||
if (!material->refMapName.empty())
|
||||
{
|
||||
material->refMapName = directory + material->refMapName;
|
||||
material->refMap = (Texture2D*)wiResourceManager::GetGlobal()->add(material->refMapName);
|
||||
}
|
||||
if (!material->textureName.empty())
|
||||
{
|
||||
material->textureName = directory + material->textureName;
|
||||
material->texture = (Texture2D*)wiResourceManager::GetGlobal()->add(material->textureName);
|
||||
}
|
||||
if (!material->normalMapName.empty())
|
||||
{
|
||||
material->normalMapName = directory + material->normalMapName;
|
||||
material->normalMap = (Texture2D*)wiResourceManager::GetGlobal()->add(material->normalMapName);
|
||||
}
|
||||
if (!material->displacementMapName.empty())
|
||||
{
|
||||
material->displacementMapName = directory + material->displacementMapName;
|
||||
material->displacementMap = (Texture2D*)wiResourceManager::GetGlobal()->add(material->displacementMapName);
|
||||
}
|
||||
if (!material->specularMapName.empty())
|
||||
{
|
||||
material->specularMapName = directory + material->specularMapName;
|
||||
material->specularMap = (Texture2D*)wiResourceManager::GetGlobal()->add(material->specularMapName);
|
||||
}
|
||||
|
||||
material->ConvertToPhysicallyBasedMaterial();
|
||||
|
||||
materialLibrary.push_back(material); // for subset-indexing...
|
||||
this->materials.insert(make_pair(material->name, material));
|
||||
}
|
||||
|
||||
// Load objects, meshes:
|
||||
for (auto& shape : obj_shapes)
|
||||
{
|
||||
Object* object = new Object(shape.name + identifier);
|
||||
Mesh* mesh = new Mesh(shape.name + "_mesh" + identifier);
|
||||
|
||||
object->mesh = mesh;
|
||||
mesh->renderable = true;
|
||||
|
||||
XMFLOAT3 min = XMFLOAT3(FLT_MAX, FLT_MAX, FLT_MAX);
|
||||
XMFLOAT3 max = XMFLOAT3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
|
||||
|
||||
unordered_map<int, int> registered_materialIndices = {};
|
||||
unordered_map<size_t, uint32_t> uniqueVertices = {};
|
||||
|
||||
for (size_t i = 0; i < shape.mesh.indices.size(); i += 3)
|
||||
{
|
||||
// Reorder face-winding to match defaults:
|
||||
tinyobj::index_t reordered_indices[] = {
|
||||
shape.mesh.indices[i + 0],
|
||||
shape.mesh.indices[i + 2],
|
||||
shape.mesh.indices[i + 1],
|
||||
};
|
||||
|
||||
for (auto& index : reordered_indices)
|
||||
{
|
||||
Mesh::Vertex_FULL vert;
|
||||
|
||||
vert.pos = XMFLOAT4(
|
||||
obj_attrib.vertices[index.vertex_index * 3 + 0],
|
||||
obj_attrib.vertices[index.vertex_index * 3 + 1],
|
||||
obj_attrib.vertices[index.vertex_index * 3 + 2],
|
||||
0
|
||||
);
|
||||
|
||||
if (!obj_attrib.normals.empty())
|
||||
{
|
||||
vert.nor = XMFLOAT4(
|
||||
obj_attrib.normals[index.normal_index * 3 + 0],
|
||||
obj_attrib.normals[index.normal_index * 3 + 1],
|
||||
obj_attrib.normals[index.normal_index * 3 + 2],
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
if (!obj_attrib.texcoords.empty())
|
||||
{
|
||||
vert.tex = XMFLOAT4(
|
||||
obj_attrib.texcoords[index.texcoord_index * 2 + 0],
|
||||
1 - obj_attrib.texcoords[index.texcoord_index * 2 + 1],
|
||||
0, 0
|
||||
);
|
||||
}
|
||||
|
||||
int materialIndex = shape.mesh.material_ids[i / 3]; // this indexes the material library
|
||||
if (registered_materialIndices.count(materialIndex) == 0)
|
||||
{
|
||||
registered_materialIndices[materialIndex] = (int)mesh->subsets.size();
|
||||
mesh->subsets.push_back(MeshSubset());
|
||||
Material* material = materialLibrary[materialIndex];
|
||||
mesh->subsets.back().material = material;
|
||||
mesh->materialNames.push_back(material->name);
|
||||
}
|
||||
vert.tex.z = (float)registered_materialIndices[materialIndex]; // this indexes a mesh subset
|
||||
|
||||
// eliminate duplicate vertices by means of hashing:
|
||||
size_t hashes[] = {
|
||||
hash<int>{}(index.vertex_index),
|
||||
hash<int>{}(index.normal_index),
|
||||
hash<int>{}(index.texcoord_index),
|
||||
};
|
||||
size_t vertexHash = (hashes[0] ^ (hashes[1] << 1) >> 1) ^ (hashes[2] << 1);
|
||||
|
||||
if (uniqueVertices.count(vertexHash) == 0)
|
||||
{
|
||||
uniqueVertices[vertexHash] = (uint32_t)mesh->vertices_FULL.size();
|
||||
mesh->vertices_FULL.push_back(vert);
|
||||
}
|
||||
mesh->indices.push_back(uniqueVertices[vertexHash]);
|
||||
|
||||
min = wiMath::Min(min, XMFLOAT3(vert.pos.x, vert.pos.y, vert.pos.z));
|
||||
max = wiMath::Max(max, XMFLOAT3(vert.pos.x, vert.pos.y, vert.pos.z));
|
||||
}
|
||||
}
|
||||
mesh->aabb.create(min, max);
|
||||
|
||||
this->objects.insert(object);
|
||||
this->meshes.insert(make_pair(mesh->name, mesh));
|
||||
}
|
||||
|
||||
this->FinishLoading();
|
||||
}
|
||||
|
||||
if (!obj_errors.empty())
|
||||
{
|
||||
wiBackLog::post(obj_errors.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Old Import
|
||||
stringstream directory(""), armatureFilePath(""), materialLibFilePath(""), meshesFilePath(""), objectsFilePath("")
|
||||
// Old Importer
|
||||
|
||||
stringstream armatureFilePath(""), materialLibFilePath(""), meshesFilePath(""), objectsFilePath("")
|
||||
, actionsFilePath(""), lightsFilePath(""), decalsFilePath("");
|
||||
|
||||
directory << dir;
|
||||
armatureFilePath << name << ".wia";
|
||||
materialLibFilePath << name << ".wim";
|
||||
meshesFilePath << name << ".wi";
|
||||
@@ -2580,13 +2784,13 @@ void Model::LoadFromDisk(const std::string& dir, const std::string& name, const
|
||||
lightsFilePath << name << ".wil";
|
||||
decalsFilePath << name << ".wid";
|
||||
|
||||
LoadWiArmatures(directory.str(), armatureFilePath.str(), identifier, armatures);
|
||||
LoadWiMaterialLibrary(directory.str(), materialLibFilePath.str(), identifier, "textures/", materials);
|
||||
LoadWiMeshes(directory.str(), meshesFilePath.str(), identifier, meshes, armatures, materials);
|
||||
LoadWiObjects(directory.str(), objectsFilePath.str(), identifier, objects, armatures, meshes, materials);
|
||||
LoadWiActions(directory.str(), actionsFilePath.str(), identifier, armatures);
|
||||
LoadWiLights(directory.str(), lightsFilePath.str(), identifier, lights);
|
||||
LoadWiDecals(directory.str(), decalsFilePath.str(), "textures/", decals);
|
||||
LoadWiArmatures(directory, armatureFilePath.str(), identifier, armatures);
|
||||
LoadWiMaterialLibrary(directory, materialLibFilePath.str(), identifier, "textures/", materials);
|
||||
LoadWiMeshes(directory, meshesFilePath.str(), identifier, meshes, armatures, materials);
|
||||
LoadWiObjects(directory, objectsFilePath.str(), identifier, objects, armatures, meshes, materials);
|
||||
LoadWiActions(directory, actionsFilePath.str(), identifier, armatures);
|
||||
LoadWiLights(directory, lightsFilePath.str(), identifier, lights);
|
||||
LoadWiDecals(directory, decalsFilePath.str(), "textures/", decals);
|
||||
|
||||
FinishLoading();
|
||||
}
|
||||
|
||||
@@ -1223,7 +1223,7 @@ struct Model : public Transform
|
||||
Model();
|
||||
virtual ~Model();
|
||||
void CleanUp();
|
||||
void LoadFromDisk(const std::string& dir, const std::string& name, const std::string& identifier);
|
||||
void LoadFromDisk(const std::string& fileName, const std::string& identifier);
|
||||
void FinishLoading();
|
||||
void UpdateModel();
|
||||
void Add(Object* value);
|
||||
@@ -1267,7 +1267,7 @@ void LoadWiActions(const std::string& directory, const std::string& filename, co
|
||||
void LoadWiLights(const std::string& directory, const std::string& filename, const std::string& identifier, std::list<Light*>& lights);
|
||||
void LoadWiHitSpheres(const std::string& directory, const std::string& name, const std::string& identifier, std::vector<HitSphere*>& spheres
|
||||
,const std::list<Armature*>& armatures);
|
||||
void LoadWiWorldInfo(const std::string&directory, const std::string& name, WorldInfo& worldInfo, Wind& wind);
|
||||
void LoadWiWorldInfo(const std::string& fileName, WorldInfo& worldInfo, Wind& wind);
|
||||
void LoadWiCameras(const std::string&directory, const std::string& name, const std::string& identifier, std::vector<Camera>& cameras
|
||||
,const std::list<Armature*>& armatures);
|
||||
void LoadWiDecals(const std::string&directory, const std::string& name, const std::string& texturesDir, std::list<Decal*>& decals);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+16
-19
@@ -2990,14 +2990,14 @@ void wiRenderer::UpdatePerFrameData(float dt)
|
||||
switch (l->GetType())
|
||||
{
|
||||
case Light::DIRECTIONAL:
|
||||
if ((shadowCounter_2D + 2) < SHADOWCOUNT_2D)
|
||||
if (!l->shadowCam_dirLight.empty() && (shadowCounter_2D + 2) < SHADOWCOUNT_2D)
|
||||
{
|
||||
l->shadowMap_index = shadowCounter_2D;
|
||||
shadowCounter_2D += 3;
|
||||
}
|
||||
break;
|
||||
case Light::SPOT:
|
||||
if (shadowCounter_2D < SHADOWCOUNT_2D)
|
||||
if (!l->shadowCam_spotLight.empty() && shadowCounter_2D < SHADOWCOUNT_2D)
|
||||
{
|
||||
l->shadowMap_index = shadowCounter_2D;
|
||||
shadowCounter_2D++;
|
||||
@@ -3008,7 +3008,7 @@ void wiRenderer::UpdatePerFrameData(float dt)
|
||||
case Light::DISC:
|
||||
case Light::RECTANGLE:
|
||||
case Light::TUBE:
|
||||
if (shadowCounter_Cube < SHADOWCOUNT_CUBE)
|
||||
if (!l->shadowCam_pointLight.empty() && shadowCounter_Cube < SHADOWCOUNT_CUBE)
|
||||
{
|
||||
l->shadowMap_index = shadowCounter_Cube;
|
||||
shadowCounter_Cube++;
|
||||
@@ -3124,7 +3124,7 @@ void wiRenderer::UpdateRenderData(GRAPHICSTHREAD threadID)
|
||||
entityArray[entityCounter].directionWS = l->GetDirection();
|
||||
entityArray[entityCounter].shadowKernel = 1.0f / SHADOWRES_2D;
|
||||
|
||||
if (shadowIndex >= 0)
|
||||
if (l->shadow && shadowIndex >= 0 && !l->shadowCam_dirLight.empty())
|
||||
{
|
||||
matrixArray[shadowIndex + 0] = l->shadowCam_dirLight[0].getVP();
|
||||
matrixArray[shadowIndex + 1] = l->shadowCam_dirLight[1].getVP();
|
||||
@@ -6443,11 +6443,11 @@ void wiRenderer::RayIntersectMeshes(const RAY& ray, const CulledList& culledObje
|
||||
_vertices = (XMVECTOR*)_mm_malloc(sizeof(XMVECTOR)*_arraySize, 16);
|
||||
}
|
||||
|
||||
XMMATRIX& objectMat = object->getMatrix();
|
||||
XMMATRIX& objectMat_Inverse = XMMatrixInverse(nullptr, objectMat);
|
||||
XMMATRIX objectMat = object->getMatrix();
|
||||
XMMATRIX objectMat_Inverse = XMMatrixInverse(nullptr, objectMat);
|
||||
|
||||
XMVECTOR& rayOrigin_local = XMVector3Transform(rayOrigin, objectMat_Inverse);
|
||||
XMVECTOR& rayDirection_local = XMVector3Normalize(XMVector3TransformNormal(rayDirection, objectMat_Inverse));
|
||||
XMVECTOR rayOrigin_local = XMVector3Transform(rayOrigin, objectMat_Inverse);
|
||||
XMVECTOR rayDirection_local = XMVector3Normalize(XMVector3TransformNormal(rayDirection, objectMat_Inverse));
|
||||
|
||||
Mesh::Vertex_FULL _tmpvert;
|
||||
|
||||
@@ -6477,14 +6477,11 @@ void wiRenderer::RayIntersectMeshes(const RAY& ray, const CulledList& culledObje
|
||||
for (size_t i = 0; i < mesh->indices.size(); i += 3)
|
||||
{
|
||||
int i0 = mesh->indices[i], i1 = mesh->indices[i + 1], i2 = mesh->indices[i + 2];
|
||||
XMVECTOR& V0 = _vertices[i0];
|
||||
XMVECTOR& V1 = _vertices[i1];
|
||||
XMVECTOR& V2 = _vertices[i2];
|
||||
float distance = 0;
|
||||
if (TriangleTests::Intersects(rayOrigin_local, rayDirection_local, V0, V1, V2, distance))
|
||||
float distance;
|
||||
if (TriangleTests::Intersects(rayOrigin_local, rayDirection_local, _vertices[i0], _vertices[i1], _vertices[i2], distance))
|
||||
{
|
||||
XMVECTOR& pos = XMVector3Transform(XMVectorAdd(rayOrigin_local, rayDirection_local*distance), objectMat);
|
||||
XMVECTOR& nor = XMVector3TransformNormal(XMVector3Normalize(XMVector3Cross(XMVectorSubtract(V2, V1), XMVectorSubtract(V1, V0))), objectMat);
|
||||
XMVECTOR& nor = XMVector3TransformNormal(XMVector3Normalize(XMVector3Cross(XMVectorSubtract(_vertices[i2], _vertices[i1]), XMVectorSubtract(_vertices[i1], _vertices[i0]))), objectMat);
|
||||
Picked picked = Picked();
|
||||
picked.transform = object;
|
||||
picked.object = object;
|
||||
@@ -6569,7 +6566,7 @@ void wiRenderer::CalculateVertexAO(Object* object)
|
||||
//mesh->calculatedAO = true;
|
||||
}
|
||||
|
||||
Model* wiRenderer::LoadModel(const std::string& dir, const std::string& name, const XMMATRIX& transform, const std::string& ident)
|
||||
Model* wiRenderer::LoadModel(const std::string& fileName, const XMMATRIX& transform, const std::string& ident)
|
||||
{
|
||||
static int unique_identifier = 0;
|
||||
|
||||
@@ -6577,21 +6574,21 @@ Model* wiRenderer::LoadModel(const std::string& dir, const std::string& name, co
|
||||
idss<<"_"<<ident;
|
||||
|
||||
Model* model = new Model;
|
||||
model->LoadFromDisk(dir,name,idss.str());
|
||||
model->LoadFromDisk(fileName, idss.str());
|
||||
|
||||
model->transform(transform);
|
||||
|
||||
AddModel(model);
|
||||
|
||||
LoadWorldInfo(dir, name);
|
||||
LoadWorldInfo(fileName);
|
||||
|
||||
unique_identifier++;
|
||||
|
||||
return model;
|
||||
}
|
||||
void wiRenderer::LoadWorldInfo(const std::string& dir, const std::string& name)
|
||||
void wiRenderer::LoadWorldInfo(const std::string& fileName)
|
||||
{
|
||||
LoadWiWorldInfo(dir, name+".wiw", GetScene().worldInfo, GetScene().wind);
|
||||
LoadWiWorldInfo(fileName, GetScene().worldInfo, GetScene().wind);
|
||||
}
|
||||
void wiRenderer::LoadDefaultLighting()
|
||||
{
|
||||
|
||||
@@ -575,8 +575,8 @@ public:
|
||||
static void SetOceanEnabled(bool enabled, const wiOceanParameter& params);
|
||||
static wiOcean* GetOcean() { return ocean; }
|
||||
|
||||
static Model* LoadModel(const std::string& dir, const std::string& name, const XMMATRIX& transform = XMMatrixIdentity(), const std::string& ident = "common");
|
||||
static void LoadWorldInfo(const std::string& dir, const std::string& name);
|
||||
static Model* LoadModel(const std::string& fileName, const XMMATRIX& transform = XMMatrixIdentity(), const std::string& ident = "common");
|
||||
static void LoadWorldInfo(const std::string& fileName);
|
||||
static void LoadDefaultLighting();
|
||||
|
||||
static void PutEnvProbe(const XMFLOAT3& position, int resolution = 256);
|
||||
|
||||
@@ -293,50 +293,48 @@ namespace wiRenderer_BindLua
|
||||
int LoadModel(lua_State* L)
|
||||
{
|
||||
int argc = wiLua::SGetArgCount(L);
|
||||
if (argc > 1)
|
||||
if (argc > 0)
|
||||
{
|
||||
string dir = wiLua::SGetString(L, 1);
|
||||
string name = wiLua::SGetString(L, 2);
|
||||
string fileName = wiLua::SGetString(L, 1);
|
||||
string identifier = "common";
|
||||
XMMATRIX transform = XMMatrixIdentity();
|
||||
if (argc > 2)
|
||||
if (argc > 1)
|
||||
{
|
||||
identifier = wiLua::SGetString(L, 3);
|
||||
if (argc > 3)
|
||||
identifier = wiLua::SGetString(L, 2);
|
||||
if (argc > 2)
|
||||
{
|
||||
Matrix_BindLua* matrix = Luna<Matrix_BindLua>::lightcheck(L, 4);
|
||||
Matrix_BindLua* matrix = Luna<Matrix_BindLua>::lightcheck(L, 3);
|
||||
if (matrix != nullptr)
|
||||
{
|
||||
transform = matrix->matrix;
|
||||
}
|
||||
else
|
||||
{
|
||||
wiLua::SError(L, "LoadModel(string directory, string name, opt string identifier, opt Matrix transform) argument is not a matrix!");
|
||||
wiLua::SError(L, "LoadModel(string fileName, opt string identifier, opt Matrix transform) argument is not a matrix!");
|
||||
}
|
||||
}
|
||||
}
|
||||
Model* model = wiRenderer::LoadModel(dir, name, transform, identifier);
|
||||
Model* model = wiRenderer::LoadModel(fileName, transform, identifier);
|
||||
Luna<Model_BindLua>::push(L, new Model_BindLua(model));
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
wiLua::SError(L, "LoadModel(string directory, string name, opt string identifier, opt Matrix transform) not enough arguments!");
|
||||
wiLua::SError(L, "LoadModel(string fileName, opt string identifier, opt Matrix transform) not enough arguments!");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int LoadWorldInfo(lua_State* L)
|
||||
{
|
||||
int argc = wiLua::SGetArgCount(L);
|
||||
if (argc > 1)
|
||||
if (argc > 0)
|
||||
{
|
||||
string dir = wiLua::SGetString(L, 1);
|
||||
string name = wiLua::SGetString(L, 2);
|
||||
wiRenderer::LoadWorldInfo(dir, name);
|
||||
string fileName = wiLua::SGetString(L, 1);
|
||||
wiRenderer::LoadWorldInfo(fileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
wiLua::SError(L, "LoadWorldInfo(string directory, string name) not enough arguments!");
|
||||
wiLua::SError(L, "LoadWorldInfo(string fileName) not enough arguments!");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -261,6 +261,8 @@ bool wiResourceManager::del(const wiHashString& name, bool forceDelete)
|
||||
if(res->data)
|
||||
switch(res->type){
|
||||
case Data_Type::IMAGE:
|
||||
SAFE_DELETE(reinterpret_cast<Texture2D*&>(res->data));
|
||||
break;
|
||||
case Data_Type::VERTEXSHADER:
|
||||
SAFE_DELETE(reinterpret_cast<VertexShaderInfo*&>(res->data));
|
||||
break;
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace wiVersion
|
||||
// minor features, major updates
|
||||
const int minor = 14;
|
||||
// minor bug fixes, alterations, refactors, updates
|
||||
const int revision = 17;
|
||||
const int revision = 18;
|
||||
|
||||
|
||||
long GetVersion()
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
LUA 5.3.3:
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright © 1994–2015 Lua.org, PUC - Rio.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
||||
files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
||||
@@ -19,6 +21,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SO
|
||||
|
||||
BULLET 2.82:
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Bullet Collision Detection and Physics Library
|
||||
Copyright (c) 2012 Advanced Micro Devices, Inc. http://bulletphysics.org
|
||||
|
||||
@@ -35,3 +39,77 @@ this software in a product, an acknowledgment in the product documentation would
|
||||
|
||||
###############################################################################################################################
|
||||
|
||||
Rectpack2D
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2016 Team Hypersomnia
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
###############################################################################################################################
|
||||
|
||||
Forsyth vertex cache optimizer
|
||||
|
||||
Copyright (C) 2008 Martin Storsjo
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
###############################################################################################################################
|
||||
|
||||
Tinyobjloader
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2012-2017 Syoyo Fujita and many contributors.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
###############################################################################################################################
|
||||
|
||||
|
||||
Reference in New Issue
Block a user