提交 ded2e561 编写于 作者: F Fabrice Robinet

Merge pull request #305 from KhronosGroup/dev-7

Dev 7
......@@ -67,11 +67,13 @@ if (USE_OPEN3DGC)
include_directories(${COLLADA2GLTF_SOURCE_DIR}/dependencies/o3dgc/src/o3dgc_decode_lib/inc)
endif()
if (NOT WIN32)
find_package(PNG REQUIRED)
find_package(PNG)
if (PNG_FOUND)
include_directories(${PNG_INCLUDE_DIR})
find_package(ZLIB REQUIRED)
include_directories(${ZLIB_INCLUDE_DIR})
add_definitions(-DUSE_LIBPNG)
else()
message(WARNING "libpng or one of its dependencies couldn't be found. Transparency may not be correctly detected.")
endif()
link_directories(${COLLADA2GLTF_BINARY_DIR}/lib)
......@@ -143,6 +145,8 @@ set(GLTF_SOURCES
helpers/geometryHelpers.cpp
helpers/mathHelpers.h
helpers/mathHelpers.cpp
helpers/encodingHelpers.h
helpers/encodingHelpers.cpp
convert/meshConverter.cpp
convert/meshConverter.h
......@@ -180,9 +184,8 @@ if (WIN32)
set_target_properties(collada2gltfConvert PROPERTIES RUNTIME_OUTPUT_DIRECTORY "bin")
endif()
if (NOT WIN32)
LIST(APPEND TARGET_LIBS ${PNG_LIBRARY} ${ZLIB_LIBRARY})
if (PNG_FOUND)
LIST(APPEND TARGET_LIBS ${PNG_LIBRARY} ${ZLIB_LIBRARY})
endif()
if (USE_OPEN3DGC)
......
......@@ -29,12 +29,14 @@
#include "GLTFOpenCOLLADAUtils.h"
#include "GLTFExtraDataHandler.h"
#include "COLLADASaxFWLLoader.h"
#include "COLLADAFWFileInfo.h"
#include "GLTF-Open3DGC.h"
#include "profiles/webgl-1.0/GLTFWebGL_1_0_Profile.h"
#include "GitSHA1.h"
#include <algorithm>
#include "commonProfileShaders.h"
#include "helpers/encodingHelpers.h"
#include "COLLADAFWFileInfo.h"
#if __cplusplus <= 199711L
using namespace std::tr1;
......@@ -51,7 +53,7 @@ namespace GLTF
*/
COLLADA2GLTFWriter::COLLADA2GLTFWriter(shared_ptr<GLTFAsset> asset):
_asset(asset),
_visualScene(0) {
_visualScene(0){
}
/*
......@@ -115,6 +117,37 @@ namespace GLTF
assetObject->setString(kProfile, asset->profile()->id());
assetObject->setDouble(kVersion, glTFVersion);
if (globalAsset->getUpAxisType() == COLLADAFW::FileInfo::X_UP ||
globalAsset->getUpAxisType() == COLLADAFW::FileInfo::Z_UP)
{
COLLADABU::Math::Matrix4 matrix = COLLADABU::Math::Matrix4::IDENTITY;
if (globalAsset->getUpAxisType() == COLLADAFW::FileInfo::X_UP)
{
// Rotate -90 deg around Z
matrix.setElement(0, 0, 0.0f);
matrix.setElement(0, 1, 1.0f);
matrix.setElement(1, 0, -1.0f);
matrix.setElement(1, 1, 0.0f);
}
else // Z_UP
{
// Rotate 90 deg around X
matrix.setElement(1, 1, 0.0f);
matrix.setElement(1, 2, -1.0f);
matrix.setElement(2, 1, 1.0f);
matrix.setElement(2, 2, 0.0f);
}
_rootTransform = std::shared_ptr<GLTF::JSONObject>(new GLTF::JSONObject());
_rootTransform->setString(kName, "Y_UP_Transform");
_rootTransform->setValue("matrix", serializeOpenCOLLADAMatrix4(matrix));
shared_ptr <GLTF::JSONArray> childrenArray(new GLTF::JSONArray());
_rootTransform->setValue(kChildren, childrenArray);
}
asset->setDistanceScale(globalAsset->getUnit().getLinearUnitMeter());
return true;
}
......@@ -310,6 +343,11 @@ namespace GLTF
if (shouldExportTRS) {
GLTF::decomposeMatrix(matrix, translation, rotation, scale);
// Scale distance units if we need to
translation[0] *= (float)_asset->getDistanceScale();
translation[1] *= (float)_asset->getDistanceScale();
translation[2] *= (float)_asset->getDistanceScale();
bool exportDefaultValues = CONFIG_BOOL(asset, "exportDefaultValues");
bool exportTranslation = !(!exportDefaultValues &&
......@@ -326,9 +364,11 @@ namespace GLTF
} else {
//FIXME: OpenCOLLADA typo
matrix.scaleTrans(_asset->getDistanceScale());
bool exportMatrix = !((matrix.isIdentiy() && (CONFIG_BOOL(asset, "exportDefaultValues") == false) ));
if (exportMatrix)
if (exportMatrix) {
nodeObject->setValue("matrix", serializeOpenCOLLADAMatrix4(matrix));
}
}
const InstanceControllerPointerArray& instanceControllers = node->getInstanceControllers();
......@@ -503,8 +543,28 @@ namespace GLTF
scenesObject->setValue("defaultScene", sceneObject); //FIXME: should use this id -> visualScene->getOriginalId()
//first pass to output children name of our root node
shared_ptr <GLTF::JSONArray> childrenArray(new GLTF::JSONArray());
sceneObject->setValue(kNodes, childrenArray);
shared_ptr <GLTF::JSONArray> childrenArray;
if (_rootTransform)
{
// Add the root transform to the nodes
std::string yUpNodeID = uniqueIdWithType(kNode, this->_loader.getUniqueId(COLLADAFW::COLLADA_TYPE::NODE));
nodesObject->setValue(yUpNodeID, _rootTransform);
// Create a children array for the scene and add the root transform to it
shared_ptr <GLTF::JSONArray> sceneChildrenArray(new GLTF::JSONArray());
sceneObject->setValue(kNodes, sceneChildrenArray);
shared_ptr <GLTF::JSONString> rootIDValue(new GLTF::JSONString(yUpNodeID));
sceneChildrenArray->appendValue(static_pointer_cast <GLTF::JSONValue> (rootIDValue));
// Set childrenArray to the root transform's children array so all root nodes will become its children
childrenArray = std::static_pointer_cast<GLTF::JSONArray>(_rootTransform->getValue(kChildren));
}
else
{
// No root transform so just add all root nodes to the scene's children array
childrenArray = std::shared_ptr<GLTF::JSONArray>(new GLTF::JSONArray());
sceneObject->setValue(kNodes, childrenArray);
}
for (size_t i = 0 ; i < nodeCount ; i++) {
std::string nodeUID = nodePointerArray[i]->getOriginalId();
......@@ -956,8 +1016,8 @@ namespace GLTF
break;
}
projectionObject->setDouble("znear", camera->getNearClippingPlane().getValue());
projectionObject->setDouble("zfar", camera->getFarClippingPlane().getValue());
projectionObject->setDouble("znear", camera->getNearClippingPlane().getValue() * _asset->getDistanceScale());
projectionObject->setDouble("zfar", camera->getFarClippingPlane().getValue() * _asset->getDistanceScale());
return true;
}
......@@ -974,13 +1034,47 @@ namespace GLTF
const COLLADABU::URI &imageURI = openCOLLADAImage->getImageURI();
std::string relPathFile = imageURI.getPathFile();
if (imageURI.getPathDir().substr(0,2) != "./") {
relPathFile = imageURI.getPathDir() + imageURI.getPathFile();
} else {
relPathFile = imageURI.getPathDir().substr(2) + imageURI.getPathFile();
}
image->setString("path", this->_asset->resourceOuputPathForPath(relPathFile));
if (imageURI.getPathDir().substr(0, 2) != "./") {
relPathFile = imageURI.getPathDir() + imageURI.getPathFile();
}
else {
relPathFile = imageURI.getPathDir().substr(2) + imageURI.getPathFile();
}
if (_asset->getEmbedResources())
{
COLLADABU::URI inputURI(_asset->getInputFilePath().c_str());
std::string imageFullPath = inputURI.getPathDir() + relPathFile;
std::ifstream fin(imageFullPath, ios::in | ios::binary);
if (fin.is_open())
{
std::ostringstream ss;
ss << fin.rdbuf();
COLLADABU::URI u(imageFullPath);
std::string ext = u.getPathExtension();
std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
std::string contentType = "application/octet-stream";
if (ext == "png")
{
contentType = "image/png";
}
else if (ext == "gif")
{
contentType = "image/gif";
}
else if (ext == "jpg" || ext == "jpeg")
{
contentType = "image/jpeg";
}
image->setString(kURI, create_dataUri(ss.str(), contentType));
return true;
}
}
image->setString(kURI, COLLADABU::URI::uriEncode(this->_asset->resourceOuputPathForPath(relPathFile)));
return true;
}
......
......@@ -45,6 +45,7 @@ namespace GLTF
{
class GLTFObject;
class ExtraDataHandler;
class JSONObject;
// -- SceneFlattening
......@@ -196,6 +197,7 @@ namespace GLTF
SceneFlatteningInfo _sceneFlatteningInfo;
GLTF::ExtraDataHandler *_extraDataHandler;
std::ofstream _compressedDataOutputStream;
std::shared_ptr<GLTF::JSONObject> _rootTransform;
};
}
......
......@@ -221,4 +221,8 @@ namespace GLTF
return this->getUnsignedInt32(kType);
}
std::string GLTFAccessor::valueType() {
return "accessor";
}
}
......@@ -83,6 +83,9 @@ namespace GLTF
bool matchesLayout(GLTFAccessor* meshAttribute);
void exposeMinMax();
virtual std::string valueType();
private:
void _computeMinMaxIfNeeded();
......
......@@ -183,4 +183,9 @@ namespace GLTF
free(rotations);
}
}
std::string GLTFAnimation::valueType() {
return "animation";
}
}
......@@ -64,6 +64,8 @@ namespace GLTF
void writeAnimationForTargetID(const std::string &targetID, GLTFAsset* asset);
virtual std::string valueType();
private:
std::string _id;
std::string _originalID;
......
......@@ -13,7 +13,7 @@ using namespace std::tr1;
using namespace std;
namespace GLTF
{
{
bool writeMeshIndices(shared_ptr <GLTFMesh> mesh, size_t startOffset, GLTFAsset* asset) {
GLTFOutputStream* indicesOutputStream = asset->createOutputStreamIfNeeded(asset->getSharedBufferId()).get();
typedef std::map<std::string , shared_ptr<GLTF::GLTFBuffer> > IDToBufferDef;
......@@ -149,7 +149,11 @@ namespace GLTF
return id;
}
GLTFAsset::GLTFAsset():_isBundle(false) {
GLTFAsset::GLTFAsset() :
_isBundle(false),
_embedResources(false),
_distanceScale(1.0)
{
this->_trackedResourcesPath = shared_ptr<JSONObject> (new JSONObject());
this->_trackedOutputResourcesPath = shared_ptr<JSONObject> (new JSONObject());
this->_converterConfig = shared_ptr<GLTFConfig> (new GLTFConfig());
......@@ -191,14 +195,23 @@ namespace GLTF
shared_ptr<GLTFOutputStream> GLTFAsset::createOutputStreamIfNeeded(const std::string& streamName) {
if (this->_nameToOutputStream.count(streamName) == 0) {
COLLADABU::URI inputURI(this->getInputFilePath().c_str());
COLLADABU::URI outputURI(this->getOutputFilePath().c_str());
std::string folder = outputURI.getPathDir();
std::string fileName = inputURI.getPathFileBase();
shared_ptr<GLTFOutputStream> outputStream = shared_ptr <GLTFOutputStream> (new GLTFOutputStream(folder, streamName, ""));
if (this->_nameToOutputStream.count(streamName) == 0)
{
shared_ptr<GLTFOutputStream> outputStream;
if (_embedResources)
{
outputStream = shared_ptr <GLTFOutputStream>(new GLTFOutputStream());
}
else
{
COLLADABU::URI inputURI(this->getInputFilePath().c_str());
COLLADABU::URI outputURI(this->getOutputFilePath().c_str());
std::string folder = outputURI.getPathDir();
std::string fileName = inputURI.getPathFileBase();
outputStream = shared_ptr <GLTFOutputStream>(new GLTFOutputStream(folder, streamName, ""));
}
this->_nameToOutputStream[streamName] = outputStream;
}
......@@ -211,8 +224,8 @@ namespace GLTF
shared_ptr<GLTFOutputStream> outputStream = this->_nameToOutputStream[streamName];
outputStream->close();
if (removeFile) {
remove(outputStream->outputPathCStr());
if (removeFile) {
outputStream->remove();
}
//FIXME: We keep it around as it's informations are still accessed once close
......@@ -280,13 +293,13 @@ namespace GLTF
outputBundlePathURI.setPath(inputPathURI.getPathDir(), outputBundlePathURI.getPathFileBase(), outputBundlePathURI.getPathExtension());
this->_bundleOutputPath = outputBundlePathURI.toNativePath();
COLLADABU::URI outputPathURI(outputBundlePathURI.getURIString() + "/" + outputBundlePathURI.getPathFileBase() + "." + "json");
COLLADABU::URI outputPathURI(outputBundlePathURI.getURIString() + "/" + outputBundlePathURI.getPathFileBase() + "." + "gltf");
this->_outputFilePath = outputPathURI.toNativePath();
// this->log("outputBundlePath:%s\n",outputBundlePathURI.toNativePath().c_str());
// this->log("outputPath:%s\n",outputPathURI.toNativePath().c_str());
} else {
this->_bundleOutputPath = outputBundlePathURI.toNativePath();
COLLADABU::URI outputPathURI(outputBundlePathURI.getURIString() + "/" + outputBundlePathURI.getPathFileBase() + "." + "json");
COLLADABU::URI outputPathURI(outputBundlePathURI.getURIString() + "/" + outputBundlePathURI.getPathFileBase() + "." + "gltf");
this->_outputFilePath = outputPathURI.toNativePath();
}
COLLADABU::Utils::createDirectoryIfNeeded(this->_bundleOutputPath.c_str());
......@@ -348,6 +361,26 @@ namespace GLTF
std::string GLTFAsset::getInputFilePath() {
return this->_inputFilePath;
}
void GLTFAsset::setEmbedResources(bool embedResources)
{
this->_embedResources = embedResources;
}
bool GLTFAsset::getEmbedResources()
{
return this->_embedResources;
}
void GLTFAsset::setDistanceScale(double distanceScale)
{
this->_distanceScale = distanceScale;
}
double GLTFAsset::getDistanceScale()
{
return this->_distanceScale;
}
std::string GLTFAsset::pathRelativeToInputPath(const std::string& path) {
if (GLTFUtils::isAbsolutePath(path) == true) {
......@@ -368,7 +401,7 @@ namespace GLTF
std::vector <std::string> keys = images->getAllKeys();
for (size_t i = 0 ; i < imagesCount ; i++) {
shared_ptr<JSONObject> image = images->getObject(keys[i]);
std::string path = image->getString("path");
std::string path = image->getString(kURI);
std::string originalPath = this->_originalResourcesPath->getString(path);
......@@ -401,10 +434,47 @@ namespace GLTF
this->_writer.initWithPath(this->getOutputFilePath().c_str());
}
static void __eval(JSONValue* value, void *context) {
//FIXME:legacy
static void __eval(JSONValue* value, void* context) {
value->evaluate(context);
}
void GLTFAsset::evaluationWillStart(GLTFAsset* asset) {
}
void GLTFAsset::evaluate(JSONValue* value, GLTFAsset* asset) {
}
void GLTFAsset::evaluationDidComplete(GLTFAsset* asset) {
}
void GLTFAsset::_performValuesEvaluation() {
size_t count = this->_evaluators.size();
for (size_t i = 0 ; i < count ; i++) {
this->_evaluators[i]->evaluationWillStart(this);
}
//these apply MUST be before the removeValue lightsIds that follows
this->_root->apply(__eval, this);
this->_root->apply(this, this);
this->_root->removeValue("lightsIds");
for (size_t i = 0 ; i < count ; i++) {
this->_evaluators[i]->evaluationDidComplete(this);
}
this->_root->write(&this->_writer, this);
}
void GLTFAsset::apply(JSONValue* value, void *context) {
size_t count = this->_evaluators.size();
for (size_t i = 0 ; i < count ; i++) {
this->_evaluators[i]->evaluate(value, (GLTFAsset*)context);
}
}
std::string GLTFAsset::getSharedBufferId() {
if (this->_sharedBufferId.length() == 0) {
COLLADABU::URI inputURI(this->getInputFilePath().c_str());
......@@ -753,6 +823,17 @@ namespace GLTF
return true;
}
void GLTFAsset::addValueEvaluator(std::shared_ptr<GLTFAssetValueEvaluator> evaluator) {
this->_evaluators.push_back(evaluator);
}
void GLTFAsset::removeValueEvaluator(std::shared_ptr<GLTFAssetValueEvaluator> evaluator) {
std::vector <std::shared_ptr<GLTFAssetValueEvaluator>>::iterator iter = std::find(this->_evaluators.begin(), this->_evaluators.end(), evaluator);
if (iter != this->_evaluators.end()) {
this->_evaluators.erase(iter);
}
}
void GLTFAsset::write() {
ifstream inputCompression;
......@@ -1040,7 +1121,9 @@ namespace GLTF
this->_root->setValue("buffers", buffersObject);
if (sharedBuffer->getByteLength() > 0) {
sharedBuffer->setString(kPath, this->getSharedBufferId() + ".bin");
COLLADABU::URI uri(rawOutputStream->outputPath());
sharedBuffer->setString(kURI, COLLADABU::URI::uriEncode(uri.getPathFile()));
sharedBuffer->setString(kType, "arraybuffer");
buffersObject->setValue(this->getSharedBufferId(), sharedBuffer);
}
......@@ -1048,7 +1131,7 @@ namespace GLTF
if (compressionBuffer->getByteLength() > 0) {
std::string compressedBufferID = compressionOutputStream->id();
buffersObject->setValue(compressedBufferID, compressionBuffer);
compressionBuffer->setString(kPath, compressedBufferID + ".bin");
compressionBuffer->setString(kURI, COLLADABU::URI::uriEncode(compressionOutputStream->outputPath()));
if (converterConfig()->config()->getString("compressionMode") == "ascii")
compressionBuffer->setString(kType, "text");
else
......@@ -1072,19 +1155,18 @@ namespace GLTF
verticesBufferView->setUnsignedInt32(kTarget, this->_profile->getGLenumForString("ARRAY_BUFFER"));
//---
//this apply MUST be before the removeValue lightsIds that follows
this->_root->apply(__eval, this);
this->_root->removeValue("lightsIds");
//to run legacy evaluate, to be removed
this->addValueEvaluator(shared_ptr<GLTFAssetValueEvaluator> (this));
this->_root->write(&this->_writer, this);
this->_performValuesEvaluation();
rawOutputStream->close();
if (compressionLength == 0) {
this->closeOutputStream(kCompressionOutputStream, true);
}
if (sharedBuffer->getByteLength() == 0)
remove(rawOutputStream->outputPathCStr());
if (sharedBuffer->getByteLength() == 0)
rawOutputStream->remove();
this->convertionResults()->setUnsignedInt32(kGeometry, (unsigned int)this->getGeometryByteLength());
this->convertionResults()->setUnsignedInt32(kAnimation, (unsigned int)this->getAnimationByteLength());
......
......@@ -7,6 +7,18 @@
namespace GLTF
{
class GLTFAsset;
class GLTFAssetValueEvaluator {
public:
//evaluate is mandatory
virtual void evaluationWillStart(GLTFAsset*) {};
virtual void evaluate(JSONValue* value, GLTFAsset* asset) = 0;
virtual void evaluationDidComplete(GLTFAsset*) {};
virtual ~GLTFAssetValueEvaluator() {};
};
#define CONFIG_BOOL(asset,X) (asset->converterConfig()->config()->getBool(X))
#define CONFIG_STRING(asset, X) (asset->converterConfig()->config()->getString(X))
#define CONFIG_DOUBLE(asset, X) (asset->converterConfig()->config()->getDouble(X))
......@@ -47,7 +59,7 @@ namespace GLTF
typedef std::map<std::string, std::shared_ptr <MaterialBindingsPrimitiveMap> > MaterialBindingsForMeshUID;
typedef std::map<std::string, std::shared_ptr <MaterialBindingsForMeshUID> > MaterialBindingsForNodeUID;
class COLLADA2GLTF_EXPORT GLTFAsset
class COLLADA2GLTF_EXPORT GLTFAsset : public GLTFAssetValueEvaluator, public JSONValueApplier
{
public:
GLTFAsset();
......@@ -84,6 +96,12 @@ namespace GLTF
void setInputFilePath(const std::string& inputFilePath);
std::string getInputFilePath();
void setEmbedResources(bool embedResources);
bool getEmbedResources();
void setDistanceScale(double distanceScale);
double getDistanceScale();
std::string pathRelativeToInputPath(const std::string& path);
void copyImagesInsideBundleIfNeeded();
......@@ -106,9 +124,20 @@ namespace GLTF
std::shared_ptr<JSONObject> getExtras();
void setExtras(std::shared_ptr<JSONObject>);
void addValueEvaluator(std::shared_ptr<GLTFAssetValueEvaluator> evaluator);
void removeValueEvaluator(std::shared_ptr<GLTFAssetValueEvaluator> evaluator);
//as an GLTFAssetValueEvaluator
virtual void evaluationWillStart(GLTFAsset*);
virtual void evaluate(JSONValue* value, GLTFAsset* asset);
virtual void evaluationDidComplete(GLTFAsset*);
void apply(JSONValue* value, void *context);
protected:
void launchModifiers();
private:
void _performValuesEvaluation();
bool _applyMaterialBindingsForNode(const std::string& nodeUID);
void _applyMaterialBindings(std::shared_ptr<GLTFMesh> mesh,
std::shared_ptr <MaterialBindingsPrimitiveMap> materialBindingPrimitiveMap,
......@@ -153,6 +182,8 @@ namespace GLTF
size_t _geometryByteLength;
size_t _animationByteLength;
bool _isBundle;
bool _embedResources;
double _distanceScale;
UniqueIDToJSONValue _uniqueIDToJSONValue;
......@@ -162,6 +193,8 @@ namespace GLTF
std::vector <std::shared_ptr<GLTFAssetModifier> > _assetModifiers;
MaterialBindingsForNodeUID _materialBindingsForNodeUID;
std::vector <std::shared_ptr<GLTFAssetValueEvaluator>> _evaluators;
};
std::string uniqueIdWithType(std::string type, const COLLADAFW::UniqueId& uniqueId);
......
......@@ -69,7 +69,7 @@ namespace GLTF
//FIXME:this would be better somewhere else..
GLTFAsset* asset = (GLTFAsset*)context;
this->setString(kPath, asset->resourceOuputPathForPath(this->getString(kPath)));
this->setString(kURI, COLLADABU::URI::uriEncode(asset->resourceOuputPathForPath(this->getString(kURI))));
}
size_t GLTFBuffer::getByteLength() {
......@@ -84,9 +84,11 @@ namespace GLTF
return this->_data;
}
//--- GLTFBufferView