From 381d4163d4afa99722946668e9f334698835904d Mon Sep 17 00:00:00 2001 From: turanszkij Date: Tue, 4 Sep 2018 18:05:23 +0100 Subject: [PATCH] updates --- Editor/MeshWindow.cpp | 288 +++++---- Editor/ModelImporter_GLTF.cpp | 1064 +++++++++++++++----------------- Editor/ObjectWindow.cpp | 543 ++++++++-------- WickedEngine/wiRenderer.cpp | 259 ++++---- WickedEngine/wiSceneSystem.cpp | 205 ++++++ WickedEngine/wiSceneSystem.h | 10 +- 6 files changed, 1274 insertions(+), 1095 deletions(-) diff --git a/Editor/MeshWindow.cpp b/Editor/MeshWindow.cpp index 5b9c3f4a6..06418b427 100644 --- a/Editor/MeshWindow.cpp +++ b/Editor/MeshWindow.cpp @@ -31,128 +31,138 @@ MeshWindow::MeshWindow(wiGUI* gui) : GUI(gui) y += 160; - //doubleSidedCheckBox = new wiCheckBox("Double Sided: "); - //doubleSidedCheckBox->SetTooltip("If enabled, the inside of the mesh will be visible."); - //doubleSidedCheckBox->SetPos(XMFLOAT2(x, y += step)); - //doubleSidedCheckBox->OnClick([&](wiEventArgs args) { - // if (mesh != nullptr) - // { - // mesh->doubleSided = args.bValue; - // } - //}); - //meshWindow->AddWidget(doubleSidedCheckBox); + doubleSidedCheckBox = new wiCheckBox("Double Sided: "); + doubleSidedCheckBox->SetTooltip("If enabled, the inside of the mesh will be visible."); + doubleSidedCheckBox->SetPos(XMFLOAT2(x, y += step)); + doubleSidedCheckBox->OnClick([&](wiEventArgs args) { + MeshComponent* mesh = wiRenderer::GetScene().meshes.GetComponent(entity); + if (mesh != nullptr) + { + mesh->doubleSided = args.bValue; + } + }); + meshWindow->AddWidget(doubleSidedCheckBox); - //massSlider = new wiSlider(0, 5000, 0, 100000, "Mass: "); - //massSlider->SetTooltip("Set the mass amount for the physics engine."); - //massSlider->SetSize(XMFLOAT2(100, 30)); - //massSlider->SetPos(XMFLOAT2(x, y += step)); - //massSlider->OnSlide([&](wiEventArgs args) { - // if (mesh != nullptr) - // { - // mesh->mass = args.fValue; - // } - //}); - //meshWindow->AddWidget(massSlider); + massSlider = new wiSlider(0, 5000, 0, 100000, "Mass: "); + massSlider->SetTooltip("Set the mass amount for the physics engine."); + massSlider->SetSize(XMFLOAT2(100, 30)); + massSlider->SetPos(XMFLOAT2(x, y += step)); + massSlider->OnSlide([&](wiEventArgs args) { + PhysicsComponent* physicscomponent = wiRenderer::GetScene().physicscomponents.GetComponent(entity); + if (physicscomponent != nullptr) + { + physicscomponent->mass = args.fValue; + } + }); + meshWindow->AddWidget(massSlider); - //frictionSlider = new wiSlider(0, 5000, 0, 100000, "Friction: "); - //frictionSlider->SetTooltip("Set the friction amount for the physics engine."); - //frictionSlider->SetSize(XMFLOAT2(100, 30)); - //frictionSlider->SetPos(XMFLOAT2(x, y += step)); - //frictionSlider->OnSlide([&](wiEventArgs args) { - // if (mesh != nullptr) - // { - // mesh->friction = args.fValue; - // } - //}); - //meshWindow->AddWidget(frictionSlider); + frictionSlider = new wiSlider(0, 5000, 0, 100000, "Friction: "); + frictionSlider->SetTooltip("Set the friction amount for the physics engine."); + frictionSlider->SetSize(XMFLOAT2(100, 30)); + frictionSlider->SetPos(XMFLOAT2(x, y += step)); + frictionSlider->OnSlide([&](wiEventArgs args) { + PhysicsComponent* physicscomponent = wiRenderer::GetScene().physicscomponents.GetComponent(entity); + if (physicscomponent != nullptr) + { + physicscomponent->friction = args.fValue; + } + }); + meshWindow->AddWidget(frictionSlider); - //impostorCreateButton = new wiButton("Create Impostor"); - //impostorCreateButton->SetTooltip("Create an impostor image of the mesh. The mesh will be replaced by this image when far away, to render faster."); - //impostorCreateButton->SetSize(XMFLOAT2(240, 30)); - //impostorCreateButton->SetPos(XMFLOAT2(x - 50, y += step)); - //impostorCreateButton->OnClick([&](wiEventArgs args) { - // if (mesh != nullptr) - // { - // wiRenderer::CreateImpostor(mesh, GRAPHICSTHREAD_IMMEDIATE); - // } - //}); - //meshWindow->AddWidget(impostorCreateButton); + impostorCreateButton = new wiButton("Create Impostor"); + impostorCreateButton->SetTooltip("Create an impostor image of the mesh. The mesh will be replaced by this image when far away, to render faster."); + impostorCreateButton->SetSize(XMFLOAT2(240, 30)); + impostorCreateButton->SetPos(XMFLOAT2(x - 50, y += step)); + impostorCreateButton->OnClick([&](wiEventArgs args) { + MeshComponent* mesh = wiRenderer::GetScene().meshes.GetComponent(entity); + if (mesh != nullptr) + { + wiRenderer::CreateImpostor(entity, GRAPHICSTHREAD_IMMEDIATE); + } + }); + meshWindow->AddWidget(impostorCreateButton); - //impostorDistanceSlider = new wiSlider(0, 1000, 100, 10000, "Impostor Distance: "); - //impostorDistanceSlider->SetTooltip("Assign the distance where the mesh geometry should be switched to the impostor image."); - //impostorDistanceSlider->SetSize(XMFLOAT2(100, 30)); - //impostorDistanceSlider->SetPos(XMFLOAT2(x, y += step)); - //impostorDistanceSlider->OnSlide([&](wiEventArgs args) { - // if (mesh != nullptr) - // { - // mesh->impostorDistance = args.fValue; - // } - //}); - //meshWindow->AddWidget(impostorDistanceSlider); + impostorDistanceSlider = new wiSlider(0, 1000, 100, 10000, "Impostor Distance: "); + impostorDistanceSlider->SetTooltip("Assign the distance where the mesh geometry should be switched to the impostor image."); + impostorDistanceSlider->SetSize(XMFLOAT2(100, 30)); + impostorDistanceSlider->SetPos(XMFLOAT2(x, y += step)); + impostorDistanceSlider->OnSlide([&](wiEventArgs args) { + MeshComponent* mesh = wiRenderer::GetScene().meshes.GetComponent(entity); + if (mesh != nullptr) + { + mesh->impostorDistance = args.fValue; + } + }); + meshWindow->AddWidget(impostorDistanceSlider); - //tessellationFactorSlider = new wiSlider(0, 16, 0, 10000, "Tessellation Factor: "); - //tessellationFactorSlider->SetTooltip("Set the dynamic tessellation amount. Tessellation should be enabled in the Renderer window and your GPU must support it!"); - //tessellationFactorSlider->SetSize(XMFLOAT2(100, 30)); - //tessellationFactorSlider->SetPos(XMFLOAT2(x, y += step)); - //tessellationFactorSlider->OnSlide([&](wiEventArgs args) { - // if (mesh != nullptr) - // { - // mesh->tessellationFactor = args.fValue; - // } - //}); - //meshWindow->AddWidget(tessellationFactorSlider); + tessellationFactorSlider = new wiSlider(0, 16, 0, 10000, "Tessellation Factor: "); + tessellationFactorSlider->SetTooltip("Set the dynamic tessellation amount. Tessellation should be enabled in the Renderer window and your GPU must support it!"); + tessellationFactorSlider->SetSize(XMFLOAT2(100, 30)); + tessellationFactorSlider->SetPos(XMFLOAT2(x, y += step)); + tessellationFactorSlider->OnSlide([&](wiEventArgs args) { + MeshComponent* mesh = wiRenderer::GetScene().meshes.GetComponent(entity); + if (mesh != nullptr) + { + mesh->tessellationFactor = args.fValue; + } + }); + meshWindow->AddWidget(tessellationFactorSlider); - //flipCullingButton = new wiButton("Flip Culling"); - //flipCullingButton->SetTooltip("Flip faces to reverse triangle culling order."); - //flipCullingButton->SetSize(XMFLOAT2(240, 30)); - //flipCullingButton->SetPos(XMFLOAT2(x - 50, y += step)); - //flipCullingButton->OnClick([&](wiEventArgs args) { - // if (mesh != nullptr) - // { - // mesh->FlipCulling(); - // SetMesh(mesh); - // } - //}); - //meshWindow->AddWidget(flipCullingButton); + flipCullingButton = new wiButton("Flip Culling"); + flipCullingButton->SetTooltip("Flip faces to reverse triangle culling order."); + flipCullingButton->SetSize(XMFLOAT2(240, 30)); + flipCullingButton->SetPos(XMFLOAT2(x - 50, y += step)); + flipCullingButton->OnClick([&](wiEventArgs args) { + MeshComponent* mesh = wiRenderer::GetScene().meshes.GetComponent(entity); + if (mesh != nullptr) + { + mesh->FlipCulling(); + SetEntity(entity); + } + }); + meshWindow->AddWidget(flipCullingButton); - //flipNormalsButton = new wiButton("Flip Normals"); - //flipNormalsButton->SetTooltip("Flip surface normals."); - //flipNormalsButton->SetSize(XMFLOAT2(240, 30)); - //flipNormalsButton->SetPos(XMFLOAT2(x - 50, y += step)); - //flipNormalsButton->OnClick([&](wiEventArgs args) { - // if (mesh != nullptr) - // { - // mesh->FlipNormals(); - // SetMesh(mesh); - // } - //}); - //meshWindow->AddWidget(flipNormalsButton); + flipNormalsButton = new wiButton("Flip Normals"); + flipNormalsButton->SetTooltip("Flip surface normals."); + flipNormalsButton->SetSize(XMFLOAT2(240, 30)); + flipNormalsButton->SetPos(XMFLOAT2(x - 50, y += step)); + flipNormalsButton->OnClick([&](wiEventArgs args) { + MeshComponent* mesh = wiRenderer::GetScene().meshes.GetComponent(entity); + if (mesh != nullptr) + { + mesh->FlipNormals(); + SetEntity(entity); + } + }); + meshWindow->AddWidget(flipNormalsButton); - //computeNormalsSmoothButton = new wiButton("Compute Normals [SMOOTH]"); - //computeNormalsSmoothButton->SetTooltip("Compute surface normals of the mesh. Resulting normals will be unique per vertex."); - //computeNormalsSmoothButton->SetSize(XMFLOAT2(240, 30)); - //computeNormalsSmoothButton->SetPos(XMFLOAT2(x - 50, y += step)); - //computeNormalsSmoothButton->OnClick([&](wiEventArgs args) { - // if (mesh != nullptr) - // { - // mesh->ComputeNormals(true); - // SetMesh(mesh); - // } - //}); - //meshWindow->AddWidget(computeNormalsSmoothButton); + computeNormalsSmoothButton = new wiButton("Compute Normals [SMOOTH]"); + computeNormalsSmoothButton->SetTooltip("Compute surface normals of the mesh. Resulting normals will be unique per vertex."); + computeNormalsSmoothButton->SetSize(XMFLOAT2(240, 30)); + computeNormalsSmoothButton->SetPos(XMFLOAT2(x - 50, y += step)); + computeNormalsSmoothButton->OnClick([&](wiEventArgs args) { + MeshComponent* mesh = wiRenderer::GetScene().meshes.GetComponent(entity); + if (mesh != nullptr) + { + mesh->ComputeNormals(true); + SetEntity(entity); + } + }); + meshWindow->AddWidget(computeNormalsSmoothButton); - //computeNormalsHardButton = new wiButton("Compute Normals [HARD]"); - //computeNormalsHardButton->SetTooltip("Compute surface normals of the mesh. Resulting normals will be unique per face."); - //computeNormalsHardButton->SetSize(XMFLOAT2(240, 30)); - //computeNormalsHardButton->SetPos(XMFLOAT2(x - 50, y += step)); - //computeNormalsHardButton->OnClick([&](wiEventArgs args) { - // if (mesh != nullptr) - // { - // mesh->ComputeNormals(false); - // SetMesh(mesh); - // } - //}); - //meshWindow->AddWidget(computeNormalsHardButton); + computeNormalsHardButton = new wiButton("Compute Normals [HARD]"); + computeNormalsHardButton->SetTooltip("Compute surface normals of the mesh. Resulting normals will be unique per face."); + computeNormalsHardButton->SetSize(XMFLOAT2(240, 30)); + computeNormalsHardButton->SetPos(XMFLOAT2(x - 50, y += step)); + computeNormalsHardButton->OnClick([&](wiEventArgs args) { + MeshComponent* mesh = wiRenderer::GetScene().meshes.GetComponent(entity); + if (mesh != nullptr) + { + mesh->ComputeNormals(false); + SetEntity(entity); + } + }); + meshWindow->AddWidget(computeNormalsHardButton); @@ -175,26 +185,36 @@ void MeshWindow::SetEntity(Entity entity) { this->entity = entity; - //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()); + Scene&scene = wiRenderer::GetScene(); - // doubleSidedCheckBox->SetCheck(mesh->doubleSided); - // massSlider->SetValue(mesh->mass); - // frictionSlider->SetValue(mesh->friction); - // impostorDistanceSlider->SetValue(mesh->impostorDistance); - // tessellationFactorSlider->SetValue(mesh->getTessellationFactor()); - // meshWindow->SetEnabled(true); - //} - //else - //{ - // meshInfoLabel->SetText("Select a mesh..."); - // meshWindow->SetEnabled(false); - //} + const MeshComponent* mesh = scene.meshes.GetComponent(entity); + + if (mesh != nullptr) + { + const NameComponent& name = *scene.names.GetComponent(entity); + + stringstream ss(""); + ss << "Mesh name: " << name.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); + impostorDistanceSlider->SetValue(mesh->impostorDistance); + tessellationFactorSlider->SetValue(mesh->GetTessellationFactor()); + + const PhysicsComponent* physicscomponent = scene.physicscomponents.GetComponent(entity); + if (physicscomponent != nullptr) + { + massSlider->SetValue(physicscomponent->mass); + frictionSlider->SetValue(physicscomponent->friction); + } + meshWindow->SetEnabled(true); + } + else + { + meshInfoLabel->SetText("Select a mesh..."); + meshWindow->SetEnabled(false); + } } diff --git a/Editor/ModelImporter_GLTF.cpp b/Editor/ModelImporter_GLTF.cpp index 66b650438..596c508d6 100644 --- a/Editor/ModelImporter_GLTF.cpp +++ b/Editor/ModelImporter_GLTF.cpp @@ -32,12 +32,6 @@ namespace tinygltf const int requiredComponents = 4; int w, h, comp; - // if image cannot be decoded, ignore parsing and keep it by its path - // don't break in this case - // FIXME we should only enter this function if the image is embedded. If - // image->uri references - // an image file, it should be left as it is. Image loading should not be - // mandatory (to support other formats) unsigned char *data = stbi_load_from_memory(bytes, size, &w, &h, &comp, requiredComponents); if (!data) { // NOTE: you can use `warn` instead of `err` @@ -77,7 +71,6 @@ namespace tinygltf image->width = w; image->height = h; - //image->component = comp; image->component = requiredComponents; image->image.resize(static_cast(w * h * image->component)); std::copy(data, data + w * h * image->component, image->image.begin()); @@ -85,76 +78,6 @@ namespace tinygltf free(data); return true; - - - //if (!image->uri.empty()) - //{ - // // external image will be loaded by resource manager - // return true; - //} - //else - //{ - // // embedded image - - // // We will load the texture2d by hand here and register to the resource manager - // { - // // png, tga, jpg, etc. loader: - - // const int channelCount = 4; - // int width, height, bpp; - // unsigned char* rgb = stbi_load_from_memory(bytes, size, &width, &height, &bpp, channelCount); - - // if (rgb != nullptr) - // { - // TextureDesc desc; - // desc.ArraySize = 1; - // desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; - // desc.CPUAccessFlags = 0; - // desc.Format = FORMAT_R8G8B8A8_UNORM; - // desc.Height = static_cast(height); - // desc.Width = static_cast(width); - // desc.MipLevels = (UINT)log2(max(width, height)); - // desc.MiscFlags = 0; - // desc.Usage = USAGE_DEFAULT; - - // UINT mipwidth = width; - // SubresourceData* InitData = new SubresourceData[desc.MipLevels]; - // for (UINT mip = 0; mip < desc.MipLevels; ++mip) - // { - // InitData[mip].pSysMem = rgb; - // InitData[mip].SysMemPitch = static_cast(mipwidth * channelCount); - // mipwidth = max(1, mipwidth / 2); - // } - - // Texture2D* tex = new Texture2D; - // tex->RequestIndependentShaderResourcesForMIPs(true); - // tex->RequestIndependentUnorderedAccessResourcesForMIPs(true); - // HRESULT hr = wiRenderer::GetDevice()->CreateTexture2D(&desc, InitData, &tex); - // assert(SUCCEEDED(hr)); - - // if (tex != nullptr) - // { - // wiRenderer::AddDeferredMIPGen(tex); - - // if (image->name.empty()) - // { - // static UINT imgcounter = 0; - // stringstream ss(""); - // ss << "gltfLoader_embedded_image" << imgcounter++; - // image->name = ss.str(); - // } - // // We loaded the texture2d, so register to the resource manager to be retrieved later: - // wiResourceManager::GetGlobal()->Register(image->name, tex, wiResourceManager::IMAGE); - // } - // } - - // free(rgb); - // } - - // return true; - //} - - //return false; } bool WriteImageData(const std::string *basepath, const std::string *filename, @@ -221,301 +144,299 @@ void RegisterTexture2D(tinygltf::Image *image) } } -//void LoadNode(tinygltf::Node* node, tinygltf::Node* parent, Model* model, tinygltf::Model& gltfModel, vector& meshArray, vector& armatureArray) -//{ -// if (node == nullptr) -// { -// return; -// } -// -// Transform transform; -// if (!node->scale.empty()) -// { -// transform.scale_rest = XMFLOAT3((float)node->scale[0], (float)node->scale[1], (float)node->scale[2]); -// } -// if (!node->rotation.empty()) -// { -// transform.rotation_rest = XMFLOAT4((float)node->rotation[0], (float)node->rotation[1], (float)node->rotation[2], (float)node->rotation[3]); -// } -// if (!node->translation.empty()) -// { -// transform.translation_rest = XMFLOAT3((float)node->translation[0], (float)node->translation[1], (float)node->translation[2]); -// } -// transform.UpdateTransform(); -// -// if (parent != nullptr) -// { -// transform.parentName = parent->name; -// } -// -// if(node->mesh >= 0) -// { -// Object* object = new Object(node->name); -// model->objects.insert(object); -// -// *(Transform*)object = transform; -// -// if (node->mesh < meshArray.size()) -// { -// object->mesh = meshArray[node->mesh]; -// object->meshName = object->mesh->name; -// } -// else -// { -// auto& x = gltfModel.meshes[node->mesh]; -// Mesh* mesh = new Mesh(x.name); -// meshArray.push_back(mesh); -// -// object->mesh = mesh; -// object->meshName = mesh->name; -// -// mesh->renderable = true; -// -// XMFLOAT3 min = XMFLOAT3(FLT_MAX, FLT_MAX, FLT_MAX); -// XMFLOAT3 max = XMFLOAT3(-FLT_MAX, -FLT_MAX, -FLT_MAX); -// -// for (auto& prim : x.primitives) -// { -// assert(prim.indices >= 0); -// -// // Fill indices: -// const tinygltf::Accessor& accessor = gltfModel.accessors[prim.indices]; -// const tinygltf::BufferView& bufferView = gltfModel.bufferViews[accessor.bufferView]; -// const tinygltf::Buffer& buffer = gltfModel.buffers[bufferView.buffer]; -// -// int stride = accessor.ByteStride(bufferView); -// size_t count = accessor.count; -// -// size_t offset = mesh->indices.size(); -// mesh->indices.resize(offset + count); -// -// const unsigned char* data = buffer.data.data() + accessor.byteOffset + bufferView.byteOffset; -// -// if (stride == 1) -// { -// for (size_t i = 0; i < count; i += 3) -// { -// mesh->indices[offset + i + 0] = data[i + 0]; -// mesh->indices[offset + i + 1] = data[i + 1]; -// mesh->indices[offset + i + 2] = data[i + 2]; -// } -// } -// else if (stride == 2) -// { -// for (size_t i = 0; i < count; i += 3) -// { -// mesh->indices[offset + i + 0] = ((uint16_t*)data)[i + 0]; -// mesh->indices[offset + i + 1] = ((uint16_t*)data)[i + 1]; -// mesh->indices[offset + i + 2] = ((uint16_t*)data)[i + 2]; -// } -// } -// else if (stride == 4) -// { -// for (size_t i = 0; i < count; i += 3) -// { -// mesh->indices[offset + i + 0] = ((uint32_t*)data)[i + 0]; -// mesh->indices[offset + i + 1] = ((uint32_t*)data)[i + 1]; -// mesh->indices[offset + i + 2] = ((uint32_t*)data)[i + 2]; -// } -// } -// else -// { -// assert(0 && "unsupported index stride!"); -// } -// -// -// // Create mesh subset: -// MeshSubset subset; -// -// if (prim.material >= 0) -// { -// const string& mat_name = gltfModel.materials[prim.material].name; -// auto& found_mat = model->materials.find(mat_name); -// if (found_mat != model->materials.end()) -// { -// subset.material = found_mat->second; -// } -// } -// -// if (subset.material == nullptr) -// { -// subset.material = new Material("gltfLoader_defaultMat"); -// } -// -// mesh->subsets.push_back(subset); -// mesh->materialNames.push_back(subset.material->name); -// } -// -// bool hasBoneWeights = false; -// bool hasBoneIndices = false; -// -// int matIndex = -1; -// for (auto& prim : x.primitives) -// { -// matIndex++; -// size_t offset = mesh->vertices_FULL.size(); -// -// for (auto& attr : prim.attributes) -// { -// const string& attr_name = attr.first; -// int attr_data = attr.second; -// -// const tinygltf::Accessor& accessor = gltfModel.accessors[attr_data]; -// const tinygltf::BufferView& bufferView = gltfModel.bufferViews[accessor.bufferView]; -// const tinygltf::Buffer& buffer = gltfModel.buffers[bufferView.buffer]; -// -// int stride = accessor.ByteStride(bufferView); -// size_t count = accessor.count; -// -// if (mesh->vertices_FULL.size() == offset) -// { -// mesh->vertices_FULL.resize(offset + count); -// } -// -// const unsigned char* data = buffer.data.data() + accessor.byteOffset + bufferView.byteOffset; -// -// if (!attr_name.compare("POSITION")) -// { -// assert(stride == 12); -// for (size_t i = 0; i < count; ++i) -// { -// XMFLOAT3 pos = ((XMFLOAT3*)data)[i]; -// -// if (transform_to_LH) -// { -// pos.z = -pos.z; -// } -// -// mesh->vertices_FULL[offset + i].pos = XMFLOAT4(pos.x, pos.y, pos.z, 0); -// -// min = wiMath::Min(min, pos); -// max = wiMath::Max(max, pos); -// } -// } -// else if (!attr_name.compare("NORMAL")) -// { -// assert(stride == 12); -// for (size_t i = 0; i < count; ++i) -// { -// const XMFLOAT3& nor = ((XMFLOAT3*)data)[i]; -// -// mesh->vertices_FULL[offset + i].nor.x = nor.x; -// mesh->vertices_FULL[offset + i].nor.y = nor.y; -// mesh->vertices_FULL[offset + i].nor.z = -nor.z; -// } -// } -// else if (!attr_name.compare("TEXCOORD_0")) -// { -// assert(stride == 8); -// for (size_t i = 0; i < count; ++i) -// { -// const XMFLOAT2& tex = ((XMFLOAT2*)data)[i]; -// -// mesh->vertices_FULL[offset + i].tex.x = tex.x; -// mesh->vertices_FULL[offset + i].tex.y = tex.y; -// mesh->vertices_FULL[offset + i].tex.z = (float)matIndex /*prim.material*/; -// } -// } -// else if (!attr_name.compare("JOINTS_0")) -// { -// if (stride == 4) -// { -// hasBoneIndices = true; -// struct JointTmp -// { -// uint8_t ind[4]; -// }; -// -// for (size_t i = 0; i < count; ++i) -// { -// const JointTmp& joint = ((JointTmp*)data)[i]; -// -// mesh->vertices_FULL[offset + i].ind.x = (float)joint.ind[0]; -// mesh->vertices_FULL[offset + i].ind.y = (float)joint.ind[1]; -// mesh->vertices_FULL[offset + i].ind.z = (float)joint.ind[2]; -// mesh->vertices_FULL[offset + i].ind.w = (float)joint.ind[3]; -// } -// } -// else if (stride == 8) -// { -// hasBoneIndices = true; -// struct JointTmp -// { -// uint16_t ind[4]; -// }; -// -// for (size_t i = 0; i < count; ++i) -// { -// const JointTmp& joint = ((JointTmp*)data)[i]; -// -// mesh->vertices_FULL[offset + i].ind.x = (float)joint.ind[0]; -// mesh->vertices_FULL[offset + i].ind.y = (float)joint.ind[1]; -// mesh->vertices_FULL[offset + i].ind.z = (float)joint.ind[2]; -// mesh->vertices_FULL[offset + i].ind.w = (float)joint.ind[3]; -// } -// } -// else -// { -// assert(0); -// } -// } -// else if (!attr_name.compare("WEIGHTS_0")) -// { -// hasBoneWeights = true; -// assert(stride == 16); -// for (size_t i = 0; i < count; ++i) -// { -// mesh->vertices_FULL[offset + i].wei = ((XMFLOAT4*)data)[i]; -// } -// } -// -// } -// -// } -// -// mesh->aabb.create(min, max); -// -// model->meshes.insert(make_pair(mesh->name, mesh)); -// -// -// if (!armatureArray.empty() && hasBoneIndices && hasBoneWeights) -// { -// mesh->armature = armatureArray[0]; // How to resolve? -// mesh->armatureName = mesh->armature->name; -// } -// -// } -// } -// -// if (node->camera >= 0) -// { -// Camera* camera = new Camera; -// camera->SetUp((float)wiRenderer::GetInternalResolution().x, (float)wiRenderer::GetInternalResolution().y, 0.1f, 800); -// model->cameras.push_back(camera); -// -// *(Transform*)camera = transform; -// -// camera->name = gltfModel.cameras[node->camera].name; -// if (camera->name.empty()) -// { -// static int camID = 0; -// stringstream ss(""); -// ss << "cam" << camID++; -// camera->name = ss.str(); -// } -// node->name = camera->name; -// -// camera->UpdateProps(); -// } -// -// if (!node->children.empty()) -// { -// for (int child : node->children) -// { -// LoadNode(&gltfModel.nodes[child], node, model, gltfModel, meshArray, armatureArray); -// } -// } -//} +void LoadNode(tinygltf::Node* node, Entity parent, Entity modelEntity, tinygltf::Model& gltfModel, const vector& materialArray, vector& meshArray, vector& armatureArray) +{ + if (node == nullptr) + { + return; + } + + Scene& scene = wiRenderer::GetScene(); + + ModelComponent& model = *scene.models.GetComponent(modelEntity); + + Entity entity = INVALID_ENTITY; + + if(node->mesh >= 0) + { + entity = scene.Entity_CreateObject(node->name); + ObjectComponent& object = *scene.objects.GetComponent(entity); + + if (node->mesh < meshArray.size()) + { + object.meshID = meshArray[node->mesh]; + } + else + { + auto& x = gltfModel.meshes[node->mesh]; + Entity meshEntity = scene.Entity_CreateMesh(x.name); + meshArray.push_back(meshEntity); + + object.meshID = meshEntity; + + MeshComponent& mesh = *scene.meshes.GetComponent(meshEntity); + + mesh.renderable = true; + + XMFLOAT3 min = XMFLOAT3(FLT_MAX, FLT_MAX, FLT_MAX); + XMFLOAT3 max = XMFLOAT3(-FLT_MAX, -FLT_MAX, -FLT_MAX); + + for (auto& prim : x.primitives) + { + assert(prim.indices >= 0); + + // Fill indices: + const tinygltf::Accessor& accessor = gltfModel.accessors[prim.indices]; + const tinygltf::BufferView& bufferView = gltfModel.bufferViews[accessor.bufferView]; + const tinygltf::Buffer& buffer = gltfModel.buffers[bufferView.buffer]; + + int stride = accessor.ByteStride(bufferView); + size_t count = accessor.count; + + size_t offset = mesh.indices.size(); + mesh.indices.resize(offset + count); + + const unsigned char* data = buffer.data.data() + accessor.byteOffset + bufferView.byteOffset; + + if (stride == 1) + { + for (size_t i = 0; i < count; i += 3) + { + mesh.indices[offset + i + 0] = data[i + 0]; + mesh.indices[offset + i + 1] = data[i + 1]; + mesh.indices[offset + i + 2] = data[i + 2]; + } + } + else if (stride == 2) + { + for (size_t i = 0; i < count; i += 3) + { + mesh.indices[offset + i + 0] = ((uint16_t*)data)[i + 0]; + mesh.indices[offset + i + 1] = ((uint16_t*)data)[i + 1]; + mesh.indices[offset + i + 2] = ((uint16_t*)data)[i + 2]; + } + } + else if (stride == 4) + { + for (size_t i = 0; i < count; i += 3) + { + mesh.indices[offset + i + 0] = ((uint32_t*)data)[i + 0]; + mesh.indices[offset + i + 1] = ((uint32_t*)data)[i + 1]; + mesh.indices[offset + i + 2] = ((uint32_t*)data)[i + 2]; + } + } + else + { + assert(0 && "unsupported index stride!"); + } + + + // Create mesh subset: + MeshComponent::MeshSubset subset; + + if (prim.material >= 0) + { + subset.materialID = materialArray[prim.material]; + } + else + { + assert(0); + } + + mesh.subsets.push_back(subset); + } + + bool hasBoneWeights = false; + bool hasBoneIndices = false; + + int matIndex = -1; + for (auto& prim : x.primitives) + { + matIndex++; + size_t offset = mesh.vertices_FULL.size(); + + for (auto& attr : prim.attributes) + { + const string& attr_name = attr.first; + int attr_data = attr.second; + + const tinygltf::Accessor& accessor = gltfModel.accessors[attr_data]; + const tinygltf::BufferView& bufferView = gltfModel.bufferViews[accessor.bufferView]; + const tinygltf::Buffer& buffer = gltfModel.buffers[bufferView.buffer]; + + int stride = accessor.ByteStride(bufferView); + size_t count = accessor.count; + + if (mesh.vertices_FULL.size() == offset) + { + mesh.vertices_FULL.resize(offset + count); + } + + const unsigned char* data = buffer.data.data() + accessor.byteOffset + bufferView.byteOffset; + + if (!attr_name.compare("POSITION")) + { + assert(stride == 12); + for (size_t i = 0; i < count; ++i) + { + XMFLOAT3 pos = ((XMFLOAT3*)data)[i]; + + if (transform_to_LH) + { + pos.z = -pos.z; + } + + mesh.vertices_FULL[offset + i].pos = XMFLOAT4(pos.x, pos.y, pos.z, 0); + + min = wiMath::Min(min, pos); + max = wiMath::Max(max, pos); + } + } + else if (!attr_name.compare("NORMAL")) + { + assert(stride == 12); + for (size_t i = 0; i < count; ++i) + { + const XMFLOAT3& nor = ((XMFLOAT3*)data)[i]; + + mesh.vertices_FULL[offset + i].nor.x = nor.x; + mesh.vertices_FULL[offset + i].nor.y = nor.y; + mesh.vertices_FULL[offset + i].nor.z = -nor.z; + } + } + else if (!attr_name.compare("TEXCOORD_0")) + { + assert(stride == 8); + for (size_t i = 0; i < count; ++i) + { + const XMFLOAT2& tex = ((XMFLOAT2*)data)[i]; + + mesh.vertices_FULL[offset + i].tex.x = tex.x; + mesh.vertices_FULL[offset + i].tex.y = tex.y; + mesh.vertices_FULL[offset + i].tex.z = (float)matIndex /*prim.material*/; + } + } + else if (!attr_name.compare("JOINTS_0")) + { + if (stride == 4) + { + hasBoneIndices = true; + struct JointTmp + { + uint8_t ind[4]; + }; + + for (size_t i = 0; i < count; ++i) + { + const JointTmp& joint = ((JointTmp*)data)[i]; + + mesh.vertices_FULL[offset + i].ind.x = (float)joint.ind[0]; + mesh.vertices_FULL[offset + i].ind.y = (float)joint.ind[1]; + mesh.vertices_FULL[offset + i].ind.z = (float)joint.ind[2]; + mesh.vertices_FULL[offset + i].ind.w = (float)joint.ind[3]; + } + } + else if (stride == 8) + { + hasBoneIndices = true; + struct JointTmp + { + uint16_t ind[4]; + }; + + for (size_t i = 0; i < count; ++i) + { + const JointTmp& joint = ((JointTmp*)data)[i]; + + mesh.vertices_FULL[offset + i].ind.x = (float)joint.ind[0]; + mesh.vertices_FULL[offset + i].ind.y = (float)joint.ind[1]; + mesh.vertices_FULL[offset + i].ind.z = (float)joint.ind[2]; + mesh.vertices_FULL[offset + i].ind.w = (float)joint.ind[3]; + } + } + else + { + assert(0); + } + } + else if (!attr_name.compare("WEIGHTS_0")) + { + hasBoneWeights = true; + assert(stride == 16); + for (size_t i = 0; i < count; ++i) + { + mesh.vertices_FULL[offset + i].wei = ((XMFLOAT4*)data)[i]; + } + } + + } + + } + + mesh.aabb.create(min, max); + mesh.CreateRenderData(); + + model.meshes.insert(meshEntity); + + + //if (!armatureArray.empty() && hasBoneIndices && hasBoneWeights) + //{ + // mesh->armature = armatureArray[0]; // How to resolve? + // mesh->armatureName = mesh->armature->name; + //} + + } + } + else if (node->camera >= 0) + { + if (node->name.empty()) + { + static int camID = 0; + stringstream ss(""); + ss << "cam" << camID++; + node->name = ss.str(); + } + + entity = scene.Entity_CreateCamera(node->name, (float)wiRenderer::GetInternalResolution().x, (float)wiRenderer::GetInternalResolution().y, 0.1f, 800); + model.cameras.insert(entity); + } + + if (entity == INVALID_ENTITY) + { + entity = CreateEntity(); + scene.transforms.Create(entity); + } + + + TransformComponent& transform = *scene.transforms.GetComponent(entity); + if (!node->scale.empty()) + { + transform.scale_local = XMFLOAT3((float)node->scale[0], (float)node->scale[1], (float)node->scale[2]); + } + if (!node->rotation.empty()) + { + transform.rotation_local = XMFLOAT4((float)node->rotation[0], (float)node->rotation[1], (float)node->rotation[2], (float)node->rotation[3]); + } + if (!node->translation.empty()) + { + transform.translation_local = XMFLOAT3((float)node->translation[0], (float)node->translation[1], (float)node->translation[2]); + } + transform.UpdateTransform(); + + + if (parent != INVALID_ENTITY) + { + scene.Component_Attach(entity, parent); + } + + if (!node->children.empty()) + { + for (int child : node->children) + { + LoadNode(&gltfModel.nodes[child], entity, modelEntity, gltfModel, materialArray, meshArray, armatureArray); + } + } +} Entity ImportModel_GLTF(const std::string& fileName) { @@ -547,231 +468,236 @@ Entity ImportModel_GLTF(const std::string& fileName) return INVALID_ENTITY; } + vector materialArray; + vector armatureArray; + vector meshArray; - return INVALID_ENTITY; + Scene& scene = wiRenderer::GetScene(); - //vector armatureArray; - //vector meshArray; + Entity modelEntity = scene.Entity_CreateModel(name); + ModelComponent& model = *scene.models.GetComponent(modelEntity); + TransformComponent& model_transform = *scene.transforms.GetComponent(modelEntity); - //Model* model = new Model; - //model->name = name; + model_transform.UpdateTransform(); // everything will be attached to this, so values need to be up to date - //for (auto& x : gltfModel.materials) - //{ - // Material* material = new Material(x.name); - // model->materials.insert(make_pair(material->name, material)); - // material->baseColor = XMFLOAT3(1, 1, 1); - // material->roughness = 1.0f; - // material->metalness = 1.0f; - // material->reflectance = 0.02f; - // material->emissive = 0; + for (auto& x : gltfModel.materials) + { + Entity materialEntity = scene.Entity_CreateMaterial(x.name); + materialArray.push_back(materialEntity); + MaterialComponent& material = *scene.materials.GetComponent(materialEntity); - // auto& baseColorTexture = x.values.find("baseColorTexture"); - // auto& metallicRoughnessTexture = x.values.find("metallicRoughnessTexture"); - // auto& normalTexture = x.additionalValues.find("normalTexture"); - // auto& emissiveTexture = x.additionalValues.find("emissiveTexture"); - // auto& occlusionTexture = x.additionalValues.find("occlusionTexture"); + material.baseColor = XMFLOAT4(1, 1, 1, 1); + material.roughness = 1.0f; + material.metalness = 1.0f; + material.reflectance = 0.02f; + material.emissive = 0; - // auto& baseColorFactor = x.values.find("baseColorFactor"); - // auto& roughnessFactor = x.values.find("roughnessFactor"); - // auto& metallicFactor = x.values.find("metallicFactor"); - // auto& emissiveFactor = x.additionalValues.find("emissiveFactor"); - // auto& alphaCutoff = x.additionalValues.find("alphaCutoff"); + auto& baseColorTexture = x.values.find("baseColorTexture"); + auto& metallicRoughnessTexture = x.values.find("metallicRoughnessTexture"); + auto& normalTexture = x.additionalValues.find("normalTexture"); + auto& emissiveTexture = x.additionalValues.find("emissiveTexture"); + auto& occlusionTexture = x.additionalValues.find("occlusionTexture"); - // if (baseColorTexture != x.values.end()) - // { - // auto& tex = gltfModel.textures[baseColorTexture->second.TextureIndex()]; - // auto& img = gltfModel.images[tex.source]; - // RegisterTexture2D(&img); - // material->textureName = img.name; - // } - // else if(!gltfModel.images.empty()) - // { - // // For some reason, we don't have diffuse texture, but have other textures - // // I have a problem, because one model viewer displays textures on a model which has no basecolor set in its material... - // // This is probably not how it should be (todo) - // RegisterTexture2D(&gltfModel.images[0]); - // material->textureName = gltfModel.images[0].name; - // } + auto& baseColorFactor = x.values.find("baseColorFactor"); + auto& roughnessFactor = x.values.find("roughnessFactor"); + auto& metallicFactor = x.values.find("metallicFactor"); + auto& emissiveFactor = x.additionalValues.find("emissiveFactor"); + auto& alphaCutoff = x.additionalValues.find("alphaCutoff"); - // tinygltf::Image* img_nor = nullptr; - // tinygltf::Image* img_met_rough = nullptr; - // tinygltf::Image* img_emissive = nullptr; + if (baseColorTexture != x.values.end()) + { + auto& tex = gltfModel.textures[baseColorTexture->second.TextureIndex()]; + auto& img = gltfModel.images[tex.source]; + RegisterTexture2D(&img); + material.baseColorMapName = img.name; + } + else if(!gltfModel.images.empty()) + { + // For some reason, we don't have diffuse texture, but have other textures + // I have a problem, because one model viewer displays textures on a model which has no basecolor set in its material... + // This is probably not how it should be (todo) + RegisterTexture2D(&gltfModel.images[0]); + material.baseColorMapName = gltfModel.images[0].name; + } - // if (normalTexture != x.additionalValues.end()) - // { - // auto& tex = gltfModel.textures[normalTexture->second.TextureIndex()]; - // img_nor = &gltfModel.images[tex.source]; - // } - // if (metallicRoughnessTexture != x.values.end()) - // { - // auto& tex = gltfModel.textures[metallicRoughnessTexture->second.TextureIndex()]; - // img_met_rough = &gltfModel.images[tex.source]; - // } - // if (emissiveTexture != x.additionalValues.end()) - // { - // auto& tex = gltfModel.textures[emissiveTexture->second.TextureIndex()]; - // img_emissive = &gltfModel.images[tex.source]; - // } + tinygltf::Image* img_nor = nullptr; + tinygltf::Image* img_met_rough = nullptr; + tinygltf::Image* img_emissive = nullptr; - // // Now we will begin interleaving texture data to match engine layout: + if (normalTexture != x.additionalValues.end()) + { + auto& tex = gltfModel.textures[normalTexture->second.TextureIndex()]; + img_nor = &gltfModel.images[tex.source]; + } + if (metallicRoughnessTexture != x.values.end()) + { + auto& tex = gltfModel.textures[metallicRoughnessTexture->second.TextureIndex()]; + img_met_rough = &gltfModel.images[tex.source]; + } + if (emissiveTexture != x.additionalValues.end()) + { + auto& tex = gltfModel.textures[emissiveTexture->second.TextureIndex()]; + img_emissive = &gltfModel.images[tex.source]; + } - // if (img_nor != nullptr) - // { - // uint32_t* data32_roughness = nullptr; - // if (img_met_rough != nullptr && img_met_rough->width == img_nor->width && img_met_rough->height == img_nor->height) - // { - // data32_roughness = (uint32_t*)img_met_rough->image.data(); - // } - // else if (img_met_rough != nullptr) - // { - // wiBackLog::post("[gltf] Warning: there is a normalmap and roughness texture, but not the same size! Roughness will not be baked in!"); - // } + // Now we will begin interleaving texture data to match engine layout: - // // Convert normal map: - // uint32_t* data32 = (uint32_t*)img_nor->image.data(); - // for (int i = 0; i < img_nor->width * img_nor->height; ++i) - // { - // uint32_t pixel = data32[i]; - // float r = ((pixel >> 0) & 255) / 255.0f; - // float g = ((pixel >> 8) & 255) / 255.0f; - // float b = ((pixel >> 16) & 255) / 255.0f; - // float a = ((pixel >> 24) & 255) / 255.0f; + if (img_nor != nullptr) + { + uint32_t* data32_roughness = nullptr; + if (img_met_rough != nullptr && img_met_rough->width == img_nor->width && img_met_rough->height == img_nor->height) + { + data32_roughness = (uint32_t*)img_met_rough->image.data(); + } + else if (img_met_rough != nullptr) + { + wiBackLog::post("[gltf] Warning: there is a normalmap and roughness texture, but not the same size! Roughness will not be baked in!"); + } - // // swap normal y direction: - // g = 1 - g; + // Convert normal map: + uint32_t* data32 = (uint32_t*)img_nor->image.data(); + for (int i = 0; i < img_nor->width * img_nor->height; ++i) + { + uint32_t pixel = data32[i]; + float r = ((pixel >> 0) & 255) / 255.0f; + float g = ((pixel >> 8) & 255) / 255.0f; + float b = ((pixel >> 16) & 255) / 255.0f; + float a = ((pixel >> 24) & 255) / 255.0f; - // // reset roughness: - // a = 1; + // swap normal y direction: + g = 1 - g; - // if (data32_roughness != nullptr) - // { - // // add roughness from texture (G): - // a = ((data32_roughness[i] >> 8) & 255) / 255.0f; - // a = max(1.0f / 255.0f, a); // disallow 0 roughness (but is it really a good idea to do it here???) - // } + // reset roughness: + a = 1; - // uint32_t rgba8 = 0; - // rgba8 |= (uint32_t)(r * 255.0f) << 0; - // rgba8 |= (uint32_t)(g * 255.0f) << 8; - // rgba8 |= (uint32_t)(b * 255.0f) << 16; - // rgba8 |= (uint32_t)(a * 255.0f) << 24; + if (data32_roughness != nullptr) + { + // add roughness from texture (G): + a = ((data32_roughness[i] >> 8) & 255) / 255.0f; + a = max(1.0f / 255.0f, a); // disallow 0 roughness (but is it really a good idea to do it here???) + } - // data32[i] = rgba8; - // } + uint32_t rgba8 = 0; + rgba8 |= (uint32_t)(r * 255.0f) << 0; + rgba8 |= (uint32_t)(g * 255.0f) << 8; + rgba8 |= (uint32_t)(b * 255.0f) << 16; + rgba8 |= (uint32_t)(a * 255.0f) << 24; - // RegisterTexture2D(img_nor); - // material->normalMapName = img_nor->name; - // } + data32[i] = rgba8; + } - // if (img_met_rough != nullptr) - // { - // uint32_t* data32_emissive = nullptr; - // if (img_emissive != nullptr && img_emissive->width == img_met_rough->width && img_emissive->height == img_met_rough->height) - // { - // data32_emissive = (uint32_t*)img_emissive->image.data(); - // } + RegisterTexture2D(img_nor); + material.normalMapName = img_nor->name; + } - // uint32_t* data32 = (uint32_t*)img_met_rough->image.data(); - // for (int i = 0; i < img_met_rough->width * img_met_rough->height; ++i) - // { - // uint32_t pixel = data32[i]; - // float r = ((pixel >> 0) & 255) / 255.0f; - // float g = ((pixel >> 8) & 255) / 255.0f; - // float b = ((pixel >> 16) & 255) / 255.0f; - // float a = ((pixel >> 24) & 255) / 255.0f; + if (img_met_rough != nullptr) + { + uint32_t* data32_emissive = nullptr; + if (img_emissive != nullptr && img_emissive->width == img_met_rough->width && img_emissive->height == img_met_rough->height) + { + data32_emissive = (uint32_t*)img_emissive->image.data(); + } - // float reflectance = 1; - // float metalness = b; - // float emissive = 0; - // float sss = 1; + uint32_t* data32 = (uint32_t*)img_met_rough->image.data(); + for (int i = 0; i < img_met_rough->width * img_met_rough->height; ++i) + { + uint32_t pixel = data32[i]; + float r = ((pixel >> 0) & 255) / 255.0f; + float g = ((pixel >> 8) & 255) / 255.0f; + float b = ((pixel >> 16) & 255) / 255.0f; + float a = ((pixel >> 24) & 255) / 255.0f; - // if (data32_emissive != nullptr) - // { - // // add emissive from texture (R): - // // (Currently only supporting single channel emissive) - // emissive = ((data32_emissive[i] >> 0) & 255) / 255.0f; - // } + float reflectance = 1; + float metalness = b; + float emissive = 0; + float sss = 1; - // uint32_t rgba8 = 0; - // rgba8 |= (uint32_t)(reflectance * 255.0f) << 0; - // rgba8 |= (uint32_t)(metalness * 255.0f) << 8; - // rgba8 |= (uint32_t)(emissive * 255.0f) << 16; - // rgba8 |= (uint32_t)(sss * 255.0f) << 24; + if (data32_emissive != nullptr) + { + // add emissive from texture (R): + // (Currently only supporting single channel emissive) + emissive = ((data32_emissive[i] >> 0) & 255) / 255.0f; + } - // data32[i] = rgba8; - // } + uint32_t rgba8 = 0; + rgba8 |= (uint32_t)(reflectance * 255.0f) << 0; + rgba8 |= (uint32_t)(metalness * 255.0f) << 8; + rgba8 |= (uint32_t)(emissive * 255.0f) << 16; + rgba8 |= (uint32_t)(sss * 255.0f) << 24; - // RegisterTexture2D(img_met_rough); - // material->surfaceMapName = img_met_rough->name; - // } - // else if (img_emissive != nullptr) - // { - // // No metalness texture, just emissive... - // uint32_t* data32 = (uint32_t*)img_emissive->image.data(); + data32[i] = rgba8; + } - // if (data32 != nullptr) - // { - // for (int i = 0; i < img_emissive->width * img_emissive->height; ++i) - // { - // uint32_t pixel = data32[i]; - // float r = ((pixel >> 0) & 255) / 255.0f; - // float g = ((pixel >> 8) & 255) / 255.0f; - // float b = ((pixel >> 16) & 255) / 255.0f; - // float a = ((pixel >> 24) & 255) / 255.0f; + RegisterTexture2D(img_met_rough); + material.surfaceMapName = img_met_rough->name; + } + else if (img_emissive != nullptr) + { + // No metalness texture, just emissive... + uint32_t* data32 = (uint32_t*)img_emissive->image.data(); - // float reflectance = 1; - // float metalness = 1; - // float emissive = r; - // float sss = 1; + if (data32 != nullptr) + { + for (int i = 0; i < img_emissive->width * img_emissive->height; ++i) + { + uint32_t pixel = data32[i]; + float r = ((pixel >> 0) & 255) / 255.0f; + float g = ((pixel >> 8) & 255) / 255.0f; + float b = ((pixel >> 16) & 255) / 255.0f; + float a = ((pixel >> 24) & 255) / 255.0f; - // uint32_t rgba8 = 0; - // rgba8 |= (uint32_t)(reflectance * 255.0f) << 0; - // rgba8 |= (uint32_t)(metalness * 255.0f) << 8; - // rgba8 |= (uint32_t)(emissive * 255.0f) << 16; - // rgba8 |= (uint32_t)(sss * 255.0f) << 24; + float reflectance = 1; + float metalness = 1; + float emissive = r; + float sss = 1; - // data32[i] = rgba8; - // } + uint32_t rgba8 = 0; + rgba8 |= (uint32_t)(reflectance * 255.0f) << 0; + rgba8 |= (uint32_t)(metalness * 255.0f) << 8; + rgba8 |= (uint32_t)(emissive * 255.0f) << 16; + rgba8 |= (uint32_t)(sss * 255.0f) << 24; - // RegisterTexture2D(img_emissive); - // material->surfaceMapName = img_emissive->name; - // } - // } + data32[i] = rgba8; + } - // // Retrieve textures by name: - // if (!material->textureName.empty()) - // material->texture = (Texture2D*)wiResourceManager::GetGlobal()->add(material->textureName); - // if (!material->normalMapName.empty()) - // material->normalMap = (Texture2D*)wiResourceManager::GetGlobal()->add(material->normalMapName); - // if (!material->surfaceMapName.empty()) - // material->surfaceMap = (Texture2D*)wiResourceManager::GetGlobal()->add(material->surfaceMapName); + RegisterTexture2D(img_emissive); + material.surfaceMapName = img_emissive->name; + } + } - // if (baseColorFactor != x.values.end()) - // { - // material->baseColor.x = static_cast(baseColorFactor->second.ColorFactor()[0]); - // material->baseColor.y = static_cast(baseColorFactor->second.ColorFactor()[1]); - // material->baseColor.z = static_cast(baseColorFactor->second.ColorFactor()[2]); - // } - // if (roughnessFactor != x.values.end()) - // { - // material->roughness = static_cast(roughnessFactor->second.Factor()); - // } - // if (metallicFactor != x.values.end()) - // { - // material->metalness = static_cast(metallicFactor->second.Factor()); - // } - // if (emissiveFactor != x.additionalValues.end()) - // { - // material->emissive = static_cast(emissiveFactor->second.ColorFactor()[0]); - // } - // if (alphaCutoff != x.additionalValues.end()) - // { - // material->alphaRef = 1 - static_cast(alphaCutoff->second.Factor()); - // } + // Retrieve textures by name: + if (!material.baseColorMapName.empty()) + material.baseColorMap = (Texture2D*)wiResourceManager::GetGlobal()->add(material.baseColorMapName); + if (!material.normalMapName.empty()) + material.normalMap = (Texture2D*)wiResourceManager::GetGlobal()->add(material.normalMapName); + if (!material.surfaceMapName.empty()) + material.surfaceMap = (Texture2D*)wiResourceManager::GetGlobal()->add(material.surfaceMapName); - //} + if (baseColorFactor != x.values.end()) + { + material.baseColor.x = static_cast(baseColorFactor->second.ColorFactor()[0]); + material.baseColor.y = static_cast(baseColorFactor->second.ColorFactor()[1]); + material.baseColor.z = static_cast(baseColorFactor->second.ColorFactor()[2]); + } + if (roughnessFactor != x.values.end()) + { + material.roughness = static_cast(roughnessFactor->second.Factor()); + } + if (metallicFactor != x.values.end()) + { + material.metalness = static_cast(metallicFactor->second.Factor()); + } + if (emissiveFactor != x.additionalValues.end()) + { + material.emissive = static_cast(emissiveFactor->second.ColorFactor()[0]); + } + if (alphaCutoff != x.additionalValues.end()) + { + material.alphaRef = 1 - static_cast(alphaCutoff->second.Factor()); + } + + } //for(auto& skin : gltfModel.skins) //{ @@ -856,11 +782,11 @@ Entity ImportModel_GLTF(const std::string& fileName) //} - //const tinygltf::Scene &scene = gltfModel.scenes[gltfModel.defaultScene]; - //for (size_t i = 0; i < scene.nodes.size(); i++) - //{ - // LoadNode(&gltfModel.nodes[scene.nodes[i]], nullptr, model, gltfModel, meshArray, armatureArray); - //} + const tinygltf::Scene &gltfScene = gltfModel.scenes[gltfModel.defaultScene]; + for (size_t i = 0; i < gltfScene.nodes.size(); i++) + { + LoadNode(&gltfModel.nodes[gltfScene.nodes[i]], INVALID_ENTITY, modelEntity, gltfModel, materialArray, meshArray, armatureArray); + } //int animID = 0; //for (auto& anim : gltfModel.animations) @@ -1038,5 +964,5 @@ Entity ImportModel_GLTF(const std::string& fileName) //model->FinishLoading(); - //return model; + return modelEntity; } diff --git a/Editor/ObjectWindow.cpp b/Editor/ObjectWindow.cpp index d2ab4fd48..535018645 100644 --- a/Editor/ObjectWindow.cpp +++ b/Editor/ObjectWindow.cpp @@ -1,5 +1,6 @@ #include "stdafx.h" #include "ObjectWindow.h" +#include "wiSceneSystem.h" using namespace wiECS; @@ -22,210 +23,217 @@ ObjectWindow::ObjectWindow(wiGUI* gui) : GUI(gui) float x = 450; float y = 0; - //renderableCheckBox = new wiCheckBox("Renderable: "); - //renderableCheckBox->SetTooltip("Set object to be participating in rendering."); - //renderableCheckBox->SetPos(XMFLOAT2(x, y += 30)); - //renderableCheckBox->SetCheck(true); - //renderableCheckBox->OnClick([&](wiEventArgs args) { - // if (object != nullptr) - // { - // object->renderable = args.bValue; - // } - //}); - //objectWindow->AddWidget(renderableCheckBox); + renderableCheckBox = new wiCheckBox("Renderable: "); + renderableCheckBox->SetTooltip("Set object to be participating in rendering."); + renderableCheckBox->SetPos(XMFLOAT2(x, y += 30)); + renderableCheckBox->SetCheck(true); + renderableCheckBox->OnClick([&](wiEventArgs args) { + ObjectComponent* object = wiRenderer::GetScene().objects.GetComponent(entity); + if (object != nullptr) + { + object->renderable = args.bValue; + } + }); + objectWindow->AddWidget(renderableCheckBox); - //ditherSlider = new wiSlider(0, 1, 0, 1000, "Dither: "); - //ditherSlider->SetTooltip("Adjust dithered transparency of the object. This disables some optimizations so performance can be affected."); - //ditherSlider->SetSize(XMFLOAT2(100, 30)); - //ditherSlider->SetPos(XMFLOAT2(x, y += 30)); - //ditherSlider->OnSlide([&](wiEventArgs args) { - // if (object != nullptr) - // { - // object->transparency = args.fValue; - // } - //}); - //objectWindow->AddWidget(ditherSlider); + ditherSlider = new wiSlider(0, 1, 0, 1000, "Dither: "); + ditherSlider->SetTooltip("Adjust dithered transparency of the object. This disables some optimizations so performance can be affected."); + ditherSlider->SetSize(XMFLOAT2(100, 30)); + ditherSlider->SetPos(XMFLOAT2(x, y += 30)); + ditherSlider->OnSlide([&](wiEventArgs args) { + ObjectComponent* object = wiRenderer::GetScene().objects.GetComponent(entity); + if (object != nullptr) + { + object->color.w = 1 - args.fValue; + } + }); + objectWindow->AddWidget(ditherSlider); - //cascadeMaskSlider = new wiSlider(0, 3, 0, 3, "Cascade Mask: "); - //cascadeMaskSlider->SetTooltip("How many shadow cascades to skip when rendering this object into shadow maps? (0: skip none, it will be in all cascades, 1: skip first (biggest cascade), ...etc..."); - //cascadeMaskSlider->SetSize(XMFLOAT2(100, 30)); - //cascadeMaskSlider->SetPos(XMFLOAT2(x, y += 30)); - //cascadeMaskSlider->OnSlide([&](wiEventArgs args) { - // if (object != nullptr) - // { - // object->cascadeMask = args.iValue; - // } - //}); - //objectWindow->AddWidget(cascadeMaskSlider); + cascadeMaskSlider = new wiSlider(0, 3, 0, 3, "Cascade Mask: "); + cascadeMaskSlider->SetTooltip("How many shadow cascades to skip when rendering this object into shadow maps? (0: skip none, it will be in all cascades, 1: skip first (biggest cascade), ...etc..."); + cascadeMaskSlider->SetSize(XMFLOAT2(100, 30)); + cascadeMaskSlider->SetPos(XMFLOAT2(x, y += 30)); + cascadeMaskSlider->OnSlide([&](wiEventArgs args) { + ObjectComponent* object = wiRenderer::GetScene().objects.GetComponent(entity); + if (object != nullptr) + { + object->cascadeMask = args.iValue; + } + }); + objectWindow->AddWidget(cascadeMaskSlider); - //colorPicker = new wiColorPicker(GUI, "Object Color"); - //colorPicker->SetPos(XMFLOAT2(10, 30)); - //colorPicker->RemoveWidgets(); - //colorPicker->SetVisible(true); - //colorPicker->SetEnabled(true); - //colorPicker->OnColorChanged([&](wiEventArgs args) { - // if (object != nullptr) - // { - // object->color = XMFLOAT3(powf(args.color.x, 1.f / 2.2f), powf(args.color.y, 1.f / 2.2f), powf(args.color.z, 1.f / 2.2f)); - // } - //}); - //objectWindow->AddWidget(colorPicker); + colorPicker = new wiColorPicker(GUI, "Object Color"); + colorPicker->SetPos(XMFLOAT2(10, 30)); + colorPicker->RemoveWidgets(); + colorPicker->SetVisible(true); + colorPicker->SetEnabled(true); + colorPicker->OnColorChanged([&](wiEventArgs args) { + ObjectComponent* object = wiRenderer::GetScene().objects.GetComponent(entity); + if (object != nullptr) + { + object->color = XMFLOAT4(powf(args.color.x, 1.f / 2.2f), powf(args.color.y, 1.f / 2.2f), powf(args.color.z, 1.f / 2.2f), object->color.w); + } + }); + objectWindow->AddWidget(colorPicker); - //y += 60; + y += 60; - //physicsLabel = new wiLabel("PHYSICSLABEL"); - //physicsLabel->SetText("PHYSICS SETTINGS"); - //physicsLabel->SetPos(XMFLOAT2(x - 30, y += 30)); - //physicsLabel->SetSize(XMFLOAT2(150, 20)); - //objectWindow->AddWidget(physicsLabel); + physicsLabel = new wiLabel("PHYSICSLABEL"); + physicsLabel->SetText("PHYSICS SETTINGS"); + physicsLabel->SetPos(XMFLOAT2(x - 30, y += 30)); + physicsLabel->SetSize(XMFLOAT2(150, 20)); + objectWindow->AddWidget(physicsLabel); - //simulationTypeComboBox = new wiComboBox("Simulation Type:"); - //simulationTypeComboBox->SetSize(XMFLOAT2(100, 20)); - //simulationTypeComboBox->SetPos(XMFLOAT2(x, y += 30)); - //simulationTypeComboBox->AddItem("None"); - //simulationTypeComboBox->AddItem("Rigid Body"); + simulationTypeComboBox = new wiComboBox("Simulation Type:"); + simulationTypeComboBox->SetSize(XMFLOAT2(100, 20)); + simulationTypeComboBox->SetPos(XMFLOAT2(x, y += 30)); + simulationTypeComboBox->AddItem("None"); + simulationTypeComboBox->AddItem("Rigid Body"); //simulationTypeComboBox->AddItem("Soft Body"); - //simulationTypeComboBox->OnSelect([&](wiEventArgs args) { - // if (object != nullptr) - // { - // wiRenderer::physicsEngine->removeObject(object); + simulationTypeComboBox->OnSelect([&](wiEventArgs args) { + //PhysicsComponent* physicscomponent = wiRenderer::GetScene().physicscomponents.GetComponent(entity); + //if (physicscomponent != nullptr) + //{ + // wiRenderer::physicsEngine->removeObject(*physicscomponent); - // switch (args.iValue) - // { - // case 0: - // object->rigidBody = false; - // if (object->mesh != nullptr) - // { - // object->mesh->softBody = false; - // } + // switch (args.iValue) + // { + // case 0: + // physicscomponent->rigidBody = false; + // //if (object->mesh != nullptr) + // //{ + // // object->mesh->softBody = false; + // //} - // kinematicCheckBox->SetEnabled(false); - // physicsTypeComboBox->SetEnabled(false); - // collisionShapeComboBox->SetEnabled(false); - // break; - // case 1: - // object->rigidBody = true; - // if (object->mesh != nullptr) - // { - // object->mesh->softBody = false; - // } + // kinematicCheckBox->SetEnabled(false); + // physicsTypeComboBox->SetEnabled(false); + // collisionShapeComboBox->SetEnabled(false); + // break; + // case 1: + // physicscomponent->rigidBody = true; + // //if (object->mesh != nullptr) + // //{ + // // object->mesh->softBody = false; + // //} - // kinematicCheckBox->SetEnabled(true); - // physicsTypeComboBox->SetEnabled(true); - // collisionShapeComboBox->SetEnabled(true); - // break; - // case 2: - // object->rigidBody = false; - // if (object->mesh != nullptr) - // { - // object->mesh->softBody = true; - // } + // kinematicCheckBox->SetEnabled(true); + // physicsTypeComboBox->SetEnabled(true); + // collisionShapeComboBox->SetEnabled(true); + // break; + // //case 2: + // // object->rigidBody = false; + // // if (object->mesh != nullptr) + // // { + // // object->mesh->softBody = true; + // // } - // kinematicCheckBox->SetEnabled(false); - // physicsTypeComboBox->SetEnabled(true); - // collisionShapeComboBox->SetEnabled(false); - // break; - // default: - // break; - // } + // // kinematicCheckBox->SetEnabled(false); + // // physicsTypeComboBox->SetEnabled(true); + // // collisionShapeComboBox->SetEnabled(false); + // // break; + // default: + // assert(0); + // break; + // } - // wiRenderer::physicsEngine->registerObject(object); + // wiRenderer::physicsEngine->registerObject(*physicscomponent); - // } - //}); - //simulationTypeComboBox->SetSelected(0); - //simulationTypeComboBox->SetEnabled(true); - //simulationTypeComboBox->SetTooltip("Set simulation type."); - //objectWindow->AddWidget(simulationTypeComboBox); + //} + }); + simulationTypeComboBox->SetSelected(0); + simulationTypeComboBox->SetEnabled(true); + simulationTypeComboBox->SetTooltip("Set simulation type."); + objectWindow->AddWidget(simulationTypeComboBox); - //kinematicCheckBox = new wiCheckBox("Kinematic: "); - //kinematicCheckBox->SetTooltip("Toggle kinematic behaviour."); - //kinematicCheckBox->SetPos(XMFLOAT2(x, y += 30)); - //kinematicCheckBox->SetCheck(false); - //kinematicCheckBox->OnClick([&](wiEventArgs args) { - // if (object != nullptr) - // { - // wiRenderer::physicsEngine->removeObject(object); + kinematicCheckBox = new wiCheckBox("Kinematic: "); + kinematicCheckBox->SetTooltip("Toggle kinematic behaviour."); + kinematicCheckBox->SetPos(XMFLOAT2(x, y += 30)); + kinematicCheckBox->SetCheck(false); + kinematicCheckBox->OnClick([&](wiEventArgs args) { + //PhysicsComponent* physicscomponent = wiRenderer::GetScene().physicscomponents.GetComponent(entity); + //if (physicscomponent != nullptr) + //{ + // wiRenderer::physicsEngine->removeObject(object); - // object->kinematic = args.bValue; + // object->kinematic = args.bValue; - // wiRenderer::physicsEngine->registerObject(object); - // } - //}); - //objectWindow->AddWidget(kinematicCheckBox); + // wiRenderer::physicsEngine->registerObject(object); + //} + }); + objectWindow->AddWidget(kinematicCheckBox); - //physicsTypeComboBox = new wiComboBox("Contribution Type:"); - //physicsTypeComboBox->SetSize(XMFLOAT2(100, 20)); - //physicsTypeComboBox->SetPos(XMFLOAT2(x, y += 30)); - //physicsTypeComboBox->AddItem("Active"); - //physicsTypeComboBox->AddItem("Passive"); - //physicsTypeComboBox->OnSelect([&](wiEventArgs args) { - // if (object != nullptr) - // { - // wiRenderer::physicsEngine->removeObject(object); + physicsTypeComboBox = new wiComboBox("Contribution Type:"); + physicsTypeComboBox->SetSize(XMFLOAT2(100, 20)); + physicsTypeComboBox->SetPos(XMFLOAT2(x, y += 30)); + physicsTypeComboBox->AddItem("Active"); + physicsTypeComboBox->AddItem("Passive"); + physicsTypeComboBox->OnSelect([&](wiEventArgs args) { + //if (object != nullptr) + //{ + // wiRenderer::physicsEngine->removeObject(object); - // switch (args.iValue) - // { - // case 0: - // object->physicsType = "ACTIVE"; - // break; - // case 1: - // object->physicsType = "PASSIVE"; - // break; - // default: - // break; - // } + // switch (args.iValue) + // { + // case 0: + // object->physicsType = "ACTIVE"; + // break; + // case 1: + // object->physicsType = "PASSIVE"; + // break; + // default: + // break; + // } - // wiRenderer::physicsEngine->registerObject(object); - // } - //}); - //physicsTypeComboBox->SetSelected(0); - //physicsTypeComboBox->SetEnabled(true); - //physicsTypeComboBox->SetTooltip("Set physics type."); - //objectWindow->AddWidget(physicsTypeComboBox); + // wiRenderer::physicsEngine->registerObject(object); + //} + }); + physicsTypeComboBox->SetSelected(0); + physicsTypeComboBox->SetEnabled(true); + physicsTypeComboBox->SetTooltip("Set physics type."); + objectWindow->AddWidget(physicsTypeComboBox); - //collisionShapeComboBox = new wiComboBox("Collision Shape:"); - //collisionShapeComboBox->SetSize(XMFLOAT2(100, 20)); - //collisionShapeComboBox->SetPos(XMFLOAT2(x, y += 30)); - //collisionShapeComboBox->AddItem("Box"); - //collisionShapeComboBox->AddItem("Sphere"); - //collisionShapeComboBox->AddItem("Capsule"); - //collisionShapeComboBox->AddItem("Convex Hull"); - //collisionShapeComboBox->AddItem("Triangle Mesh"); - //collisionShapeComboBox->OnSelect([&](wiEventArgs args) { - // if (object != nullptr) - // { - // wiRenderer::physicsEngine->removeObject(object); + collisionShapeComboBox = new wiComboBox("Collision Shape:"); + collisionShapeComboBox->SetSize(XMFLOAT2(100, 20)); + collisionShapeComboBox->SetPos(XMFLOAT2(x, y += 30)); + collisionShapeComboBox->AddItem("Box"); + collisionShapeComboBox->AddItem("Sphere"); + collisionShapeComboBox->AddItem("Capsule"); + collisionShapeComboBox->AddItem("Convex Hull"); + collisionShapeComboBox->AddItem("Triangle Mesh"); + collisionShapeComboBox->OnSelect([&](wiEventArgs args) { + //if (object != nullptr) + //{ + // wiRenderer::physicsEngine->removeObject(object); - // switch (args.iValue) - // { - // case 0: - // object->collisionShape = "BOX"; - // break; - // case 1: - // object->collisionShape = "SPHERE"; - // break; - // case 2: - // object->collisionShape = "CAPSULE"; - // break; - // case 3: - // object->collisionShape = "CONVEX_HULL"; - // break; - // case 4: - // object->collisionShape = "MESH"; - // break; - // default: - // break; - // } + // switch (args.iValue) + // { + // case 0: + // object->collisionShape = "BOX"; + // break; + // case 1: + // object->collisionShape = "SPHERE"; + // break; + // case 2: + // object->collisionShape = "CAPSULE"; + // break; + // case 3: + // object->collisionShape = "CONVEX_HULL"; + // break; + // case 4: + // object->collisionShape = "MESH"; + // break; + // default: + // break; + // } - // wiRenderer::physicsEngine->registerObject(object); - // } - //}); - //collisionShapeComboBox->SetSelected(0); - //collisionShapeComboBox->SetEnabled(true); - //collisionShapeComboBox->SetTooltip("Set rigid body collision shape."); - //objectWindow->AddWidget(collisionShapeComboBox); + // wiRenderer::physicsEngine->registerObject(object); + //} + }); + collisionShapeComboBox->SetSelected(0); + collisionShapeComboBox->SetEnabled(true); + collisionShapeComboBox->SetTooltip("Set rigid body collision shape."); + objectWindow->AddWidget(collisionShapeComboBox); @@ -247,99 +255,106 @@ ObjectWindow::~ObjectWindow() void ObjectWindow::SetEntity(Entity entity) { + if (this->entity == entity) + return; + this->entity = entity; - //if (this->object == obj) - // return; + Scene& scene = wiRenderer::GetScene(); - //object = obj; + const ObjectComponent* object = scene.objects.GetComponent(entity); - //if (object != nullptr) - //{ - // renderableCheckBox->SetCheck(object->renderable); - // cascadeMaskSlider->SetValue((float)object->cascadeMask); - // ditherSlider->SetValue(object->transparency); + if (object != nullptr) + { + renderableCheckBox->SetCheck(object->renderable); + cascadeMaskSlider->SetValue((float)object->cascadeMask); + ditherSlider->SetValue(object->GetTransparency()); - // if (object->rigidBody) - // { - // simulationTypeComboBox->SetSelected(1); - // } - // else - // { - // if (object->mesh != nullptr) - // { - // if (object->mesh->softBody) - // { - // simulationTypeComboBox->SetSelected(2); - // } - // else - // { - // simulationTypeComboBox->SetSelected(0); - // } - // } - // else - // { - // simulationTypeComboBox->SetSelected(0); - // } - // } + const PhysicsComponent* physicsComponent = scene.physicscomponents.GetComponent(entity); - // kinematicCheckBox->SetCheck(object->kinematic); + if (physicsComponent != nullptr) + { + if (physicsComponent->rigidBody) + { + simulationTypeComboBox->SetSelected(1); + } + //else + //{ + // if (object->mesh != nullptr) + // { + // if (object->mesh->softBody) + // { + // simulationTypeComboBox->SetSelected(2); + // } + // else + // { + // simulationTypeComboBox->SetSelected(0); + // } + // } + // else + // { + // simulationTypeComboBox->SetSelected(0); + // } + //} - // if (!object->physicsType.compare("ACTIVE")) - // { - // physicsTypeComboBox->SetSelected(0); - // } - // else if (!object->physicsType.compare("PASSIVE")) - // { - // physicsTypeComboBox->SetSelected(1); - // } + kinematicCheckBox->SetCheck(physicsComponent->kinematic); - // if (!object->collisionShape.compare("BOX")) - // { - // collisionShapeComboBox->SetSelected(0); - // } - // else if (!object->collisionShape.compare("SPHERE")) - // { - // collisionShapeComboBox->SetSelected(1); - // } - // else if (!object->collisionShape.compare("CAPSULE")) - // { - // collisionShapeComboBox->SetSelected(2); - // } - // else if (!object->collisionShape.compare("CONVEX_HULL")) - // { - // collisionShapeComboBox->SetSelected(3); - // } - // else if (!object->collisionShape.compare("MESH")) - // { - // collisionShapeComboBox->SetSelected(4); - // } + if (!physicsComponent->physicsType.compare("ACTIVE")) + { + physicsTypeComboBox->SetSelected(0); + } + else if (!physicsComponent->physicsType.compare("PASSIVE")) + { + physicsTypeComboBox->SetSelected(1); + } - // objectWindow->SetEnabled(true); + if (!physicsComponent->collisionShape.compare("BOX")) + { + collisionShapeComboBox->SetSelected(0); + } + else if (!physicsComponent->collisionShape.compare("SPHERE")) + { + collisionShapeComboBox->SetSelected(1); + } + else if (!physicsComponent->collisionShape.compare("CAPSULE")) + { + collisionShapeComboBox->SetSelected(2); + } + else if (!physicsComponent->collisionShape.compare("CONVEX_HULL")) + { + collisionShapeComboBox->SetSelected(3); + } + else if (!physicsComponent->collisionShape.compare("MESH")) + { + collisionShapeComboBox->SetSelected(4); + } + } + + objectWindow->SetEnabled(true); - // switch (simulationTypeComboBox->GetSelected()) - // { - // case 1: - // kinematicCheckBox->SetEnabled(true); - // physicsTypeComboBox->SetEnabled(true); - // collisionShapeComboBox->SetEnabled(true); - // break; - // case 2: - // kinematicCheckBox->SetEnabled(false); - // physicsTypeComboBox->SetEnabled(true); - // collisionShapeComboBox->SetEnabled(false); - // break; - // default: - // kinematicCheckBox->SetEnabled(false); - // physicsTypeComboBox->SetEnabled(false); - // collisionShapeComboBox->SetEnabled(false); - // break; - // } - //} - //else - //{ - // objectWindow->SetEnabled(false); - //} + switch (simulationTypeComboBox->GetSelected()) + { + case 1: + kinematicCheckBox->SetEnabled(true); + physicsTypeComboBox->SetEnabled(true); + collisionShapeComboBox->SetEnabled(true); + break; + case 2: + kinematicCheckBox->SetEnabled(false); + physicsTypeComboBox->SetEnabled(true); + collisionShapeComboBox->SetEnabled(false); + break; + default: + kinematicCheckBox->SetEnabled(false); + physicsTypeComboBox->SetEnabled(false); + collisionShapeComboBox->SetEnabled(false); + break; + } + } + else + { + objectWindow->SetEnabled(false); + } } diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index c6587c977..5e23ce6e2 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -8137,150 +8137,155 @@ void wiRenderer::SynchronizeWithPhysicsEngine(float dt) void wiRenderer::CreateImpostor(Entity entity, GRAPHICSTHREAD threadID) { - //MeshComponent& mesh = GetScene().meshes.GetComponent(mesh_ref); + Scene& scene = GetScene(); - //static const int res = 256; + MeshComponent& mesh = *scene.meshes.GetComponent(entity); - //const AABB& bbox = mesh.aabb; - //const XMFLOAT3 extents = bbox.getHalfWidth(); - //if (!mesh.impostorTarget.IsInitialized()) - //{ - // mesh.impostorTarget.Initialize(res * 6, res, true, RTFormat_impostor_albedo, 0); - // mesh.impostorTarget.Add(RTFormat_impostor_normal); // normal, roughness - // mesh.impostorTarget.Add(RTFormat_impostor_surface); // surface properties - //} + static const int res = 256; - //CameraComponent savedCam = *cam; + const AABB& bbox = mesh.aabb; + const XMFLOAT3 extents = bbox.getHalfWidth(); + if (!mesh.impostorTarget.IsInitialized()) + { + mesh.impostorTarget.Initialize(res * 6, res, true, RTFormat_impostor_albedo, 0); + mesh.impostorTarget.Add(RTFormat_impostor_normal); // normal, roughness + mesh.impostorTarget.Add(RTFormat_impostor_surface); // surface properties + } - //BindPersistentState(threadID); - //const XMFLOAT4X4 __identity = XMFLOAT4X4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); - //struct InstBuf - //{ - // Instance instance; - // InstancePrev instancePrev; - //}; - //UINT instancesOffset; - //volatile InstBuf* buff = (volatile InstBuf*)GetDevice()->AllocateFromRingBuffer(dynamicVertexBufferPool, sizeof(InstBuf), instancesOffset, threadID); - //buff->instance.Create(__identity); - //buff->instancePrev.Create(__identity); - //GetDevice()->InvalidateBufferAccess(dynamicVertexBufferPool, threadID); + CameraComponent camera = *getCamera(); + TransformComponent camera_transform = *scene.transforms.GetComponent(getCameraID()); - //GPUBuffer* vbs[] = { - // mesh.IsSkinned() ? mesh.streamoutBuffer_POS : mesh.vertexBuffer_POS, - // mesh.vertexBuffer_TEX, - // mesh.IsSkinned() ? mesh.streamoutBuffer_PRE : mesh.vertexBuffer_POS, - // dynamicVertexBufferPool - //}; - //UINT strides[] = { - // sizeof(MeshComponent::Vertex_POS), - // sizeof(MeshComponent::Vertex_TEX), - // sizeof(MeshComponent::Vertex_POS), - // sizeof(InstBuf) - //}; - //UINT offsets[] = { - // 0, - // 0, - // 0, - // instancesOffset - //}; - //GetDevice()->BindVertexBuffers(vbs, 0, ARRAYSIZE(vbs), strides, offsets, threadID); + BindPersistentState(threadID); - //GetDevice()->BindIndexBuffer(mesh.indexBuffer, mesh.GetIndexFormat(), 0, threadID); + const XMFLOAT4X4 __identity = XMFLOAT4X4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); + struct InstBuf + { + Instance instance; + InstancePrev instancePrev; + }; + UINT instancesOffset; + volatile InstBuf* buff = (volatile InstBuf*)GetDevice()->AllocateFromRingBuffer(dynamicVertexBufferPool, sizeof(InstBuf), instancesOffset, threadID); + buff->instance.Create(__identity); + buff->instancePrev.Create(__identity); + GetDevice()->InvalidateBufferAccess(dynamicVertexBufferPool, threadID); - //GetDevice()->BindGraphicsPSO(PSO_captureimpostor, threadID); + GPUBuffer* vbs[] = { + mesh.IsSkinned() ? mesh.streamoutBuffer_POS : mesh.vertexBuffer_POS, + mesh.vertexBuffer_TEX, + mesh.IsSkinned() ? mesh.streamoutBuffer_PRE : mesh.vertexBuffer_POS, + dynamicVertexBufferPool + }; + UINT strides[] = { + sizeof(MeshComponent::Vertex_POS), + sizeof(MeshComponent::Vertex_TEX), + sizeof(MeshComponent::Vertex_POS), + sizeof(InstBuf) + }; + UINT offsets[] = { + 0, + 0, + 0, + instancesOffset + }; + GetDevice()->BindVertexBuffers(vbs, 0, ARRAYSIZE(vbs), strides, offsets, threadID); - //ViewPort savedViewPort = mesh.impostorTarget.viewPort; - //mesh.impostorTarget.Activate(threadID, 0, 0, 0, 0); - //for (size_t i = 0; i < 6; ++i) - //{ - // mesh.impostorTarget.viewPort.Height = (float)res; - // mesh.impostorTarget.viewPort.Width = (float)res; - // mesh.impostorTarget.viewPort.TopLeftX = (float)(i*res); - // mesh.impostorTarget.viewPort.TopLeftY = 0.f; - // mesh.impostorTarget.Set(threadID); + GetDevice()->BindIndexBuffer(mesh.indexBuffer, mesh.GetIndexFormat(), 0, threadID); - // cam->ClearTransform(); - // cam->Translate(bbox.getCenter()); - // switch (i) - // { - // case 0: - // { - // // front capture - // XMMATRIX ortho = XMMatrixOrthographicOffCenterLH(-extents.x, extents.x, -extents.y, extents.y, -extents.z, extents.z); - // XMStoreFloat4x4(&cam->Projection, ortho); - // } - // break; - // case 1: - // { - // // right capture - // XMMATRIX ortho = XMMatrixOrthographicOffCenterLH(-extents.z, extents.z, -extents.y, extents.y, -extents.x, extents.x); - // XMStoreFloat4x4(&cam->Projection, ortho); - // cam->RotateRollPitchYaw(XMFLOAT3(0, -XM_PIDIV2, 0)); - // } - // break; - // case 2: - // { - // // back capture - // XMMATRIX ortho = XMMatrixOrthographicOffCenterLH(-extents.x, extents.x, -extents.y, extents.y, -extents.z, extents.z); - // XMStoreFloat4x4(&cam->Projection, ortho); - // cam->RotateRollPitchYaw(XMFLOAT3(0, -XM_PI, 0)); - // } - // break; - // case 3: - // { - // // left capture - // XMMATRIX ortho = XMMatrixOrthographicOffCenterLH(-extents.z, extents.z, -extents.y, extents.y, -extents.x, extents.x); - // XMStoreFloat4x4(&cam->Projection, ortho); - // cam->RotateRollPitchYaw(XMFLOAT3(0, XM_PIDIV2, 0)); - // } - // break; - // case 4: - // { - // // bottom capture - // XMMATRIX ortho = XMMatrixOrthographicOffCenterLH(-extents.x, extents.x, -extents.z, extents.z, -extents.y, extents.y); - // XMStoreFloat4x4(&cam->Projection, ortho); - // cam->RotateRollPitchYaw(XMFLOAT3(-XM_PIDIV2, 0, 0)); - // } - // break; - // case 5: - // { - // // top capture - // XMMATRIX ortho = XMMatrixOrthographicOffCenterLH(-extents.x, extents.x, -extents.z, extents.z, -extents.y, extents.y); - // XMStoreFloat4x4(&cam->Projection, ortho); - // cam->RotateRollPitchYaw(XMFLOAT3(XM_PIDIV2, 0, 0)); - // } - // break; - // default: - // break; - // } - // cam->UpdateProps(); - // UpdateCameraCB(cam, threadID); + GetDevice()->BindGraphicsPSO(PSO_captureimpostor, threadID); - // for (MeshComponent::MeshSubset& subset : mesh.subsets) - // { - // if (subset.subsetIndices.empty()) - // { - // continue; - // } - // MaterialComponent& material = GetScene().materials.GetComponent(subset.material_ref); + ViewPort savedViewPort = mesh.impostorTarget.viewPort; + mesh.impostorTarget.Activate(threadID, 0, 0, 0, 0); + for (size_t i = 0; i < 6; ++i) + { + mesh.impostorTarget.viewPort.Height = (float)res; + mesh.impostorTarget.viewPort.Width = (float)res; + mesh.impostorTarget.viewPort.TopLeftX = (float)(i*res); + mesh.impostorTarget.viewPort.TopLeftY = 0.f; + mesh.impostorTarget.Set(threadID); - // GetDevice()->BindConstantBuffer(PS, material.constantBuffer, CB_GETBINDSLOT(MaterialCB), threadID); + camera_transform.ClearTransform(); + camera_transform.Translate(bbox.getCenter()); + switch (i) + { + case 0: + { + // front capture + XMMATRIX ortho = XMMatrixOrthographicOffCenterLH(-extents.x, extents.x, -extents.y, extents.y, -extents.z, extents.z); + XMStoreFloat4x4(&camera.Projection, ortho); + } + break; + case 1: + { + // right capture + XMMATRIX ortho = XMMatrixOrthographicOffCenterLH(-extents.z, extents.z, -extents.y, extents.y, -extents.x, extents.x); + XMStoreFloat4x4(&camera.Projection, ortho); + camera_transform.RotateRollPitchYaw(XMFLOAT3(0, -XM_PIDIV2, 0)); + } + break; + case 2: + { + // back capture + XMMATRIX ortho = XMMatrixOrthographicOffCenterLH(-extents.x, extents.x, -extents.y, extents.y, -extents.z, extents.z); + XMStoreFloat4x4(&camera.Projection, ortho); + camera_transform.RotateRollPitchYaw(XMFLOAT3(0, -XM_PI, 0)); + } + break; + case 3: + { + // left capture + XMMATRIX ortho = XMMatrixOrthographicOffCenterLH(-extents.z, extents.z, -extents.y, extents.y, -extents.x, extents.x); + XMStoreFloat4x4(&camera.Projection, ortho); + camera_transform.RotateRollPitchYaw(XMFLOAT3(0, XM_PIDIV2, 0)); + } + break; + case 4: + { + // bottom capture + XMMATRIX ortho = XMMatrixOrthographicOffCenterLH(-extents.x, extents.x, -extents.z, extents.z, -extents.y, extents.y); + XMStoreFloat4x4(&camera.Projection, ortho); + camera_transform.RotateRollPitchYaw(XMFLOAT3(-XM_PIDIV2, 0, 0)); + } + break; + case 5: + { + // top capture + XMMATRIX ortho = XMMatrixOrthographicOffCenterLH(-extents.x, extents.x, -extents.z, extents.z, -extents.y, extents.y); + XMStoreFloat4x4(&camera.Projection, ortho); + camera_transform.RotateRollPitchYaw(XMFLOAT3(XM_PIDIV2, 0, 0)); + } + break; + default: + break; + } + camera_transform.UpdateTransform(); + camera.UpdateCamera(&camera_transform); + camera.UpdateProjection(); + UpdateCameraCB(&camera, threadID); - // GetDevice()->BindResource(PS, material.GetBaseColorMap(), TEXSLOT_ONDEMAND0, threadID); - // GetDevice()->BindResource(PS, material.GetNormalMap(), TEXSLOT_ONDEMAND1, threadID); - // GetDevice()->BindResource(PS, material.GetSurfaceMap(), TEXSLOT_ONDEMAND2, threadID); + for (MeshComponent::MeshSubset& subset : mesh.subsets) + { + if (subset.subsetIndices.empty()) + { + continue; + } + MaterialComponent& material = *GetScene().materials.GetComponent(subset.materialID); - // GetDevice()->DrawIndexedInstanced((int)subset.subsetIndices.size(), 1, subset.indexBufferOffset, 0, 0, threadID); + GetDevice()->BindConstantBuffer(PS, material.constantBuffer, CB_GETBINDSLOT(MaterialCB), threadID); - // } + GetDevice()->BindResource(PS, material.GetBaseColorMap(), TEXSLOT_ONDEMAND0, threadID); + GetDevice()->BindResource(PS, material.GetNormalMap(), TEXSLOT_ONDEMAND1, threadID); + GetDevice()->BindResource(PS, material.GetSurfaceMap(), TEXSLOT_ONDEMAND2, threadID); - //} - //wiRenderer::GenerateMipChain(mesh.impostorTarget.GetTexture(), wiRenderer::MIPGENFILTER_LINEAR, threadID); + GetDevice()->DrawIndexedInstanced((int)subset.subsetIndices.size(), 1, subset.indexBufferOffset, 0, 0, threadID); - //mesh.impostorTarget.viewPort = savedViewPort; - //*cam = savedCam; - //UpdateCameraCB(cam, threadID); + } + + } + wiRenderer::GenerateMipChain(mesh.impostorTarget.GetTexture(), wiRenderer::MIPGENFILTER_LINEAR, threadID); + + mesh.impostorTarget.viewPort = savedViewPort; + UpdateCameraCB(getCamera(), threadID); } void wiRenderer::AddRenderableBox(const XMFLOAT4X4& boxMatrix, const XMFLOAT4& color) diff --git a/WickedEngine/wiSceneSystem.cpp b/WickedEngine/wiSceneSystem.cpp index ad71ec23b..0e3a6c581 100644 --- a/WickedEngine/wiSceneSystem.cpp +++ b/WickedEngine/wiSceneSystem.cpp @@ -426,6 +426,191 @@ namespace wiSceneSystem SAFE_DELETE_ARRAY(gpuIndexData); } + void MeshComponent::ComputeNormals(bool smooth) + { + // Start recalculating normals: + + if (smooth) + { + // Compute smooth surface normals: + + // 1.) Zero normals, they will be averaged later + for (size_t i = 0; i < vertices_FULL.size() - 1; i++) + { + vertices_FULL[i].nor = XMFLOAT4(0, 0, 0, 0); + } + + // 2.) Find identical vertices by POSITION, accumulate face normals + for (size_t i = 0; i < vertices_FULL.size() - 1; i++) + { + Vertex_FULL& v_search = vertices_FULL[i]; + + for (size_t ind = 0; ind < indices.size() / 3; ++ind) + { + uint32_t i0 = indices[ind * 3 + 0]; + uint32_t i1 = indices[ind * 3 + 1]; + uint32_t i2 = indices[ind * 3 + 2]; + + Vertex_FULL& v0 = vertices_FULL[i0]; + Vertex_FULL& v1 = vertices_FULL[i1]; + Vertex_FULL& v2 = vertices_FULL[i2]; + + bool match_pos0 = + fabs(v_search.pos.x - v0.pos.x) < FLT_EPSILON && + fabs(v_search.pos.y - v0.pos.y) < FLT_EPSILON && + fabs(v_search.pos.z - v0.pos.z) < FLT_EPSILON; + + bool match_pos1 = + fabs(v_search.pos.x - v1.pos.x) < FLT_EPSILON && + fabs(v_search.pos.y - v1.pos.y) < FLT_EPSILON && + fabs(v_search.pos.z - v1.pos.z) < FLT_EPSILON; + + bool match_pos2 = + fabs(v_search.pos.x - v2.pos.x) < FLT_EPSILON && + fabs(v_search.pos.y - v2.pos.y) < FLT_EPSILON && + fabs(v_search.pos.z - v2.pos.z) < FLT_EPSILON; + + if (match_pos0 || match_pos1 || match_pos2) + { + XMVECTOR U = XMLoadFloat4(&v2.pos) - XMLoadFloat4(&v0.pos); + XMVECTOR V = XMLoadFloat4(&v1.pos) - XMLoadFloat4(&v0.pos); + + XMVECTOR N = XMVector3Cross(U, V); + N = XMVector3Normalize(N); + + XMFLOAT3 normal; + XMStoreFloat3(&normal, N); + + v_search.nor.x += normal.x; + v_search.nor.y += normal.y; + v_search.nor.z += normal.z; + } + + } + } + + // 3.) Find unique vertices by POSITION and TEXCOORD and MATERIAL and remove duplicates + for (size_t i = 0; i < vertices_FULL.size() - 1; i++) + { + const Vertex_FULL& v0 = vertices_FULL[i]; + + for (size_t j = i + 1; j < vertices_FULL.size(); j++) + { + const Vertex_FULL& v1 = vertices_FULL[j]; + + bool unique_pos = + fabs(v0.pos.x - v1.pos.x) < FLT_EPSILON && + fabs(v0.pos.y - v1.pos.y) < FLT_EPSILON && + fabs(v0.pos.z - v1.pos.z) < FLT_EPSILON; + + bool unique_tex = + fabs(v0.tex.x - v1.tex.x) < FLT_EPSILON && + fabs(v0.tex.y - v1.tex.y) < FLT_EPSILON && + (int)v0.tex.z == (int)v1.tex.z; + + if (unique_pos && unique_tex) + { + for (size_t ind = 0; ind < indices.size(); ++ind) + { + if (indices[ind] == j) + { + indices[ind] = static_cast(i); + } + else if (indices[ind] > j && indices[ind] > 0) + { + indices[ind]--; + } + } + + vertices_FULL.erase(vertices_FULL.begin() + j); + } + + } + } + } + else + { + // Compute hard surface normals: + + std::vector newIndexBuffer; + std::vector newVertexBuffer; + + for (size_t face = 0; face < indices.size() / 3; face++) + { + uint32_t i0 = indices[face * 3 + 0]; + uint32_t i1 = indices[face * 3 + 1]; + uint32_t i2 = indices[face * 3 + 2]; + + Vertex_FULL& v0 = vertices_FULL[i0]; + Vertex_FULL& v1 = vertices_FULL[i1]; + Vertex_FULL& v2 = vertices_FULL[i2]; + + XMVECTOR U = XMLoadFloat4(&v2.pos) - XMLoadFloat4(&v0.pos); + XMVECTOR V = XMLoadFloat4(&v1.pos) - XMLoadFloat4(&v0.pos); + + XMVECTOR N = XMVector3Cross(U, V); + N = XMVector3Normalize(N); + + XMFLOAT3 normal; + XMStoreFloat3(&normal, N); + + v0.nor.x = normal.x; + v0.nor.y = normal.y; + v0.nor.z = normal.z; + + v1.nor.x = normal.x; + v1.nor.y = normal.y; + v1.nor.z = normal.z; + + v2.nor.x = normal.x; + v2.nor.y = normal.y; + v2.nor.z = normal.z; + + newVertexBuffer.push_back(v0); + newVertexBuffer.push_back(v1); + newVertexBuffer.push_back(v2); + + newIndexBuffer.push_back(static_cast(newIndexBuffer.size())); + newIndexBuffer.push_back(static_cast(newIndexBuffer.size())); + newIndexBuffer.push_back(static_cast(newIndexBuffer.size())); + } + + // For hard surface normals, we created a new mesh in the previous loop through faces, so swap data: + vertices_FULL = newVertexBuffer; + indices = newIndexBuffer; + } + + CreateRenderData(); + } + void MeshComponent::FlipCulling() + { + for (size_t face = 0; face < indices.size() / 3; face++) + { + uint32_t i0 = indices[face * 3 + 0]; + uint32_t i1 = indices[face * 3 + 1]; + uint32_t i2 = indices[face * 3 + 2]; + + indices[face * 3 + 0] = i0; + indices[face * 3 + 1] = i2; + indices[face * 3 + 2] = i1; + } + + CreateRenderData(); + } + void MeshComponent::FlipNormals() + { + for (size_t i = 0; i < vertices_FULL.size() - 1; i++) + { + Vertex_FULL& v0 = vertices_FULL[i]; + + v0.nor.x *= -1; + v0.nor.y *= -1; + v0.nor.z *= -1; + } + + CreateRenderData(); + } + void CameraComponent::CreatePerspective(float newWidth, float newHeight, float newNear, float newFar, float newFOV) { @@ -1094,6 +1279,26 @@ namespace wiSceneSystem return entity; } + wiECS::Entity Scene::Entity_CreateCamera( + const std::string& name, + float width, float height, float nearPlane, float farPlane, float fov + ) + { + Entity entity = CreateEntity(); + + owned_entities.insert(entity); + + names.Create(entity) = name; + + layers.Create(entity); + + transforms.Create(entity); + + CameraComponent& camera = cameras.Create(entity); + camera.CreatePerspective(width, height, nearPlane, farPlane, fov); + + return entity; + } void Scene::Component_Attach(Entity entity, Entity parent) { diff --git a/WickedEngine/wiSceneSystem.h b/WickedEngine/wiSceneSystem.h index 4232a7749..d35ddb3d8 100644 --- a/WickedEngine/wiSceneSystem.h +++ b/WickedEngine/wiSceneSystem.h @@ -20,7 +20,7 @@ namespace wiSceneSystem struct NameComponent { - char name[32]; + char name[128]; inline void operator=(const std::string& str) { strcpy_s(name, str.c_str()); } }; @@ -328,6 +328,9 @@ namespace wiSceneSystem inline bool IsDynamicVB() const { return dynamicVB; } void CreateRenderData(); + void ComputeNormals(bool smooth); + void FlipCulling(); + void FlipNormals(); }; struct CullableComponent @@ -719,6 +722,11 @@ namespace wiSceneSystem const std::string& textureName, const std::string& normalMapName = "" ); + // Helper function to create a camera entity: + wiECS::Entity Entity_CreateCamera( + const std::string& name, + float width, float height, float nearPlane = 0.01f, float farPlane = 1000.0f, float fov = XM_PIDIV4 + ); // Attaches an entity to a parent: void Component_Attach(wiECS::Entity entity, wiECS::Entity parent);