TextureDesc LoadTextureFormat(StringSection<::Assets::ResChar> filename) { ucs2 wfilename[MaxPath]; Conversion::Convert(wfilename, dimof(wfilename), filename.begin(), filename.end()); auto fmt = GetTexFmt(wfilename); using namespace DirectX; TexMetadata metadata; HRESULT hresult = -1; if (fmt == TexFmt::DDS) { hresult = GetMetadataFromDDSFile((const wchar_t*)wfilename, DDS_FLAGS_NONE, metadata); } else if (fmt == TexFmt::TGA) { hresult = GetMetadataFromTGAFile((const wchar_t*)wfilename, metadata); } else if (fmt == TexFmt::WIC) { hresult = GetMetadataFromWICFile((const wchar_t*)wfilename, WIC_FLAGS_NONE, metadata); } else { LogWarning << "Texture format not apparent from filename (" << filename.AsString().c_str() << ")"; } if (SUCCEEDED(hresult)) { return BuildTextureDesc(metadata); } return TextureDesc::Empty(); }
std::shared_ptr<DependencyValidation> Store::WriteDependencies( const ResChar intermediateFileName[], StringSection<ResChar> baseDir, IteratorRange<const DependentFileState*> deps, bool makeDepValidation) const { Data data; std::shared_ptr<DependencyValidation> result; if (makeDepValidation) result = std::make_shared<DependencyValidation>(); // we have to write the base directory to the dependencies file as well // to keep it short, most filenames should be expressed as relative files char buffer[MaxPath]; data.SetAttribute("BasePath", baseDir.AsString().c_str()); SplitPath<ResChar> baseSplitPath(baseDir); auto dependenciesBlock = std::make_unique<Data>("Dependencies"); for (auto& s:deps) { auto c = std::make_unique<Data>(); auto relPath = MakeRelativePath( baseSplitPath, SplitPath<ResChar>(s._filename)); c->SetValue(relPath.c_str()); if (s._status != DependentFileState::Status::Shadowed) { c->SetAttribute("ModTimeH", (int)(s._timeMarker>>32ull)); c->SetAttribute("ModTimeL", (int)(s._timeMarker)); } dependenciesBlock->Add(c.release()); if (makeDepValidation) RegisterFileDependency(result, s._filename.c_str()); }
void PushString( std::basic_streambuf<OutChar>& stream, StringSection<InChar> input) { // String conversion process results in several redundant allocations. It's not perfectly // efficient using OutputString = std::basic_string<OutChar>; auto converted = Conversion::Convert<OutputString>(input.AsString()); stream.sputn(AsPointer(converted.begin()), converted.size()); }
PreparedSkinFile::PreparedSkinFile(const ColladaScaffold& input, const VisualScene& scene, StringSection<utf8> rootNode) { using namespace RenderCore::ColladaConversion; SkeletonRegistry jointRefs; ReferencedGeometries refGeos; bool gatherSuccess = refGeos.Gather(scene.GetRootNode(), rootNode, jointRefs); if (!gatherSuccess) { StringMeld<1024> meld; using ::operator<<; meld << "Error while looking for root node: " << rootNode.AsString().c_str() << ". Known nodes: "; auto nodes = scene.GetRootNode().FindAllBreadthFirst([](const Node& n) { return true;}); for (unsigned c=0; c<nodes.size(); ++c) { if (c!=0) meld << ", "; meld << nodes[c].GetName().AsString().c_str(); } Throw(::Assets::Exceptions::FormatError(meld.get())); } // The skeleton joints won't be included in the skeleton // until we call FindSkinJoints. We don't really need the // full skeleton embedded in the skin file... When the skeleton // is not there, we will just see the model in the bind pose. // But it can be handy to be there for previewing models quickly. refGeos.FindSkinJoints(scene, input._resolveContext, jointRefs); // We can now build the skeleton (because ReferencedGeometries::Gather // has initialised jointRefs. unsigned topLevelPops = 0; auto coordinateTransform = BuildCoordinateTransform(input._doc->GetAssetDesc()); if (!Equivalent(coordinateTransform, Identity<Float4x4>(), 1e-5f)) { // Push on the coordinate transform (if there is one) // This should be optimised into other matrices (or even into // the geometry) when we perform the skeleton optimisation steps. topLevelPops = _skeleton.GetTransformationMachine().PushTransformation( coordinateTransform); } // When extracting an internal node, we ignore the transform // on that internal node BuildSkeleton(_skeleton, scene.GetRootNode(), rootNode, jointRefs, false); _skeleton.GetTransformationMachine().Pop(topLevelPops); // For each output matrix, we want to know if we can merge a transformation into it. // We can only do this if (unskinned) geometry instances are attached -- and those // geometry instances must be attached in only one place. If the output transform does // not have a geometry instance attached, or if any of the geometry instances are // attached to more than one matrix, or if something other than a geometry instance is // attached, then we cannot do any merging. TransMachineOptimizer optimizer(refGeos, _skeleton.GetTransformationMachine().GetOutputMatrixCount(), scene); _skeleton.GetTransformationMachine().Optimize(optimizer); // We can try to optimise the skeleton here. We should collect the list // of meshes that we can optimise transforms into (ie, meshes that aren't // used in multiple places, and that aren't skinned). // We need to collect that list of transforms before we actually instantiate // the geometry -- so that merging in the changes can be done in the instantiate // step. for (auto c:refGeos._meshes) { TRY { _cmdStream.Add( RenderCore::ColladaConversion::InstantiateGeometry( scene.GetInstanceGeometry(c._objectIndex), c._outputMatrixIndex, optimizer.GetMergedOutputMatrix(c._outputMatrixIndex), c._levelOfDetail, input._resolveContext, _geoObjects, jointRefs, input._cfg)); } CATCH(const std::exception& e) { LogWarning << "Got exception while instantiating geometry (" << scene.GetInstanceGeometry(c._objectIndex)._reference.AsString().c_str() << "). Exception details:"; LogWarning << e.what(); } CATCH(...) { LogWarning << "Got unknown exception while instantiating geometry (" << scene.GetInstanceGeometry(c._objectIndex)._reference.AsString().c_str() << ")."; } CATCH_END