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