vrshoot
view libs/assimp/CSMLoader.cpp @ 3:c179c72369be
rename candy->vr
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Mon, 03 Feb 2014 08:52:13 +0200 |
parents | |
children |
line source
1 /*
2 ---------------------------------------------------------------------------
3 Open Asset Import Library (assimp)
4 ---------------------------------------------------------------------------
6 Copyright (c) 2006-2012, assimp team
8 All rights reserved.
10 Redistribution and use of this software in source and binary forms,
11 with or without modification, are permitted provided that the following
12 conditions are met:
14 * Redistributions of source code must retain the above
15 copyright notice, this list of conditions and the
16 following disclaimer.
18 * Redistributions in binary form must reproduce the above
19 copyright notice, this list of conditions and the
20 following disclaimer in the documentation and/or other
21 materials provided with the distribution.
23 * Neither the name of the assimp team, nor the names of its
24 contributors may be used to endorse or promote products
25 derived from this software without specific prior
26 written permission of the assimp team.
28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 ---------------------------------------------------------------------------
40 */
42 /** @file CSMLoader.cpp
43 * Implementation of the CSM importer class.
44 */
46 #include "AssimpPCH.h"
48 #ifndef ASSIMP_BUILD_NO_CSM_IMPORTER
50 #include "CSMLoader.h"
51 #include "SkeletonMeshBuilder.h"
52 #include "ParsingUtils.h"
53 #include "fast_atof.h"
55 using namespace Assimp;
57 static const aiImporterDesc desc = {
58 "CharacterStudio Motion Importer (MoCap)",
59 "",
60 "",
61 "",
62 aiImporterFlags_SupportTextFlavour,
63 0,
64 0,
65 0,
66 0,
67 "csm"
68 };
71 // ------------------------------------------------------------------------------------------------
72 // Constructor to be privately used by Importer
73 CSMImporter::CSMImporter()
74 : noSkeletonMesh()
75 {}
77 // ------------------------------------------------------------------------------------------------
78 // Destructor, private as well
79 CSMImporter::~CSMImporter()
80 {}
82 // ------------------------------------------------------------------------------------------------
83 // Returns whether the class can handle the format of the given file.
84 bool CSMImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
85 {
86 // check file extension
87 const std::string extension = GetExtension(pFile);
89 if( extension == "csm")
90 return true;
92 if ((checkSig || !extension.length()) && pIOHandler) {
93 const char* tokens[] = {"$Filename"};
94 return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
95 }
96 return false;
97 }
99 // ------------------------------------------------------------------------------------------------
100 // Build a string of all file extensions supported
101 const aiImporterDesc* CSMImporter::GetInfo () const
102 {
103 return &desc;
104 }
106 // ------------------------------------------------------------------------------------------------
107 // Setup configuration properties for the loader
108 void CSMImporter::SetupProperties(const Importer* pImp)
109 {
110 noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
111 }
113 // ------------------------------------------------------------------------------------------------
114 // Imports the given file into the given scene structure.
115 void CSMImporter::InternReadFile( const std::string& pFile,
116 aiScene* pScene, IOSystem* pIOHandler)
117 {
118 boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
120 // Check whether we can read from the file
121 if( file.get() == NULL) {
122 throw DeadlyImportError( "Failed to open CSM file " + pFile + ".");
123 }
125 // allocate storage and copy the contents of the file to a memory buffer
126 std::vector<char> mBuffer2;
127 TextFileToBuffer(file.get(),mBuffer2);
128 const char* buffer = &mBuffer2[0];
130 aiAnimation* anim = new aiAnimation();
131 int first = 0, last = 0x00ffffff;
133 // now process the file and look out for '$' sections
134 while (1) {
135 SkipSpaces(&buffer);
136 if ('\0' == *buffer)
137 break;
139 if ('$' == *buffer) {
140 ++buffer;
141 if (TokenMatchI(buffer,"firstframe",10)) {
142 SkipSpaces(&buffer);
143 first = strtol10(buffer,&buffer);
144 }
145 else if (TokenMatchI(buffer,"lastframe",9)) {
146 SkipSpaces(&buffer);
147 last = strtol10(buffer,&buffer);
148 }
149 else if (TokenMatchI(buffer,"rate",4)) {
150 SkipSpaces(&buffer);
151 float d;
152 buffer = fast_atoreal_move<float>(buffer,d);
153 anim->mTicksPerSecond = d;
154 }
155 else if (TokenMatchI(buffer,"order",5)) {
156 std::vector< aiNodeAnim* > anims_temp;
157 anims_temp.reserve(30);
158 while (1) {
159 SkipSpaces(&buffer);
160 if (IsLineEnd(*buffer) && SkipSpacesAndLineEnd(&buffer) && *buffer == '$')
161 break; // next section
163 // Construct a new node animation channel and setup its name
164 anims_temp.push_back(new aiNodeAnim());
165 aiNodeAnim* nda = anims_temp.back();
167 char* ot = nda->mNodeName.data;
168 while (!IsSpaceOrNewLine(*buffer))
169 *ot++ = *buffer++;
171 *ot = '\0';
172 nda->mNodeName.length = (size_t)(ot-nda->mNodeName.data);
173 }
175 anim->mNumChannels = anims_temp.size();
176 if (!anim->mNumChannels)
177 throw DeadlyImportError("CSM: Empty $order section");
179 // copy over to the output animation
180 anim->mChannels = new aiNodeAnim*[anim->mNumChannels];
181 ::memcpy(anim->mChannels,&anims_temp[0],sizeof(aiNodeAnim*)*anim->mNumChannels);
182 }
183 else if (TokenMatchI(buffer,"points",6)) {
184 if (!anim->mNumChannels)
185 throw DeadlyImportError("CSM: \'$order\' section is required to appear prior to \'$points\'");
187 // If we know how many frames we'll read, we can preallocate some storage
188 unsigned int alloc = 100;
189 if (last != 0x00ffffff)
190 {
191 alloc = last-first;
192 alloc += alloc>>2u; // + 25%
193 for (unsigned int i = 0; i < anim->mNumChannels;++i)
194 anim->mChannels[i]->mPositionKeys = new aiVectorKey[alloc];
195 }
197 unsigned int filled = 0;
199 // Now read all point data.
200 while (1) {
201 SkipSpaces(&buffer);
202 if (IsLineEnd(*buffer) && (!SkipSpacesAndLineEnd(&buffer) || *buffer == '$')) {
203 break; // next section
204 }
206 // read frame
207 const int frame = ::strtoul10(buffer,&buffer);
208 last = std::max(frame,last);
209 first = std::min(frame,last);
210 for (unsigned int i = 0; i < anim->mNumChannels;++i) {
212 aiNodeAnim* s = anim->mChannels[i];
213 if (s->mNumPositionKeys == alloc) { /* need to reallocate? */
215 aiVectorKey* old = s->mPositionKeys;
216 s->mPositionKeys = new aiVectorKey[s->mNumPositionKeys = alloc*2];
217 ::memcpy(s->mPositionKeys,old,sizeof(aiVectorKey)*alloc);
218 delete[] old;
219 }
221 // read x,y,z
222 if(!SkipSpacesAndLineEnd(&buffer))
223 throw DeadlyImportError("CSM: Unexpected EOF occured reading sample x coord");
225 if (TokenMatchI(buffer, "DROPOUT", 7)) {
226 // seems this is invalid marker data; at least the doc says it's possible
227 DefaultLogger::get()->warn("CSM: Encountered invalid marker data (DROPOUT)");
228 }
229 else {
230 aiVectorKey* sub = s->mPositionKeys + s->mNumPositionKeys;
231 sub->mTime = (double)frame;
232 buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.x);
234 if(!SkipSpacesAndLineEnd(&buffer))
235 throw DeadlyImportError("CSM: Unexpected EOF occured reading sample y coord");
236 buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.y);
238 if(!SkipSpacesAndLineEnd(&buffer))
239 throw DeadlyImportError("CSM: Unexpected EOF occured reading sample z coord");
240 buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.z);
242 ++s->mNumPositionKeys;
243 }
244 }
246 // update allocation granularity
247 if (filled == alloc)
248 alloc *= 2;
250 ++filled;
251 }
252 // all channels must be complete in order to continue safely.
253 for (unsigned int i = 0; i < anim->mNumChannels;++i) {
255 if (!anim->mChannels[i]->mNumPositionKeys)
256 throw DeadlyImportError("CSM: Invalid marker track");
257 }
258 }
259 }
260 else {
261 // advance to the next line
262 SkipLine(&buffer);
263 }
264 }
266 // Setup a proper animation duration
267 anim->mDuration = last - std::min( first, 0 );
269 // build a dummy root node with the tiny markers as children
270 pScene->mRootNode = new aiNode();
271 pScene->mRootNode->mName.Set("$CSM_DummyRoot");
273 pScene->mRootNode->mNumChildren = anim->mNumChannels;
274 pScene->mRootNode->mChildren = new aiNode* [anim->mNumChannels];
276 for (unsigned int i = 0; i < anim->mNumChannels;++i) {
277 aiNodeAnim* na = anim->mChannels[i];
279 aiNode* nd = pScene->mRootNode->mChildren[i] = new aiNode();
280 nd->mName = anim->mChannels[i]->mNodeName;
281 nd->mParent = pScene->mRootNode;
283 aiMatrix4x4::Translation(na->mPositionKeys[0].mValue, nd->mTransformation);
284 }
286 // Store the one and only animation in the scene
287 pScene->mAnimations = new aiAnimation*[pScene->mNumAnimations=1];
288 pScene->mAnimations[0] = anim;
289 anim->mName.Set("$CSM_MasterAnim");
291 // mark the scene as incomplete and run SkeletonMeshBuilder on it
292 pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
294 if (!noSkeletonMesh) {
295 SkeletonMeshBuilder maker(pScene,pScene->mRootNode,true);
296 }
297 }
299 #endif // !! ASSIMP_BUILD_NO_CSM_IMPORTER