1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
|
/* Copyright (C) 2015 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INCLUDED_COMMONCONVERT
#define INCLUDED_COMMONCONVERT
#include <exception>
#include <string>
#include <memory>
#include <vector>
class FCDEntityInstance;
class FCDSceneNode;
class FCDSkinController;
class FMMatrix44;
class FUStatus;
class Skeleton;
class ColladaException : public std::exception
{
public:
ColladaException(const std::string& msg) : msg(msg) { }
~ColladaException() throw() { }
virtual const char* what() const throw() { return msg.c_str(); }
private:
std::string msg;
};
struct OutputCB
{
virtual ~OutputCB() { }
virtual void operator() (const char* data, unsigned int length)=0;
};
/**
* Standard error handler - logs FCollada messages using Log(), and also
* maintains a list of XML parser errors.
*/
class FColladaErrorHandler
{
public:
FColladaErrorHandler(std::string& xmlErrors);
~FColladaErrorHandler();
private:
void OnError(FUError::Level errorLevel, uint32 errorCode, uint32 lineNumber);
std::string& xmlErrors;
void operator=(FColladaErrorHandler);
};
/**
* Standard document loader. Based on FCDocument::LoadFromText, but allows
* access to \<extra\> nodes at the document level (i.e. directly in \<COLLADA\>).
*/
class FColladaDocument
{
public:
/**
* Loads the document from the given XML string. Should be the first function
* called on this object, and should only be called once.
* @throws ColladaException if unable to load.
*/
void LoadFromText(const char* text);
/** Returns the FCDocument that was loaded. */
FCDocument* GetDocument() const { return document.get(); }
/** Returns the \<extra\> data from the \<COLLADA\> element. */
FCDExtra* GetExtra() const { return extra.get(); }
private:
void ReadExtras(xmlNode* colladaNode);
std::unique_ptr<FCDocument> document;
std::unique_ptr<FCDExtra> extra;
};
/**
* Wrapper for code shared between the PMD and PSA converters. Loads the document
* and provides access to the relevant objects and values.
*/
class CommonConvert
{
public:
CommonConvert(const char* text, std::string& xmlErrors);
~CommonConvert();
const FColladaDocument& GetDocument() const { return m_Doc; }
FCDSceneNode& GetRoot() { return *m_Doc.GetDocument()->GetVisualSceneRoot(); }
FCDEntityInstance& GetInstance() { return *m_Instance; }
const FMMatrix44& GetEntityTransform() const { return m_EntityTransform; }
bool IsYUp() const { return m_YUp; }
bool IsXSI() const { return m_IsXSI; }
private:
FColladaErrorHandler m_Err;
FColladaDocument m_Doc;
FCDEntityInstance* m_Instance;
FMMatrix44 m_EntityTransform;
bool m_YUp;
bool m_IsXSI;
};
/** Throws a ColladaException unless the value is true. */
#define REQUIRE(value, message) require_(__LINE__, value, "Assertion not satisfied", "failed requirement \"" message "\"")
/** Throws a ColladaException unless the status is successful. */
#define REQUIRE_SUCCESS(status) require_(__LINE__, status, "FCollada error", "Line " STRINGIFY(__LINE__))
#define STRINGIFY(x) #x
void require_(int line, bool value, const char* type, const char* message);
/** Outputs a structure, using sizeof to get the size. */
template<typename T> void write(OutputCB& output, const T& data)
{
output((char*)&data, sizeof(T));
}
/**
* Tries to find a single suitable entity instance in the scene. Fails if there
* are none, or if there are too many and it's not clear which one should
* be converted.
*
* @param node root scene node to search under
* @param instance output - the found entity instance (if any)
* @param transform - the world-space transform of the found entity
*
* @return true if one was found
*/
bool FindSingleInstance(FCDSceneNode* node, FCDEntityInstance*& instance, FMMatrix44& transform);
/**
* Like FCDSkinController::ReduceInfluences but works correctly.
* Additionally, multiple influences for the same joint-vertex pair are
* collapsed into a single influence.
*/
void SkinReduceInfluences(FCDSkinController* skin, size_t maxInfluenceCount, float minimumWeight);
/**
* Fixes some occasional problems with the skeleton root definitions in a
* controller. (In particular, it's needed for models exported from XSI.)
* Should be called before extracting any joint information from the controller.
*/
void FixSkeletonRoots(FCDControllerInstance& controllerInstance);
/**
* Finds the skeleton definition which best matches the given controller.
* @throws ColladaException if none is found.
*/
const Skeleton& FindSkeleton(const FCDControllerInstance& controllerInstance);
/** Bone pose data */
struct BoneTransform
{
float translation[3];
float orientation[4];
};
/**
* Performs the standard transformations on bones, applying a scale matrix and
* moving them into the game's coordinate space.
*/
void TransformBones(std::vector<BoneTransform>& bones, const FMMatrix44& scaleTransform, bool yUp);
extern FMMatrix44 FMMatrix44_Identity;
#endif // INCLUDED_COMMONCONVERT
|