summaryrefslogtreecommitdiffstats
path: root/o3d/converter/cross/converter.cc
diff options
context:
space:
mode:
Diffstat (limited to 'o3d/converter/cross/converter.cc')
-rw-r--r--o3d/converter/cross/converter.cc312
1 files changed, 312 insertions, 0 deletions
diff --git a/o3d/converter/cross/converter.cc b/o3d/converter/cross/converter.cc
new file mode 100644
index 0000000..511b69f
--- /dev/null
+++ b/o3d/converter/cross/converter.cc
@@ -0,0 +1,312 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the logic for converting the scene graph to a
+// JSON-encoded file that is stored in a zip archive.
+#include "converter/cross/converter.h"
+
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/scoped_ptr.h"
+#include "core/cross/class_manager.h"
+#include "core/cross/client.h"
+#include "core/cross/effect.h"
+#include "core/cross/error.h"
+#include "core/cross/features.h"
+#include "core/cross/object_manager.h"
+#include "core/cross/pack.h"
+#include "core/cross/renderer.h"
+#include "core/cross/service_locator.h"
+#include "core/cross/transform.h"
+#include "core/cross/tree_traversal.h"
+#include "core/cross/types.h"
+#include "import/cross/collada.h"
+#include "import/cross/collada_conditioner.h"
+#include "import/cross/file_output_stream_processor.h"
+#include "import/cross/targz_generator.h"
+#include "import/cross/archive_request.h"
+#include "serializer/cross/serializer.h"
+#include "utils/cross/file_path_utils.h"
+#include "utils/cross/json_writer.h"
+#include "utils/cross/string_writer.h"
+#include "utils/cross/temporary_file.h"
+
+namespace o3d {
+
+namespace {
+void AddBinaryElements(const Collada& collada,
+ TarGzGenerator* archive_generator) {
+ std::vector<FilePath> paths = collada.GetOriginalDataFilenames();
+ for (std::vector<FilePath>::const_iterator iter = paths.begin();
+ iter != paths.end();
+ ++iter) {
+ const std::string& data = collada.GetOriginalData(*iter);
+
+ archive_generator->AddFile(FilePathToUTF8(*iter), data.size());
+ archive_generator->AddFileBytes(
+ reinterpret_cast<const uint8*>(data.c_str()),
+ data.length());
+ }
+}
+} // end anonymous namespace
+
+namespace converter {
+// Loads the Collada input file and writes it to the zipped JSON output file.
+bool Convert(const FilePath& in_filename,
+ const FilePath& out_filename,
+ const Options& options,
+ String *error_messages) {
+ // Create a service locator and renderer.
+ ServiceLocator service_locator;
+ EvaluationCounter evaluation_counter(&service_locator);
+ ClassManager class_manager(&service_locator);
+ ObjectManager object_manager(&service_locator);
+ Profiler profiler(&service_locator);
+ ErrorStatus error_status(&service_locator);
+ Features features(&service_locator);
+
+ features.Init("MaxCapabilities");
+
+ // Collect error messages.
+ ErrorCollector error_collector(&service_locator);
+
+ scoped_ptr<Renderer> renderer(
+ Renderer::CreateDefaultRenderer(&service_locator));
+ renderer->InitCommon();
+
+ Pack::Ref pack(object_manager.CreatePack());
+ Transform* root = pack->Create<Transform>();
+ root->set_name(String(Serializer::ROOT_PREFIX) + String("root"));
+
+ // Setup a ParamFloat to be the source to all animations in this file.
+ ParamObject* param_object = pack->Create<ParamObject>();
+ // This is some arbitrary name
+ param_object->set_name(O3D_STRING_CONSTANT("animSourceOwner"));
+ ParamFloat* param_float = param_object->CreateParam<ParamFloat>("animSource");
+
+ Collada::Options collada_options;
+ collada_options.condition_document = options.condition;
+ collada_options.keep_original_data = true;
+ collada_options.base_path = options.base_path;
+ collada_options.up_axis = options.up_axis;
+ Collada collada(pack.Get(), collada_options);
+ if (!collada.ImportFile(in_filename, root, param_float)) {
+ if (error_messages) {
+ *error_messages += error_collector.errors();
+ }
+ return false;
+ }
+
+ // Remove the animation param_object (and indirectly the param_float)
+ // if there is no animation.
+ if (param_float->output_connections().empty()) {
+ pack->RemoveObject(param_object);
+ }
+
+ // Attempt to open the output file.
+ FILE* out_file = file_util::OpenFile(out_filename, "wb");
+ if (out_file == NULL) {
+ O3D_ERROR(&service_locator) << "Could not open output file \""
+ << FilePathToUTF8(out_filename).c_str()
+ << "\"";
+ if (error_messages) {
+ *error_messages += error_collector.errors();
+ }
+ return false;
+ }
+
+ // Create an archive file and serialize the JSON scene graph and assets to it.
+ FileOutputStreamProcessor stream_processor(out_file);
+ TarGzGenerator archive_generator(&stream_processor);
+
+ archive_generator.AddFile(ArchiveRequest::O3D_MARKER,
+ ArchiveRequest::O3D_MARKER_CONTENT_LENGTH);
+ archive_generator.AddFileBytes(
+ reinterpret_cast<const uint8*>(ArchiveRequest::O3D_MARKER_CONTENT),
+ ArchiveRequest::O3D_MARKER_CONTENT_LENGTH);
+
+ // Serialize the created O3D scene graph to JSON.
+ StringWriter out_writer(StringWriter::LF);
+ JsonWriter json_writer(&out_writer, 2);
+ if (!options.pretty_print) {
+ json_writer.BeginCompacting();
+ }
+ Serializer serializer(&service_locator, &json_writer, &archive_generator);
+ serializer.SerializePack(pack.Get());
+ json_writer.Close();
+ out_writer.Close();
+ if (!options.pretty_print) {
+ json_writer.EndCompacting();
+ }
+
+ String json = out_writer.ToString();
+
+ archive_generator.AddFile("scene.json", json.length());
+ archive_generator.AddFileBytes(reinterpret_cast<const uint8*>(json.c_str()),
+ json.length());
+
+ // Now add original data (e.g. compressed textures) collected during
+ // the loading process.
+ AddBinaryElements(collada, &archive_generator);
+
+ archive_generator.Finalize();
+
+ file_util::CloseFile(out_file);
+
+ pack->Destroy();
+ if (error_messages) {
+ *error_messages = error_collector.errors();
+ }
+ return true;
+}
+
+// Loads the input shader file and validates it.
+bool Verify(const FilePath& in_filename,
+ const FilePath& out_filename,
+ const Options& options,
+ String* error_messages) {
+ FilePath source_filename(in_filename);
+ // Create a service locator and renderer.
+ ServiceLocator service_locator;
+ EvaluationCounter evaluation_counter(&service_locator);
+ ClassManager class_manager(&service_locator);
+ ObjectManager object_manager(&service_locator);
+ Profiler profiler(&service_locator);
+ ErrorStatus error_status(&service_locator);
+
+ // Collect error messages.
+ ErrorCollector error_collector(&service_locator);
+
+ scoped_ptr<Renderer> renderer(
+ Renderer::CreateDefaultRenderer(&service_locator));
+ renderer->InitCommon();
+
+ Pack::Ref pack(object_manager.CreatePack());
+ Transform* root = pack->Create<Transform>();
+ root->set_name(O3D_STRING_CONSTANT("root"));
+
+ Collada::Options collada_options;
+ collada_options.condition_document = options.condition;
+ collada_options.keep_original_data = false;
+ Collada collada(pack.Get(), collada_options);
+
+ ColladaConditioner conditioner(&service_locator);
+ String vertex_shader_entry_point;
+ String fragment_shader_entry_point;
+ TemporaryFile temp_file;
+ if (options.condition) {
+ if (!TemporaryFile::Create(&temp_file)) {
+ O3D_ERROR(&service_locator) << "Could not create temporary file";
+ if (error_messages) {
+ *error_messages = error_collector.errors();
+ }
+ return false;
+ }
+ SamplerStateList state_list;
+ if (!conditioner.RewriteShaderFile(NULL,
+ in_filename,
+ temp_file.path(),
+ &state_list,
+ &vertex_shader_entry_point,
+ &fragment_shader_entry_point)) {
+ O3D_ERROR(&service_locator) << "Could not rewrite shader file";
+ if (error_messages) {
+ *error_messages = error_collector.errors();
+ }
+ return false;
+ }
+ source_filename = temp_file.path();
+ } else {
+ source_filename = in_filename;
+ }
+
+ std::string shader_source_in;
+ // Load file into memory
+ if (!file_util::ReadFileToString(source_filename, &shader_source_in)) {
+ O3D_ERROR(&service_locator) << "Could not read shader file "
+ << FilePathToUTF8(source_filename).c_str();
+ if (error_messages) {
+ *error_messages = error_collector.errors();
+ }
+ return false;
+ }
+
+ Effect::MatrixLoadOrder matrix_load_order;
+ scoped_ptr<Effect> effect(pack->Create<Effect>());
+ if (!effect->ValidateFX(shader_source_in,
+ &vertex_shader_entry_point,
+ &fragment_shader_entry_point,
+ &matrix_load_order)) {
+ O3D_ERROR(&service_locator) << "Could not validate shader file";
+ if (error_messages) {
+ *error_messages = error_collector.errors();
+ }
+ return false;
+ }
+
+ if (!conditioner.CompileHLSL(shader_source_in,
+ vertex_shader_entry_point,
+ fragment_shader_entry_point)) {
+ O3D_ERROR(&service_locator) << "Could not HLSL compile shader file";
+ if (error_messages) {
+ *error_messages = error_collector.errors();
+ }
+ return false;
+ }
+
+ if (!conditioner.CompileCg(in_filename,
+ shader_source_in,
+ vertex_shader_entry_point,
+ fragment_shader_entry_point)) {
+ O3D_ERROR(&service_locator) << "Could not Cg compile shader file";
+ if (error_messages) {
+ *error_messages = error_collector.errors();
+ }
+ return false;
+ }
+
+ // If we've validated the file, then we write out the conditioned
+ // shader to the given output file, if there is one.
+ if (options.condition && !out_filename.empty()) {
+ if (file_util::WriteFile(out_filename, shader_source_in.c_str(),
+ shader_source_in.size()) == -1) {
+ O3D_ERROR(&service_locator) << "Warning: Could not write to output file '"
+ << FilePathToUTF8(in_filename).c_str() << "'";
+ }
+ }
+ if (error_messages) {
+ *error_messages = error_collector.errors();
+ }
+ return true;
+}
+} // end namespace converter
+} // end namespace o3d