diff --git a/Editor/CameraWindow.cpp b/Editor/CameraWindow.cpp index 48f2fbee6..03e2dfe6a 100644 --- a/Editor/CameraWindow.cpp +++ b/Editor/CameraWindow.cpp @@ -50,8 +50,10 @@ CameraWindow::CameraWindow(wiGUI* gui) :GUI(gui) farPlaneSlider->SetPos(XMFLOAT2(x, y += inc)); farPlaneSlider->SetValue(wiRenderer::getCamera()->zFarP); farPlaneSlider->OnSlide([&](wiEventArgs args) { - wiRenderer::getCamera()->zFarP = args.fValue; - wiRenderer::getCamera()->UpdateProjection(); + Scene& scene = wiRenderer::GetScene(); + CameraComponent& camera = *scene.cameras.GetComponent(wiRenderer::getCameraID()); + camera.zFarP = args.fValue; + camera.UpdateProjection(); }); cameraWindow->AddWidget(farPlaneSlider); @@ -60,8 +62,10 @@ CameraWindow::CameraWindow(wiGUI* gui) :GUI(gui) nearPlaneSlider->SetPos(XMFLOAT2(x, y += inc)); nearPlaneSlider->SetValue(wiRenderer::getCamera()->zNearP); nearPlaneSlider->OnSlide([&](wiEventArgs args) { - wiRenderer::getCamera()->zNearP = args.fValue; - wiRenderer::getCamera()->UpdateProjection(); + Scene& scene = wiRenderer::GetScene(); + CameraComponent& camera = *scene.cameras.GetComponent(wiRenderer::getCameraID()); + camera.zNearP = args.fValue; + camera.UpdateProjection(); }); cameraWindow->AddWidget(nearPlaneSlider); @@ -69,8 +73,10 @@ CameraWindow::CameraWindow(wiGUI* gui) :GUI(gui) fovSlider->SetSize(XMFLOAT2(100, 30)); fovSlider->SetPos(XMFLOAT2(x, y += inc)); fovSlider->OnSlide([&](wiEventArgs args) { - wiRenderer::getCamera()->fov = args.fValue / 180.f * XM_PI; - wiRenderer::getCamera()->UpdateProjection(); + Scene& scene = wiRenderer::GetScene(); + CameraComponent& camera = *scene.cameras.GetComponent(wiRenderer::getCameraID()); + camera.fov = args.fValue / 180.f * XM_PI; + camera.UpdateProjection(); }); cameraWindow->AddWidget(fovSlider); diff --git a/Editor/ModelImporter_GLTF.cpp b/Editor/ModelImporter_GLTF.cpp index 596c508d6..21bec8f08 100644 --- a/Editor/ModelImporter_GLTF.cpp +++ b/Editor/ModelImporter_GLTF.cpp @@ -144,7 +144,19 @@ void RegisterTexture2D(tinygltf::Image *image) } } -void LoadNode(tinygltf::Node* node, Entity parent, Entity modelEntity, tinygltf::Model& gltfModel, const vector& materialArray, vector& meshArray, vector& armatureArray) + +struct LoaderState +{ + tinygltf::Model gltfModel; + Entity modelEntity; + unordered_map entityMap; + vector materialArray; + vector meshArray; + vector armatureArray; +}; + +// Recursively loads nodes and resolves hierarchy: +void LoadNode(tinygltf::Node* node, Entity parent, LoaderState& state) { if (node == nullptr) { @@ -153,7 +165,7 @@ void LoadNode(tinygltf::Node* node, Entity parent, Entity modelEntity, tinygltf: Scene& scene = wiRenderer::GetScene(); - ModelComponent& model = *scene.models.GetComponent(modelEntity); + ModelComponent& model = *scene.models.GetComponent(state.modelEntity); Entity entity = INVALID_ENTITY; @@ -162,229 +174,20 @@ void LoadNode(tinygltf::Node* node, Entity parent, Entity modelEntity, tinygltf: entity = scene.Entity_CreateObject(node->name); ObjectComponent& object = *scene.objects.GetComponent(entity); - if (node->mesh < meshArray.size()) + if (node->mesh < state.meshArray.size()) { - object.meshID = meshArray[node->mesh]; + object.meshID = state.meshArray[node->mesh]; + + if (node->skin >= 0) + { + MeshComponent& mesh = *scene.meshes.GetComponent(object.meshID); + assert(!mesh.vertices_BON.empty()); + mesh.armatureID = state.armatureArray[node->skin]; + } } 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; - //} - + assert(0); } } else if (node->camera >= 0) @@ -404,9 +207,11 @@ void LoadNode(tinygltf::Node* node, Entity parent, Entity modelEntity, tinygltf: if (entity == INVALID_ENTITY) { entity = CreateEntity(); + scene.owned_entities.insert(entity); scene.transforms.Create(entity); } + state.entityMap[node] = entity; TransformComponent& transform = *scene.transforms.GetComponent(entity); if (!node->scale.empty()) @@ -433,7 +238,7 @@ void LoadNode(tinygltf::Node* node, Entity parent, Entity modelEntity, tinygltf: { for (int child : node->children) { - LoadNode(&gltfModel.nodes[child], entity, modelEntity, gltfModel, materialArray, meshArray, armatureArray); + LoadNode(&state.gltfModel.nodes[child], entity, state); } } } @@ -446,45 +251,45 @@ Entity ImportModel_GLTF(const std::string& fileName) wiHelper::RemoveExtensionFromFileName(name); - tinygltf::Model gltfModel; tinygltf::TinyGLTF loader; std::string err; std::string warn; loader.SetImageLoader(tinygltf::LoadImageData, nullptr); loader.SetImageWriter(tinygltf::WriteImageData, nullptr); + + LoaderState state; bool ret; if (!extension.compare("GLTF")) { - ret = loader.LoadASCIIFromFile(&gltfModel, &err, &warn, fileName); + ret = loader.LoadASCIIFromFile(&state.gltfModel, &err, &warn, fileName); } else { - ret = loader.LoadBinaryFromFile(&gltfModel, &err, &warn, fileName); // for binary glTF(.glb) + ret = loader.LoadBinaryFromFile(&state.gltfModel, &err, &warn, fileName); // for binary glTF(.glb) } if (!ret) { wiHelper::messageBox(err, "GLTF error!"); return INVALID_ENTITY; } - vector materialArray; - vector armatureArray; - vector meshArray; - Scene& scene = wiRenderer::GetScene(); - Entity modelEntity = scene.Entity_CreateModel(name); - ModelComponent& model = *scene.models.GetComponent(modelEntity); - TransformComponent& model_transform = *scene.transforms.GetComponent(modelEntity); + state.modelEntity = scene.Entity_CreateModel(name); + ModelComponent& model = *scene.models.GetComponent(state.modelEntity); + TransformComponent& model_transform = *scene.transforms.GetComponent(state.modelEntity); model_transform.UpdateTransform(); // everything will be attached to this, so values need to be up to date - - for (auto& x : gltfModel.materials) + // Create materials: + for (auto& x : state.gltfModel.materials) { Entity materialEntity = scene.Entity_CreateMaterial(x.name); - materialArray.push_back(materialEntity); + + model.materials.insert(materialEntity); + state.materialArray.push_back(materialEntity); + MaterialComponent& material = *scene.materials.GetComponent(materialEntity); material.baseColor = XMFLOAT4(1, 1, 1, 1); @@ -507,18 +312,18 @@ Entity ImportModel_GLTF(const std::string& fileName) if (baseColorTexture != x.values.end()) { - auto& tex = gltfModel.textures[baseColorTexture->second.TextureIndex()]; - auto& img = gltfModel.images[tex.source]; + auto& tex = state.gltfModel.textures[baseColorTexture->second.TextureIndex()]; + auto& img = state.gltfModel.images[tex.source]; RegisterTexture2D(&img); material.baseColorMapName = img.name; } - else if(!gltfModel.images.empty()) + else if(!state.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; + RegisterTexture2D(&state.gltfModel.images[0]); + material.baseColorMapName = state.gltfModel.images[0].name; } tinygltf::Image* img_nor = nullptr; @@ -527,18 +332,18 @@ Entity ImportModel_GLTF(const std::string& fileName) if (normalTexture != x.additionalValues.end()) { - auto& tex = gltfModel.textures[normalTexture->second.TextureIndex()]; - img_nor = &gltfModel.images[tex.source]; + auto& tex = state.gltfModel.textures[normalTexture->second.TextureIndex()]; + img_nor = &state.gltfModel.images[tex.source]; } if (metallicRoughnessTexture != x.values.end()) { - auto& tex = gltfModel.textures[metallicRoughnessTexture->second.TextureIndex()]; - img_met_rough = &gltfModel.images[tex.source]; + auto& tex = state.gltfModel.textures[metallicRoughnessTexture->second.TextureIndex()]; + img_met_rough = &state.gltfModel.images[tex.source]; } if (emissiveTexture != x.additionalValues.end()) { - auto& tex = gltfModel.textures[emissiveTexture->second.TextureIndex()]; - img_emissive = &gltfModel.images[tex.source]; + auto& tex = state.gltfModel.textures[emissiveTexture->second.TextureIndex()]; + img_emissive = &state.gltfModel.images[tex.source]; } // Now we will begin interleaving texture data to match engine layout: @@ -699,270 +504,397 @@ Entity ImportModel_GLTF(const std::string& fileName) } - //for(auto& skin : gltfModel.skins) - //{ - // Armature* armature = new Armature(skin.name); - // model->armatures.insert(armature); - - // armatureArray.push_back(armature); - - // const tinygltf::Node& skeleton_node = gltfModel.nodes[skin.skeleton]; - - // const size_t jointCount = skin.joints.size(); - - // armature->boneCollection.resize(jointCount); - - // // Create bone collection: - // for (size_t i = 0; i < jointCount; ++i) - // { - // int jointIndex = skin.joints[i]; - // const tinygltf::Node& joint_node = gltfModel.nodes[jointIndex]; - - // Bone* bone = new Bone(joint_node.name); - // if (bone->name.empty()) - // { - // // GLTF might not contain bone names... - // stringstream ss(""); - // ss << "Bone_" << i; - // bone->name = ss.str(); - // } - - // armature->boneCollection[i] = bone; - - // if (!joint_node.scale.empty()) - // { - // bone->scale_rest = XMFLOAT3((float)joint_node.scale[0], (float)joint_node.scale[1], (float)joint_node.scale[2]); - // } - // if (!joint_node.rotation.empty()) - // { - // bone->rotation_rest = XMFLOAT4((float)joint_node.rotation[0], (float)joint_node.rotation[1], (float)joint_node.rotation[2], (float)joint_node.rotation[3]); - // } - // if (!joint_node.translation.empty()) - // { - // bone->translation_rest = XMFLOAT3((float)joint_node.translation[0], (float)joint_node.translation[1], (float)joint_node.translation[2]); - // } - - // XMVECTOR s = XMLoadFloat3(&bone->scale_rest); - // XMVECTOR r = XMLoadFloat4(&bone->rotation_rest); - // XMVECTOR t = XMLoadFloat3(&bone->translation_rest); - // XMMATRIX w = - // XMMatrixScalingFromVector(s)* - // XMMatrixRotationQuaternion(r)* - // XMMatrixTranslationFromVector(t) - // ; - // XMStoreFloat4x4(&bone->world_rest, w); - // } - - // // Create bone name hierarchy: - // for (size_t i = 0; i < jointCount; ++i) - // { - // int jointIndex = skin.joints[i]; - // const tinygltf::Node& joint_node = gltfModel.nodes[jointIndex]; - - // for (int childJointIndex : joint_node.children) - // { - // for (size_t j = 0; j < jointCount; ++j) - // { - // if (skin.joints[j] == childJointIndex) - // { - // armature->boneCollection[j]->parentName = armature->boneCollection[i]->name; - // break; - // } - // } - // } - // } - - // if (transform_to_LH) - // { - // XMStoreFloat4x4(&armature->skinningRemap, XMMatrixScaling(1, 1, -1)); - // } - - // // Final hierarchy and extra matrices created here: - // armature->CreateFamily(); - - //} - - const tinygltf::Scene &gltfScene = gltfModel.scenes[gltfModel.defaultScene]; - for (size_t i = 0; i < gltfScene.nodes.size(); i++) + // Create meshes: + for (auto& x : state.gltfModel.meshes) { - LoadNode(&gltfModel.nodes[gltfScene.nodes[i]], INVALID_ENTITY, modelEntity, gltfModel, materialArray, meshArray, armatureArray); + Entity meshEntity = scene.Entity_CreateMesh(x.name); + + model.meshes.insert(meshEntity); + state.meshArray.push_back(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 = state.gltfModel.accessors[prim.indices]; + const tinygltf::BufferView& bufferView = state.gltfModel.bufferViews[accessor.bufferView]; + const tinygltf::Buffer& buffer = state.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 = state.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 = state.gltfModel.accessors[attr_data]; + const tinygltf::BufferView& bufferView = state.gltfModel.bufferViews[accessor.bufferView]; + const tinygltf::Buffer& buffer = state.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); } - //int animID = 0; - //for (auto& anim : gltfModel.animations) - //{ - // if (armatureArray.empty()) - // { - // break; - // } - // Armature* armature = armatureArray[0]; + // Create armatures: + for (auto& skin : state.gltfModel.skins) + { + Entity armatureEntity = CreateEntity(); + scene.owned_entities.insert(armatureEntity); + scene.names.Create(armatureEntity) = skin.name; + scene.layers.Create(armatureEntity); + TransformComponent& transform = scene.transforms.Create(armatureEntity); + ArmatureComponent& armature = scene.armatures.Create(armatureEntity); - // for (Bone* bone : armature->boneCollection) - // { - // bone->actionFrames.push_back(ActionFrames()); - // } + model.armatures.insert(armatureEntity); - // Action action; - // action.name = anim.name; - // if (action.name.empty()) - // { - // stringstream ss(""); - // ss << "Action_" << animID++; - // action.name = ss.str(); - // } + state.armatureArray.push_back(armatureEntity); - // for (auto& channel : anim.channels) - // { - // const tinygltf::Node& target_node = gltfModel.nodes[channel.target_node]; - // const tinygltf::AnimationSampler& sam = anim.samplers[channel.sampler]; + if (transform_to_LH) + { + XMStoreFloat4x4(&armature.skinningRemap, XMMatrixScaling(1, 1, -1)); + } + } - // Bone* bone = nullptr; + // Create transform hierarchy, assign objects, meshes, armatures, cameras: + const tinygltf::Scene &gltfScene = state.gltfModel.scenes[state.gltfModel.defaultScene]; + for (size_t i = 0; i < gltfScene.nodes.size(); i++) + { + LoadNode(&state.gltfModel.nodes[gltfScene.nodes[i]], INVALID_ENTITY, state); + } - // // Search for the armature + bone this animation belongs to: - // { - // const auto& skin = gltfModel.skins[0]; + // Create bone components (transforms for them are already in place): + int i = 0; + for (auto& skin : state.gltfModel.skins) + { + Entity entity = state.armatureArray[i++]; + ArmatureComponent& armature = *scene.armatures.GetComponent(entity); - // const size_t jointCount = skin.joints.size(); - // assert(armature->boneCollection.size() == jointCount); + const size_t jointCount = skin.joints.size(); - // for (size_t i = 0; i < jointCount; ++i) - // { - // int jointIndex = skin.joints[i]; + // Create bone collection: + for (size_t i = 0; i < jointCount; ++i) + { + int jointIndex = skin.joints[i]; + const tinygltf::Node& joint_node = state.gltfModel.nodes[jointIndex]; - // if (jointIndex == channel.target_node) - // { - // bone = armature->boneCollection[i]; - // break; - // } - // } - // } + Entity boneEntity = state.entityMap[&joint_node]; + BoneComponent& bone = scene.bones.Create(boneEntity); - // if (bone == nullptr) - // { - // assert(0 && "Corresponding bone not found!"); - // continue; - // } + armature.boneCollection.push_back(boneEntity); + + TransformComponent& bone_transform = *scene.transforms.GetComponent(boneEntity); + XMMATRIX bind = XMLoadFloat4x4(&bone_transform.world); + bind = XMMatrixInverse(nullptr, bind); + XMStoreFloat4x4(&bone.inverseBindPoseMatrix, bind); + } + } + + int animID = 0; + for (auto& anim : state.gltfModel.animations) + { + Entity entity = CreateEntity(); + scene.owned_entities.insert(entity); + scene.names.Create(entity) = anim.name; + AnimationComponent& animationcomponent = scene.animations.Create(entity); + + for (auto& channel : anim.channels) + { + const tinygltf::AnimationSampler& sam = anim.samplers[channel.sampler]; + + animationcomponent.channels.push_back(AnimationComponent::AnimationChannel()); + animationcomponent.channels.back().target = state.entityMap[&state.gltfModel.nodes[channel.target_node]]; + + // AnimationSampler input = keyframe times + { + const tinygltf::Accessor& accessor = state.gltfModel.accessors[sam.input]; + const tinygltf::BufferView& bufferView = state.gltfModel.bufferViews[accessor.bufferView]; + const tinygltf::Buffer& buffer = state.gltfModel.buffers[bufferView.buffer]; + + assert(accessor.componentType == TINYGLTF_COMPONENT_TYPE_FLOAT); + + int stride = accessor.ByteStride(bufferView); + size_t count = accessor.count; + + animationcomponent.channels.back().keyframe_times.resize(count); + + const unsigned char* data = buffer.data.data() + accessor.byteOffset + bufferView.byteOffset; + + assert(stride == 4); + for (size_t i = 0; i < count; ++i) + { + animationcomponent.channels.back().keyframe_times[i] = ((float*)data)[i]; + } + + } + + // AnimationSampler output = keyframe data + { + const tinygltf::Accessor& accessor = state.gltfModel.accessors[sam.output]; + const tinygltf::BufferView& bufferView = state.gltfModel.bufferViews[accessor.bufferView]; + const tinygltf::Buffer& buffer = state.gltfModel.buffers[bufferView.buffer]; + + int stride = accessor.ByteStride(bufferView); + size_t count = accessor.count; + + //// Unfortunately, GLTF stores absolute values for animation nodes, but the engine needs relative + //// Absolute = animation * rest (so the rest matrix is baked into animation, this can't be blended like we do now) + //// Relative = animation (so we can blend all animation tracks however we want, then post multiply with the rest matrix after blending) + //const XMMATRIX invRest = XMMatrixInverse(nullptr, XMLoadFloat4x4(&bone->world_rest)); + + const unsigned char* data = buffer.data.data() + accessor.byteOffset + bufferView.byteOffset; + + if (!channel.target_path.compare("scale")) + { + animationcomponent.channels.back().type = AnimationComponent::AnimationChannel::Type::SCALE; + animationcomponent.channels.back().keyframe_data.resize(count * 3); + + assert(stride == sizeof(XMFLOAT3)); + for (size_t i = 0; i < count; ++i) + { + const XMFLOAT3& sca = ((XMFLOAT3*)data)[i]; + ((XMFLOAT3*)animationcomponent.channels.back().keyframe_data.data())[i] = sca; + + //// Remove rest matrix from animation track: + //XMMATRIX mat = XMMatrixScalingFromVector(XMLoadFloat3(&sca)); + //mat = mat * invRest; + //XMVECTOR s, r, t; + //XMMatrixDecompose(&s, &r, &t, mat); + + //XMStoreFloat3(&((XMFLOAT3*)animationcomponent.channels.back().keyframe_data.data())[i], s); + } + } + else if (!channel.target_path.compare("rotation")) + { + animationcomponent.channels.back().type = AnimationComponent::AnimationChannel::Type::ROTATION; + animationcomponent.channels.back().keyframe_data.resize(count * 4); + + assert(stride == sizeof(XMFLOAT4)); + for (size_t i = 0; i < count; ++i) + { + const XMFLOAT4& rot = ((XMFLOAT4*)data)[i]; + ((XMFLOAT4*)animationcomponent.channels.back().keyframe_data.data())[i] = rot; + + //// Remove rest matrix from animation track: + //XMMATRIX mat = XMMatrixRotationQuaternion(XMLoadFloat4(&rot)); + //mat = mat * invRest; + //XMVECTOR s, r, t; + //XMMatrixDecompose(&s, &r, &t, mat); + + //XMStoreFloat4(&((XMFLOAT4*)animationcomponent.channels.back().keyframe_data.data())[i], r); + } + } + else if (!channel.target_path.compare("translation")) + { + animationcomponent.channels.back().type = AnimationComponent::AnimationChannel::Type::TRANSLATION; + animationcomponent.channels.back().keyframe_data.resize(count * 3); + + assert(stride == sizeof(XMFLOAT3)); + for (size_t i = 0; i < count; ++i) + { + const XMFLOAT3& tra = ((XMFLOAT3*)data)[i]; + ((XMFLOAT3*)animationcomponent.channels.back().keyframe_data.data())[i] = tra; + + //// Remove rest matrix from animation track: + //XMMATRIX mat = XMMatrixTranslationFromVector(XMLoadFloat3(&tra)); + //mat = mat * invRest; + //XMVECTOR s, r, t; + //XMMatrixDecompose(&s, &r, &t, mat); + + //XMStoreFloat3(&((XMFLOAT3*)animationcomponent.channels.back().keyframe_data.data())[i], t); + } + } + else + { + assert(0); + } + } - // vector keyframes; + } - // // AnimationSampler input = keyframe times - // { - // const tinygltf::Accessor& accessor = gltfModel.accessors[sam.input]; - // const tinygltf::BufferView& bufferView = gltfModel.bufferViews[accessor.bufferView]; - // const tinygltf::Buffer& buffer = gltfModel.buffers[bufferView.buffer]; + } - // assert(accessor.componentType == TINYGLTF_COMPONENT_TYPE_FLOAT); - - // int stride = accessor.ByteStride(bufferView); - // size_t count = accessor.count; - - // keyframes.resize(count); - - // const unsigned char* data = buffer.data.data() + accessor.byteOffset + bufferView.byteOffset; - - // int firstFrame = INT_MAX; - - // assert(stride == 4); - // for (size_t i = 0; i < count; ++i) - // { - // keyframes[i].frameI = (int)(((float*)data)[i] * 60); // !!! converting from time-base to frame-based !!! - - // action.frameCount = max(action.frameCount, keyframes[i].frameI); - // firstFrame = min(firstFrame, keyframes[i].frameI); - // } - - // // Cut out the empty part of the animation at the beginning: - // firstFrame = min(firstFrame, action.frameCount); - // for (size_t i = 0; i < count; ++i) - // { - // keyframes[i].frameI -= firstFrame; - // } - // action.frameCount -= firstFrame; - - // } - - // // AnimationSampler output = keyframe data - // { - // const tinygltf::Accessor& accessor = gltfModel.accessors[sam.output]; - // 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; - - // // Unfortunately, GLTF stores absolute values for animation nodes, but the engine needs relative - // // Absolute = animation * rest (so the rest matrix is baked into animation, this can't be blended like we do now) - // // Relative = animation (so we can blend all animation tracks however we want, then post multiply with the rest matrix after blending) - // const XMMATRIX invRest = XMMatrixInverse(nullptr, XMLoadFloat4x4(&bone->world_rest)); - - // const unsigned char* data = buffer.data.data() + accessor.byteOffset + bufferView.byteOffset; - - // if (!channel.target_path.compare("scale")) - // { - // assert(stride == sizeof(XMFLOAT3)); - // for (size_t i = 0; i < count; ++i) - // { - // const XMFLOAT3& sca = ((XMFLOAT3*)data)[i]; - // //keyframes[i].data = XMFLOAT4(sca.x, sca.y, sca.z, 0); - - // // Remove rest matrix from animation track: - // XMMATRIX mat = XMMatrixScalingFromVector(XMLoadFloat3(&sca)); - // mat = mat * invRest; - // XMVECTOR s, r, t; - // XMMatrixDecompose(&s, &r, &t, mat); - // XMStoreFloat4(&keyframes[i].data, s); - // } - // bone->actionFrames.back().keyframesSca.insert(bone->actionFrames.back().keyframesSca.end(), keyframes.begin(), keyframes.end()); - // } - // else if (!channel.target_path.compare("rotation")) - // { - // assert(stride == sizeof(XMFLOAT4)); - // for (size_t i = 0; i < count; ++i) - // { - // const XMFLOAT4& rot = ((XMFLOAT4*)data)[i]; - // //keyframes[i].data = rot; - - // // Remove rest matrix from animation track: - // XMMATRIX mat = XMMatrixRotationQuaternion(XMLoadFloat4(&rot)); - // mat = mat * invRest; - // XMVECTOR s, r, t; - // XMMatrixDecompose(&s, &r, &t, mat); - // XMStoreFloat4(&keyframes[i].data, r); - // } - // bone->actionFrames.back().keyframesRot.insert(bone->actionFrames.back().keyframesRot.end(), keyframes.begin(), keyframes.end()); - // } - // else if (!channel.target_path.compare("translation")) - // { - // assert(stride == sizeof(XMFLOAT3)); - // for (size_t i = 0; i < count; ++i) - // { - // const XMFLOAT3& tra = ((XMFLOAT3*)data)[i]; - // //keyframes[i].data = XMFLOAT4(tra.x, tra.y, tra.z, 1); - - // // Remove rest matrix from animation track: - // XMMATRIX mat = XMMatrixTranslationFromVector(XMLoadFloat3(&tra)); - // mat = mat * invRest; - // XMVECTOR s, r, t; - // XMMatrixDecompose(&s, &r, &t, mat); - // XMStoreFloat4(&keyframes[i].data, t); - // } - // bone->actionFrames.back().keyframesPos.insert(bone->actionFrames.back().keyframesPos.end(), keyframes.begin(), keyframes.end()); - // } - // else - // { - // assert(0); - // } - // } - - - // } - - // armature->actions.push_back(action); - - //} - - //model->FinishLoading(); - - return modelEntity; + return state.modelEntity; } diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 7283aa849..b9a828ac0 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -3172,12 +3172,12 @@ void wiRenderer::UpdateRenderData(GRAPHICSTHREAD threadID) SubresourceData InitData; InitData.pSysMem = &materialGPUData; - material.constantBuffer = new GPUBuffer; - device->CreateBuffer(&desc, &InitData, material.constantBuffer); + material.constantBuffer.reset(new GPUBuffer); + device->CreateBuffer(&desc, &InitData, material.constantBuffer.get()); } else { - device->UpdateBuffer(material.constantBuffer, &materialGPUData, threadID); + device->UpdateBuffer(material.constantBuffer.get(), &materialGPUData, threadID); } } @@ -3402,116 +3402,116 @@ void wiRenderer::UpdateRenderData(GRAPHICSTHREAD threadID) ManageDecalAtlas(threadID); - //wiProfiler::GetInstance().BeginRange("Skinning", wiProfiler::DOMAIN_GPU, threadID); - //GetDevice()->EventBegin("Skinning", threadID); - //{ - // bool streamOutSetUp = false; - // CSTYPES lastCS = CSTYPE_SKINNING_LDS; + wiProfiler::GetInstance().BeginRange("Skinning", wiProfiler::DOMAIN_GPU, threadID); + GetDevice()->EventBegin("Skinning", threadID); + { + bool streamOutSetUp = false; + CSTYPES lastCS = CSTYPE_SKINNING_LDS; - // for (Model* model : GetScene().models) - // { - // // Update material constant buffers: - // MaterialCB materialGPUData; - // for (auto& it : model->materials) - // { - // Material* material = it.second; - // materialGPUData.Create(*material); - // // These will probably not change every time so only issue a GPU memory update if it is necessary: - // if (memcmp(&material->gpuData, &materialGPUData, sizeof(MaterialCB)) != 0) - // { - // material->gpuData = materialGPUData; - // GetDevice()->UpdateBuffer(&material->constantBuffer, &materialGPUData, threadID); - // } - // } + for (size_t i = 0; i < scene.meshes.GetCount(); ++i) + { + MeshComponent& mesh = scene.meshes[i]; - // // Skinning: - // for (auto& iter = model->meshes.begin(); iter != model->meshes.end(); ++iter) - // { - // Mesh* mesh = iter->second; + if (mesh.IsSkinned()) + { + ArmatureComponent& armature = *scene.armatures.GetComponent(mesh.armatureID); - // if (mesh->hasArmature() && !mesh->hasDynamicVB() && mesh->renderable && !mesh->vertices_POS.empty() - // && mesh->streamoutBuffer_POS != nullptr && mesh->vertexBuffer_POS != nullptr) - // { - // Armature* armature = mesh->armature; + if (armature.boneBuffer == nullptr) + { + armature.boneData.resize(armature.boneCollection.size()); - // if (!streamOutSetUp) - // { - // // Set up skinning shader - // streamOutSetUp = true; - // GPUBuffer* vbs[] = { - // nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr - // }; - // const UINT strides[] = { - // 0,0,0,0,0,0,0,0 - // }; - // GetDevice()->BindVertexBuffers(vbs, 0, ARRAYSIZE(vbs), strides, nullptr, threadID); - // GetDevice()->BindComputePSO(CPSO[CSTYPE_SKINNING_LDS], threadID); - // } + GPUBufferDesc bd; + bd.Usage = USAGE_DYNAMIC; + bd.CPUAccessFlags = CPU_ACCESS_WRITE; - // CSTYPES targetCS = CSTYPE_SKINNING_LDS; + bd.ByteWidth = sizeof(ArmatureComponent::ShaderBoneType) * (UINT)armature.boneCollection.size(); + bd.BindFlags = BIND_SHADER_RESOURCE; + bd.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED; + bd.StructureByteStride = sizeof(ArmatureComponent::ShaderBoneType); - // if (!GetLDSSkinningEnabled() || armature->boneCollection.size() > SKINNING_COMPUTE_THREADCOUNT) - // { - // // If we have more bones that can fit into LDS, we switch to a skinning shader which loads from device memory: - // targetCS = CSTYPE_SKINNING; - // } + armature.boneBuffer.reset(new GPUBuffer); + HRESULT hr = wiRenderer::GetDevice()->CreateBuffer(&bd, nullptr, armature.boneBuffer.get()); + assert(SUCCEEDED(hr)); + } - // if (targetCS != lastCS) - // { - // lastCS = targetCS; - // GetDevice()->BindComputePSO(CPSO[targetCS], threadID); - // } + if (!streamOutSetUp) + { + // Set up skinning shader + streamOutSetUp = true; + GPUBuffer* vbs[] = { + nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr + }; + const UINT strides[] = { + 0,0,0,0,0,0,0,0 + }; + GetDevice()->BindVertexBuffers(vbs, 0, ARRAYSIZE(vbs), strides, nullptr, threadID); + GetDevice()->BindComputePSO(CPSO[CSTYPE_SKINNING_LDS], threadID); + } - // // Upload bones for skinning to shader - // for (unsigned int k = 0; k < armature->boneCollection.size(); k++) - // { - // armature->boneData[k].Create(armature->boneCollection[k]->boneRelativity); - // } - // GetDevice()->UpdateBuffer(&armature->boneBuffer, armature->boneData.data(), threadID, (int)(sizeof(Armature::ShaderBoneType) * armature->boneCollection.size())); - // GetDevice()->BindResource(CS, &armature->boneBuffer, SKINNINGSLOT_IN_BONEBUFFER, threadID); + CSTYPES targetCS = CSTYPE_SKINNING_LDS; - // // Do the skinning - // GPUResource* vbs[] = { - // mesh->vertexBuffer_POS, - // mesh->vertexBuffer_BON, - // }; - // GPUResource* sos[] = { - // mesh->streamoutBuffer_POS, - // mesh->streamoutBuffer_PRE, - // }; + if (!GetLDSSkinningEnabled() || armature.skinningMatrices.size() > SKINNING_COMPUTE_THREADCOUNT) + { + // If we have more bones that can fit into LDS, we switch to a skinning shader which loads from device memory: + targetCS = CSTYPE_SKINNING; + } - // GetDevice()->BindResources(CS, vbs, SKINNINGSLOT_IN_VERTEX_POS, ARRAYSIZE(vbs), threadID); - // GetDevice()->BindUAVs(CS, sos, 0, ARRAYSIZE(sos), threadID); + if (targetCS != lastCS) + { + lastCS = targetCS; + GetDevice()->BindComputePSO(CPSO[targetCS], threadID); + } - // GetDevice()->Dispatch((UINT)ceilf((float)mesh->vertices_POS.size() / SKINNING_COMPUTE_THREADCOUNT), 1, 1, threadID); - // GetDevice()->UAVBarrier(sos, ARRAYSIZE(sos), threadID); // todo: defer - // //GetDevice()->TransitionBarrier(sos, ARRAYSIZE(sos), RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, threadID); - // } - // else if (mesh->hasDynamicVB()) - // { - // // Upload CPU skinned vertex buffer (Soft body VB) - // size_t size_pos = sizeof(MeshComponent::Vertex_POS)*mesh->vertices_Transformed_POS.size(); - // size_t size_pre = sizeof(MeshComponent::Vertex_POS)*mesh->vertices_Transformed_PRE.size(); - // UINT offset; - // void* vertexData = GetDevice()->AllocateFromRingBuffer(dynamicVertexBufferPool, size_pos + size_pre, offset, threadID); - // mesh->bufferOffset_POS = offset; - // mesh->bufferOffset_PRE = offset + (UINT)size_pos; - // memcpy(vertexData, mesh->vertices_Transformed_POS.data(), size_pos); - // memcpy(reinterpret_cast(reinterpret_cast(vertexData) + size_pos), mesh->vertices_Transformed_PRE.data(), size_pre); - // GetDevice()->InvalidateBufferAccess(dynamicVertexBufferPool, threadID); - // } - // } - // } + // Upload bones for skinning to shader + for (size_t k = 0; k < armature.skinningMatrices.size(); k++) + { + armature.boneData[k].Create(armature.skinningMatrices[k]); + } + GetDevice()->UpdateBuffer(armature.boneBuffer.get(), armature.boneData.data(), threadID, (int)(sizeof(ArmatureComponent::ShaderBoneType) * armature.boneData.size())); + GetDevice()->BindResource(CS, armature.boneBuffer.get(), SKINNINGSLOT_IN_BONEBUFFER, threadID); - // if (streamOutSetUp) - // { - // GetDevice()->UnbindUAVs(0, 2, threadID); - // GetDevice()->UnbindResources(SKINNINGSLOT_IN_VERTEX_POS, 2, threadID); - // } + // Do the skinning + GPUResource* vbs[] = { + mesh.vertexBuffer_POS.get(), + mesh.vertexBuffer_BON.get(), + }; + GPUResource* sos[] = { + mesh.streamoutBuffer_POS.get(), + mesh.streamoutBuffer_PRE.get(), + }; - //} - //GetDevice()->EventEnd(threadID); - //wiProfiler::GetInstance().EndRange(threadID); // skinning + GetDevice()->BindResources(CS, vbs, SKINNINGSLOT_IN_VERTEX_POS, ARRAYSIZE(vbs), threadID); + GetDevice()->BindUAVs(CS, sos, 0, ARRAYSIZE(sos), threadID); + + GetDevice()->Dispatch((UINT)ceilf((float)mesh.vertices_POS.size() / SKINNING_COMPUTE_THREADCOUNT), 1, 1, threadID); + GetDevice()->UAVBarrier(sos, ARRAYSIZE(sos), threadID); // todo: defer + //GetDevice()->TransitionBarrier(sos, ARRAYSIZE(sos), RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, threadID); + } + else if (mesh.IsDynamicVB()) + { + // Upload CPU skinned vertex buffer (Soft body VB) + size_t size_pos = sizeof(MeshComponent::Vertex_POS) * mesh.vertices_Transformed_POS.size(); + size_t size_pre = sizeof(MeshComponent::Vertex_POS) * mesh.vertices_Transformed_PRE.size(); + UINT offset; + void* vertexData = GetDevice()->AllocateFromRingBuffer(dynamicVertexBufferPool, size_pos + size_pre, offset, threadID); + mesh.bufferOffset_POS = offset; + mesh.bufferOffset_PRE = offset + (UINT)size_pos; + memcpy(vertexData, mesh.vertices_Transformed_POS.data(), size_pos); + memcpy(reinterpret_cast(reinterpret_cast(vertexData) + size_pos), mesh.vertices_Transformed_PRE.data(), size_pre); + GetDevice()->InvalidateBufferAccess(dynamicVertexBufferPool, threadID); + } + + } + + if (streamOutSetUp) + { + GetDevice()->UnbindUAVs(0, 2, threadID); + GetDevice()->UnbindResources(SKINNINGSLOT_IN_VERTEX_POS, 2, threadID); + } + + } + GetDevice()->EventEnd(threadID); + wiProfiler::GetInstance().EndRange(threadID); // skinning //// Particle system simulation/sorting/culling: //for (auto& x : emitterSystems) @@ -3725,72 +3725,73 @@ void wiRenderer::DrawDebugWorld(CameraComponent* camera, GRAPHICSTHREAD threadID device->EventBegin("DrawDebugWorld", threadID); - //if (debugBoneLines) - //{ - // device->EventBegin("DebugBoneLines", threadID); + if (debugBoneLines) + { + device->EventBegin("DebugBoneLines", threadID); - // device->BindGraphicsPSO(PSO_debug[DEBUGRENDERING_LINES], threadID); + device->BindGraphicsPSO(PSO_debug[DEBUGRENDERING_LINES], threadID); - // MiscCB sb; - // sb.mTransform = XMMatrixTranspose(camera->GetViewProjection()); - // sb.mColor = XMFLOAT4(1, 1, 1, 1); - // device->UpdateBuffer(constantBuffers[CBTYPE_MISC], &sb, threadID); + MiscCB sb; + sb.mTransform = XMMatrixTranspose(camera->GetViewProjection()); + sb.mColor = XMFLOAT4(1, 1, 1, 1); + device->UpdateBuffer(constantBuffers[CBTYPE_MISC], &sb, threadID); - // for (auto& model : GetScene().models) - // { - // for (auto& armature : model->armatures) - // { - // if (armature->boneCollection.empty()) - // { - // continue; - // } + for (size_t i = 0; i < scene.armatures.GetCount(); ++i) + { + const ArmatureComponent& armature = scene.armatures[i]; - // struct LineSegment - // { - // XMFLOAT4 a, colorA, b, colorB; - // }; - // UINT offset; - // void* mem = device->AllocateFromRingBuffer(dynamicVertexBufferPool, sizeof(LineSegment) * armature->boneCollection.size(), offset, threadID); + if (armature.boneCollection.empty()) + { + continue; + } - // int i = 0; - // for (auto& bone : armature->boneCollection) - // { - // XMMATRIX world = XMLoadFloat4x4(&bone->world); - // XMVECTOR a = XMVectorSet(0, 0, 0, 1); - // XMVECTOR b = XMVectorSet(0, 0, bone->length, 1); + struct LineSegment + { + XMFLOAT4 a, colorA, b, colorB; + }; + UINT offset; + void* mem = device->AllocateFromRingBuffer(dynamicVertexBufferPool, sizeof(LineSegment) * armature.boneCollection.size(), offset, threadID); - // a = XMVector4Transform(a, world); - // b = XMVector4Transform(b, world); + int j = 0; + for (Entity entity : armature.boneCollection) + { + const TransformComponent& transform = *scene.transforms.GetComponent(entity); + + XMMATRIX world = XMLoadFloat4x4(&transform.world); + XMVECTOR a = XMVectorSet(0, 0, 0, 1); + XMVECTOR b = XMVectorSet(0, 0, 1, 1); + + a = XMVector4Transform(a, world); + b = XMVector4Transform(b, world); - // LineSegment segment; - // XMStoreFloat4(&segment.a, a); - // XMStoreFloat4(&segment.b, b); + LineSegment segment; + XMStoreFloat4(&segment.a, a); + XMStoreFloat4(&segment.b, b); - // memcpy((void*)((size_t)mem + i * sizeof(LineSegment)), &segment, sizeof(LineSegment)); - // i++; - // } + memcpy((void*)((size_t)mem + j * sizeof(LineSegment)), &segment, sizeof(LineSegment)); + j++; + } - // device->InvalidateBufferAccess(dynamicVertexBufferPool, threadID); + device->InvalidateBufferAccess(dynamicVertexBufferPool, threadID); - // GPUBuffer* vbs[] = { - // dynamicVertexBufferPool, - // }; - // const UINT strides[] = { - // sizeof(XMFLOAT4) + sizeof(XMFLOAT4), - // }; - // const UINT offsets[] = { - // offset, - // }; - // device->BindVertexBuffers(vbs, 0, ARRAYSIZE(vbs), strides, offsets, threadID); + GPUBuffer* vbs[] = { + dynamicVertexBufferPool, + }; + const UINT strides[] = { + sizeof(XMFLOAT4) + sizeof(XMFLOAT4), + }; + const UINT offsets[] = { + offset, + }; + device->BindVertexBuffers(vbs, 0, ARRAYSIZE(vbs), strides, offsets, threadID); - // device->Draw(2 * i, 0, threadID); + device->Draw(2 * j, 0, threadID); - // } - // } + } - // device->EventEnd(threadID); - //} + device->EventEnd(threadID); + } if (!renderableLines.empty()) { @@ -5212,7 +5213,7 @@ void wiRenderer::RenderMeshes(const XMFLOAT3& eye, const CulledCollection& culle if (k < 1) continue; - device->BindIndexBuffer(mesh.indexBuffer, mesh.GetIndexFormat(), 0, threadID); + device->BindIndexBuffer(mesh.indexBuffer.get(), mesh.GetIndexFormat(), 0, threadID); enum class BOUNDVERTEXBUFFERTYPE { @@ -5306,7 +5307,7 @@ void wiRenderer::RenderMeshes(const XMFLOAT3& eye, const CulledCollection& culle case BOUNDVERTEXBUFFERTYPE::POSITION: { GPUBuffer* vbs[] = { - dynamicVB ? dynamicVertexBufferPool : (mesh.streamoutBuffer_POS != nullptr ? mesh.streamoutBuffer_POS : mesh.vertexBuffer_POS), + dynamicVB ? dynamicVertexBufferPool : (mesh.streamoutBuffer_POS.get() != nullptr ? mesh.streamoutBuffer_POS.get() : mesh.vertexBuffer_POS.get()), dynamicVertexBufferPool }; UINT strides[] = { @@ -5323,8 +5324,8 @@ void wiRenderer::RenderMeshes(const XMFLOAT3& eye, const CulledCollection& culle case BOUNDVERTEXBUFFERTYPE::POSITION_TEXCOORD: { GPUBuffer* vbs[] = { - dynamicVB ? dynamicVertexBufferPool : (mesh.streamoutBuffer_POS != nullptr ? mesh.streamoutBuffer_POS : mesh.vertexBuffer_POS), - mesh.vertexBuffer_TEX, + dynamicVB ? dynamicVertexBufferPool : (mesh.streamoutBuffer_POS.get() != nullptr ? mesh.streamoutBuffer_POS.get() : mesh.vertexBuffer_POS.get()), + mesh.vertexBuffer_TEX.get(), dynamicVertexBufferPool }; UINT strides[] = { @@ -5343,9 +5344,9 @@ void wiRenderer::RenderMeshes(const XMFLOAT3& eye, const CulledCollection& culle case BOUNDVERTEXBUFFERTYPE::EVERYTHING: { GPUBuffer* vbs[] = { - dynamicVB ? dynamicVertexBufferPool : (mesh.streamoutBuffer_POS != nullptr ? mesh.streamoutBuffer_POS : mesh.vertexBuffer_POS), - mesh.vertexBuffer_TEX, - dynamicVB ? dynamicVertexBufferPool : (mesh.streamoutBuffer_PRE != nullptr ? mesh.streamoutBuffer_PRE : mesh.vertexBuffer_POS), + dynamicVB ? dynamicVertexBufferPool : (mesh.streamoutBuffer_POS.get() != nullptr ? mesh.streamoutBuffer_POS.get() : mesh.vertexBuffer_POS.get()), + mesh.vertexBuffer_TEX.get(), + dynamicVB ? dynamicVertexBufferPool : (mesh.streamoutBuffer_PRE.get() != nullptr ? mesh.streamoutBuffer_PRE.get() : mesh.vertexBuffer_POS.get()), dynamicVertexBufferPool }; UINT strides[] = { @@ -5370,7 +5371,7 @@ void wiRenderer::RenderMeshes(const XMFLOAT3& eye, const CulledCollection& culle } boundVBType_Prev = boundVBType; - device->BindConstantBuffer(PS, material.constantBuffer, CB_GETBINDSLOT(MaterialCB), threadID); + device->BindConstantBuffer(PS, material.constantBuffer.get(), CB_GETBINDSLOT(MaterialCB), threadID); device->BindStencilRef(material.GetStencilRef(), threadID); @@ -6754,9 +6755,9 @@ void wiRenderer::BuildSceneBVH(GRAPHICSTHREAD threadID) device->BindConstantBuffer(CS, constantBuffers[CBTYPE_BVH], CB_GETBINDSLOT(BVHCB), threadID); GPUResource* res[] = { - mesh.indexBuffer, - mesh.vertexBuffer_POS, - mesh.vertexBuffer_TEX, + mesh.indexBuffer.get(), + mesh.vertexBuffer_POS.get(), + mesh.vertexBuffer_TEX.get(), }; device->BindResources(CS, res, TEXSLOT_ONDEMAND0, ARRAYSIZE(res), threadID); @@ -7895,12 +7896,22 @@ wiRenderer::RayIntersectWorldResult wiRenderer::RayIntersectWorld(const RAY& ray if (mesh.IsSkinned()) { - //for (size_t i = 0; i < mesh.vertices_POS.size(); ++i) - //{ - // _tmpvert = mesh.TransformVertex((int)i); - // _vertices[i] = XMLoadFloat4(&_tmpvert.pos); - //} - assert(0); // todo + const ArmatureComponent& armature = *scene.armatures.GetComponent(mesh.armatureID); + + for (size_t vertexI = 0; vertexI < mesh.vertices_POS.size(); ++vertexI) + { + XMVECTOR pos = mesh.vertices_POS[vertexI].LoadPOS(); + + const XMFLOAT4& ind = mesh.vertices_BON[vertexI].GetInd_FULL(); + const XMFLOAT4& wei = mesh.vertices_BON[vertexI].GetWei_FULL(); + + XMMATRIX sump = XMLoadFloat4x4(&armature.skinningMatrices[(int)ind.x]) * wei.x; + sump += XMLoadFloat4x4(&armature.skinningMatrices[(int)ind.y]) * wei.y; + sump += XMLoadFloat4x4(&armature.skinningMatrices[(int)ind.z]) * wei.z; + sump += XMLoadFloat4x4(&armature.skinningMatrices[(int)ind.w]) * wei.w; + + _vertices[i] = XMVector3Transform(pos, sump); + } } else if (mesh.IsDynamicVB()) { @@ -8168,9 +8179,9 @@ void wiRenderer::CreateImpostor(Entity entity, GRAPHICSTHREAD threadID) GetDevice()->InvalidateBufferAccess(dynamicVertexBufferPool, threadID); GPUBuffer* vbs[] = { - mesh.IsSkinned() ? mesh.streamoutBuffer_POS : mesh.vertexBuffer_POS, - mesh.vertexBuffer_TEX, - mesh.IsSkinned() ? mesh.streamoutBuffer_PRE : mesh.vertexBuffer_POS, + mesh.IsSkinned() ? mesh.streamoutBuffer_POS.get() : mesh.vertexBuffer_POS.get(), + mesh.vertexBuffer_TEX.get(), + mesh.IsSkinned() ? mesh.streamoutBuffer_PRE.get() : mesh.vertexBuffer_POS.get(), dynamicVertexBufferPool }; UINT strides[] = { @@ -8187,7 +8198,7 @@ void wiRenderer::CreateImpostor(Entity entity, GRAPHICSTHREAD threadID) }; GetDevice()->BindVertexBuffers(vbs, 0, ARRAYSIZE(vbs), strides, offsets, threadID); - GetDevice()->BindIndexBuffer(mesh.indexBuffer, mesh.GetIndexFormat(), 0, threadID); + GetDevice()->BindIndexBuffer(mesh.indexBuffer.get(), mesh.GetIndexFormat(), 0, threadID); GetDevice()->BindGraphicsPSO(PSO_captureimpostor, threadID); @@ -8268,7 +8279,7 @@ void wiRenderer::CreateImpostor(Entity entity, GRAPHICSTHREAD threadID) } MaterialComponent& material = *GetScene().materials.GetComponent(subset.materialID); - GetDevice()->BindConstantBuffer(PS, material.constantBuffer, CB_GETBINDSLOT(MaterialCB), threadID); + GetDevice()->BindConstantBuffer(PS, material.constantBuffer.get(), CB_GETBINDSLOT(MaterialCB), threadID); GetDevice()->BindResource(PS, material.GetBaseColorMap(), TEXSLOT_ONDEMAND0, threadID); GetDevice()->BindResource(PS, material.GetNormalMap(), TEXSLOT_ONDEMAND1, threadID); diff --git a/WickedEngine/wiSceneSystem.cpp b/WickedEngine/wiSceneSystem.cpp index 1d320e835..7aba8b369 100644 --- a/WickedEngine/wiSceneSystem.cpp +++ b/WickedEngine/wiSceneSystem.cpp @@ -31,6 +31,29 @@ namespace wiSceneSystem XMStoreFloat4x4(&world, W); } } + void TransformComponent::UpdateParentedTransform(const TransformComponent& parent, const XMFLOAT4X4& inverseParentBindMatrix) + { + XMVECTOR S_local = XMLoadFloat3(&scale_local); + XMVECTOR R_local = XMLoadFloat4(&rotation_local); + XMVECTOR T_local = XMLoadFloat3(&translation_local); + XMMATRIX W = + XMMatrixScalingFromVector(S_local) * + XMMatrixRotationQuaternion(R_local) * + XMMatrixTranslationFromVector(T_local); + + XMMATRIX W_parent = XMLoadFloat4x4(&parent.world); + XMMATRIX B = XMLoadFloat4x4(&inverseParentBindMatrix); + W = W * B * W_parent; + + XMVECTOR S, R, T; + XMMatrixDecompose(&S, &R, &T, W); + XMStoreFloat3(&scale, S); + XMStoreFloat4(&rotation, R); + XMStoreFloat3(&translation, T); + + world_prev = world; + XMStoreFloat4x4(&world, W); + } void TransformComponent::ApplyTransform() { dirty = true; @@ -302,17 +325,12 @@ namespace wiSceneSystem // Create actual GPU data: - SAFE_DELETE(indexBuffer); - SAFE_DELETE(vertexBuffer_POS); - SAFE_DELETE(vertexBuffer_TEX); - SAFE_DELETE(vertexBuffer_BON); - SAFE_DELETE(streamoutBuffer_POS); - SAFE_DELETE(streamoutBuffer_PRE); - GPUBufferDesc bd; SubresourceData InitData; - //if (!hasDynamicVB()) + HRESULT hr; + + //if (!IsDynamicVB()) { ZeroMemory(&bd, sizeof(bd)); bd.Usage = USAGE_IMMUTABLE; @@ -323,8 +341,9 @@ namespace wiSceneSystem InitData.pSysMem = vertices_POS.data(); bd.ByteWidth = (UINT)(sizeof(Vertex_POS) * vertices_POS.size()); - vertexBuffer_POS = new GPUBuffer; - wiRenderer::GetDevice()->CreateBuffer(&bd, &InitData, vertexBuffer_POS); + vertexBuffer_POS.reset(new GPUBuffer); + hr = wiRenderer::GetDevice()->CreateBuffer(&bd, &InitData, vertexBuffer_POS.get()); + assert(SUCCEEDED(hr)); } if (!vertices_BON.empty()) @@ -337,8 +356,9 @@ namespace wiSceneSystem InitData.pSysMem = vertices_BON.data(); bd.ByteWidth = (UINT)(sizeof(Vertex_BON) * vertices_BON.size()); - vertexBuffer_BON = new GPUBuffer; - wiRenderer::GetDevice()->CreateBuffer(&bd, &InitData, vertexBuffer_BON); + vertexBuffer_BON.reset(new GPUBuffer); + hr = wiRenderer::GetDevice()->CreateBuffer(&bd, &InitData, vertexBuffer_BON.get()); + assert(SUCCEEDED(hr)); ZeroMemory(&bd, sizeof(bd)); bd.Usage = USAGE_DEFAULT; @@ -347,12 +367,14 @@ namespace wiSceneSystem bd.MiscFlags = RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; bd.ByteWidth = (UINT)(sizeof(Vertex_POS) * vertices_POS.size()); - streamoutBuffer_POS = new GPUBuffer; - wiRenderer::GetDevice()->CreateBuffer(&bd, nullptr, streamoutBuffer_POS); + streamoutBuffer_POS.reset(new GPUBuffer); + hr = wiRenderer::GetDevice()->CreateBuffer(&bd, nullptr, streamoutBuffer_POS.get()); + assert(SUCCEEDED(hr)); bd.ByteWidth = (UINT)(sizeof(Vertex_POS) * vertices_POS.size()); - streamoutBuffer_PRE = new GPUBuffer; - wiRenderer::GetDevice()->CreateBuffer(&bd, nullptr, streamoutBuffer_PRE); + streamoutBuffer_PRE.reset(new GPUBuffer); + hr = wiRenderer::GetDevice()->CreateBuffer(&bd, nullptr, streamoutBuffer_PRE.get()); + assert(SUCCEEDED(hr)); } // texture coordinate buffers are always static: @@ -365,8 +387,9 @@ namespace wiSceneSystem bd.ByteWidth = (UINT)(bd.StructureByteStride * vertices_TEX.size()); bd.Format = Vertex_TEX::FORMAT; InitData.pSysMem = vertices_TEX.data(); - vertexBuffer_TEX = new GPUBuffer; - wiRenderer::GetDevice()->CreateBuffer(&bd, &InitData, vertexBuffer_TEX); + vertexBuffer_TEX.reset(new GPUBuffer); + hr = wiRenderer::GetDevice()->CreateBuffer(&bd, &InitData, vertexBuffer_TEX.get()); + assert(SUCCEEDED(hr)); // Remap index buffer to be continuous across subsets and create gpu buffer data: @@ -420,8 +443,9 @@ namespace wiSceneSystem bd.Format = GetIndexFormat() == INDEXFORMAT_16BIT ? FORMAT_R16_UINT : FORMAT_R32_UINT; InitData.pSysMem = gpuIndexData; bd.ByteWidth = (UINT)(stride * indices.size()); - indexBuffer = new GPUBuffer; - wiRenderer::GetDevice()->CreateBuffer(&bd, &InitData, indexBuffer); + indexBuffer.reset(new GPUBuffer); + hr = wiRenderer::GetDevice()->CreateBuffer(&bd, &InitData, indexBuffer.get()); + assert(SUCCEEDED(hr)); SAFE_DELETE_ARRAY(gpuIndexData); @@ -612,6 +636,7 @@ namespace wiSceneSystem } + void CameraComponent::CreatePerspective(float newWidth, float newHeight, float newNear, float newFar, float newFOV) { zNearP = newNear; @@ -699,7 +724,7 @@ namespace wiSceneSystem RunHierarchyUpdateSystem(parents, transforms, layers); - RunBoneUpdateSystem(transforms, bones); + RunArmatureUpdateSystem(transforms, bones, armatures); RunPhysicsUpdateSystem(transforms, meshes, objects, physicscomponents); @@ -988,6 +1013,12 @@ namespace wiSceneSystem XMStoreFloat4x4(&parentcomponent->world_parent_inverse_bind, XMMatrixInverse(nullptr, XMLoadFloat4x4(&transform_parent->world))); } + TransformComponent* transform_child = transforms.GetComponent(entity); + if (transform_child != nullptr) + { + transform_child->UpdateParentedTransform(*transform_parent, parentcomponent->world_parent_inverse_bind); + } + LayerComponent* layer_child = layers.GetComponent(entity); if (layer_child != nullptr) { @@ -1058,26 +1089,7 @@ namespace wiSceneSystem TransformComponent* transform_parent = transforms.GetComponent(parentcomponent.parentID); if (transform_child != nullptr && transform_parent != nullptr) { - XMVECTOR S_local = XMLoadFloat3(&transform_child->scale_local); - XMVECTOR R_local = XMLoadFloat4(&transform_child->rotation_local); - XMVECTOR T_local = XMLoadFloat3(&transform_child->translation_local); - XMMATRIX W = - XMMatrixScalingFromVector(S_local) * - XMMatrixRotationQuaternion(R_local) * - XMMatrixTranslationFromVector(T_local); - - XMMATRIX W_parent = XMLoadFloat4x4(&transform_parent->world); - XMMATRIX B = XMLoadFloat4x4(&parentcomponent.world_parent_inverse_bind); - W = W * B * W_parent; - - XMVECTOR S, R, T; - XMMatrixDecompose(&S, &R, &T, W); - XMStoreFloat3(&transform_child->scale, S); - XMStoreFloat4(&transform_child->rotation, R); - XMStoreFloat3(&transform_child->translation, T); - - transform_child->world_prev = transform_child->world; - XMStoreFloat4x4(&transform_child->world, W); + transform_child->UpdateParentedTransform(*transform_parent, parentcomponent.world_parent_inverse_bind); } @@ -1090,21 +1102,37 @@ namespace wiSceneSystem } } - void RunBoneUpdateSystem( + void RunArmatureUpdateSystem( const ComponentManager& transforms, - ComponentManager& bones + const ComponentManager& bones, + ComponentManager& armatures ) { - for (size_t i = 0; i < bones.GetCount(); ++i) + for (size_t i = 0; i < armatures.GetCount(); ++i) { - BoneComponent& bone = bones[i]; - Entity entity = bones.GetEntity(i); - const TransformComponent& transform = *transforms.GetComponent(entity); + ArmatureComponent& armature = armatures[i]; + Entity entity = armatures.GetEntity(i); + + XMMATRIX R = XMLoadFloat4x4(&armature.skinningRemap); + + if (armature.skinningMatrices.size() != armature.boneCollection.size()) + { + armature.skinningMatrices.resize(armature.boneCollection.size()); + } + + int boneIndex = 0; + for (Entity boneEntity : armature.boneCollection) + { + const BoneComponent& bone = *bones.GetComponent(boneEntity); + const TransformComponent& bone_transform = *transforms.GetComponent(boneEntity); + + XMMATRIX B = XMLoadFloat4x4(&bone.inverseBindPoseMatrix); + XMMATRIX W = XMLoadFloat4x4(&bone_transform.world); + XMMATRIX M = W * B * R; + + XMStoreFloat4x4(&armature.skinningMatrices[boneIndex++], M); + } - XMMATRIX inverseBindPoseMatrix = XMLoadFloat4x4(&bone.inverseBindPoseMatrix); - XMMATRIX world = XMLoadFloat4x4(&transform.world); - XMMATRIX skinningMatrix = inverseBindPoseMatrix * world; - XMStoreFloat4x4(&bone.skinningMatrix, skinningMatrix); } } void RunPhysicsUpdateSystem( diff --git a/WickedEngine/wiSceneSystem.h b/WickedEngine/wiSceneSystem.h index d2d7a0436..80bad86d7 100644 --- a/WickedEngine/wiSceneSystem.h +++ b/WickedEngine/wiSceneSystem.h @@ -47,6 +47,7 @@ namespace wiSceneSystem XMFLOAT4X4 world_prev; void UpdateTransform(); + void UpdateParentedTransform(const TransformComponent& parent, const XMFLOAT4X4& inverseParentBindMatrix); void ApplyTransform(); void ClearTransform(); void Translate(const XMFLOAT3& value); @@ -107,7 +108,7 @@ namespace wiSceneSystem std::string displacementMapName; wiGraphicsTypes::Texture2D* displacementMap = nullptr; - wiGraphicsTypes::GPUBuffer* constantBuffer = nullptr; + std::unique_ptr constantBuffer; inline void SetUserStencilRef(uint8_t value) { @@ -288,12 +289,12 @@ namespace wiSceneSystem }; std::vector subsets; - wiGraphicsTypes::GPUBuffer* indexBuffer = nullptr; - wiGraphicsTypes::GPUBuffer* vertexBuffer_POS = nullptr; - wiGraphicsTypes::GPUBuffer* vertexBuffer_TEX = nullptr; - wiGraphicsTypes::GPUBuffer* vertexBuffer_BON = nullptr; - wiGraphicsTypes::GPUBuffer* streamoutBuffer_POS = nullptr; - wiGraphicsTypes::GPUBuffer* streamoutBuffer_PRE = nullptr; + std::unique_ptr indexBuffer; + std::unique_ptr vertexBuffer_POS; + std::unique_ptr vertexBuffer_TEX; + std::unique_ptr vertexBuffer_BON; + std::unique_ptr streamoutBuffer_POS; + std::unique_ptr streamoutBuffer_PRE; // Dynamic vertexbuffers write into a global pool, these will be the offsets into that: bool dynamicVB = false; @@ -396,12 +397,12 @@ namespace wiSceneSystem struct BoneComponent { XMFLOAT4X4 inverseBindPoseMatrix; - XMFLOAT4X4 skinningMatrix; }; struct ArmatureComponent { std::vector boneCollection; + std::vector skinningMatrices; GFX_STRUCT ShaderBoneType { @@ -419,7 +420,7 @@ namespace wiSceneSystem ALIGN_16 }; std::vector boneData; - wiGraphicsTypes::GPUBuffer boneBuffer; + std::unique_ptr boneBuffer; // This will be used to eg. mirror the whole skin, without modifying the armature transform itself // It will affect the skin only, so the mesh vertices should be mirrored as well to work correctly! @@ -439,7 +440,24 @@ namespace wiSceneSystem LIGHTTYPE_COUNT, } type = POINT; - inline void SetType(LightType val) { type = val; } + inline void SetType(LightType val) { + type = val; + switch (type) + { + case DIRECTIONAL: + case SPOT: + shadowBias = 0.0001f; + break; + case POINT: + case SPHERE: + case DISC: + case RECTANGLE: + case TUBE: + case LIGHTTYPE_COUNT: + shadowBias = 0.1f; + break; + } + } inline LightType GetType() const { return type; } XMFLOAT3 color = XMFLOAT3(1, 1, 1); @@ -621,6 +639,29 @@ namespace wiSceneSystem inline float GetOpacity() const { return color.w; } }; + struct AnimationComponent + { + struct AnimationChannel + { + wiECS::Entity target = wiECS::INVALID_ENTITY; + enum class Type + { + TRANSLATION, + ROTATION, + SCALE + } type = Type::TRANSLATION; + enum class Mode + { + LINEAR, + STEP, + } mode = Mode::LINEAR; + std::vector keyframe_times; + std::vector keyframe_data; + }; + + std::vector channels; + }; + struct ModelComponent { std::unordered_set materials; @@ -654,6 +695,7 @@ namespace wiSceneSystem wiECS::ComponentManager probes; wiECS::ComponentManager forces; wiECS::ComponentManager decals; + wiECS::ComponentManager animations; wiECS::ComponentManager models; AABB bounds; @@ -748,9 +790,10 @@ namespace wiSceneSystem wiECS::ComponentManager& objects, wiECS::ComponentManager& physicscomponents ); - void RunBoneUpdateSystem( + void RunArmatureUpdateSystem( const wiECS::ComponentManager& transforms, - wiECS::ComponentManager& bones + const wiECS::ComponentManager& bones, + wiECS::ComponentManager& armatures ); void RunMaterialUpdateSystem(wiECS::ComponentManager& materials, float dt); void RunObjectUpdateSystem( diff --git a/WickedEngine/wiSceneSystem_Decl.h b/WickedEngine/wiSceneSystem_Decl.h index b1a5f8325..1c0a9cfe3 100644 --- a/WickedEngine/wiSceneSystem_Decl.h +++ b/WickedEngine/wiSceneSystem_Decl.h @@ -19,6 +19,7 @@ namespace wiSceneSystem struct EnvironmentProbeComponent; struct ForceFieldComponent; struct DecalComponent; + struct AnimationComponent; struct ModelComponent; struct Scene; } diff --git a/models/GLTF/CesiumMan.glb b/models/GLTF/CesiumMan.glb new file mode 100644 index 000000000..bc1a784f0 Binary files /dev/null and b/models/GLTF/CesiumMan.glb differ diff --git a/models/GLTF/T-Rex.glb b/models/GLTF/T-Rex.glb new file mode 100644 index 000000000..c0d899cd4 Binary files /dev/null and b/models/GLTF/T-Rex.glb differ