Subversion Repository Public Repository

Divide-Framework

This repository has no backups
This repository's network speed is throttled to 100KB/sec

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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
#include "Headers/MeshImporter.h"
#include "Headers/DVDConverter.h"

#include "Core/Headers/Console.h"
#include "Core/Time/Headers/ProfileTimer.h"
#include "Core/Resources/Headers/ResourceCache.h"

#include "Geometry/Shapes/Headers/Mesh.h"
#include "Geometry/Shapes/Headers/SkinnedSubMesh.h"
#include "Utility/Headers/Localization.h"

namespace Divide {

namespace {
    const stringImpl g_parsedAssetLocation("parsed");
    const stringImpl g_parsedAssetGeometryExt("DVDGeom");
    const stringImpl g_parsedAssetAnimationExt("DVDAnim");
};

namespace Import {
    ImportData::~ImportData()
    {
        MemoryManager::SAFE_DELETE(_vertexBuffer);
    }

    bool ImportData::saveToFile(const stringImpl& fileName) {
        ByteBuffer tempBuffer;
        assert(_vertexBuffer != nullptr);
        tempBuffer << stringImpl("BufferEntryPoint");
        tempBuffer << _modelName;
        tempBuffer << _modelPath;
        _vertexBuffer->serialize(tempBuffer);
        tempBuffer << to_uint(_subMeshData.size());
        for (const SubMeshData& subMesh : _subMeshData) {
            if (!subMesh.serialize(tempBuffer)) {
                //handle error
            }
        }
        tempBuffer << _hasAnimations;
        // Animations are handled by the SceneAnimator I/O
        return tempBuffer.dumpToFile(fileName + "." + g_parsedAssetGeometryExt);
    }

    bool ImportData::loadFromFile(const stringImpl& fileName) {
        ByteBuffer tempBuffer;
        if (tempBuffer.loadFromFile(fileName + "." + g_parsedAssetGeometryExt)) {
            stringImpl signature;
            tempBuffer >> signature;
            if (signature.compare("BufferEntryPoint") != 0) {
                return false;
            }
            tempBuffer >> _modelName;
            tempBuffer >> _modelPath;
            _vertexBuffer = GFX_DEVICE.newVB();
            _vertexBuffer->deserialize(tempBuffer);
            U32 subMeshCount = 0;
            tempBuffer >> subMeshCount;
            _subMeshData.resize(subMeshCount);
            for (SubMeshData& subMesh : _subMeshData) {
                if (!subMesh.deserialize(tempBuffer)) {
                    //handle error
                    DIVIDE_UNEXPECTED_CALL();
                }
            }
            tempBuffer >> _hasAnimations;
            _loadedFromFile = true;
            return true;
        }
        return false;
    }

    bool SubMeshData::serialize(ByteBuffer& dataOut) const {
        dataOut << _name;
        dataOut << _index;
        dataOut << _boneCount;
        dataOut << _partitionOffset;
        dataOut << _minPos;
        dataOut << _maxPos;
        dataOut << _triangles;
        return _material.serialize(dataOut);
    }

    bool SubMeshData::deserialize(ByteBuffer& dataIn) {
        dataIn >> _name;
        dataIn >> _index;
        dataIn >> _boneCount;
        dataIn >> _partitionOffset;
        dataIn >> _minPos;
        dataIn >> _maxPos;
        dataIn >> _triangles;
        return _material.deserialize(dataIn);
    }

    bool MaterialData::serialize(ByteBuffer& dataOut) const {
        dataOut << _ignoreAlpha;
        dataOut << _doubleSided;
        dataOut << _name;
        dataOut << _shadingData._diffuse;
        dataOut << _shadingData._specular;
        dataOut << _shadingData._emissive;
        dataOut << _shadingData._shininess;
        dataOut << _shadingData._textureCount;
        dataOut << to_uint(_shadingMode);
        dataOut << to_uint(_bumpMethod);
        for (const TextureEntry& texture : _textures) {
            if (!texture.serialize(dataOut)) {
                //handle error
                DIVIDE_UNEXPECTED_CALL();
            }
        }

        return true;
    }

    bool MaterialData::deserialize(ByteBuffer& dataIn) {
        U32 temp = 0;
        dataIn >> _ignoreAlpha;
        dataIn >> _doubleSided;
        dataIn >> _name;
        dataIn >> _shadingData._diffuse;
        dataIn >> _shadingData._specular;
        dataIn >> _shadingData._emissive;
        dataIn >> _shadingData._shininess;
        dataIn >> _shadingData._textureCount;
        dataIn >> temp;
        _shadingMode = static_cast<Material::ShadingMode>(temp);
        dataIn >> temp;
        _bumpMethod = static_cast<Material::BumpMethod>(temp);
        for (TextureEntry& texture : _textures) {
            if (!texture.deserialize(dataIn)) {
                //handle error
                DIVIDE_UNEXPECTED_CALL();
            }
        }

        return true;
    }

    bool TextureEntry::serialize(ByteBuffer& dataOut) const {
        dataOut << _textureName;
        dataOut << _texturePath;
        dataOut << _srgbSpace;
        dataOut << to_uint(_wrapU);
        dataOut << to_uint(_wrapV);
        dataOut << to_uint(_wrapW);
        dataOut << to_uint(_operation);
        return true;
    }

    bool TextureEntry::deserialize(ByteBuffer& dataIn) {
        U32 data = 0;
        dataIn >> _textureName;
        dataIn >> _texturePath;
        dataIn >> _srgbSpace;
        dataIn >> data;
        _wrapU = static_cast<TextureWrap>(data);
        dataIn >> data;
        _wrapV = static_cast<TextureWrap>(data);
        dataIn >> data;
        _wrapW = static_cast<TextureWrap>(data);
        dataIn >> data;
        _operation = static_cast<Material::TextureOperation>(data);
        return true;
    }
};
    bool MeshImporter::loadMeshDataFromFile(Import::ImportData& dataOut) {
        Time::ProfileTimer importTimer;
        importTimer.start();

        stringImpl modelName = dataOut._modelPath.substr(dataOut._modelPath.find_last_of('/') + 1);
        stringImpl path = dataOut._modelPath.substr(0, dataOut._modelPath.find_last_of('/'));

        bool success = false;
        if (!dataOut.loadFromFile(path + "/" + g_parsedAssetLocation + "/" + modelName)) {
            Console::printfn(Locale::get(_ID("MESH_NOT_LOADED_FROM_FILE")), modelName.c_str());

            DVDConverter converter(dataOut, dataOut._modelPath, success);
            if (success) {
                dataOut._modelName = modelName;
                dataOut._modelPath = path;
                if (dataOut.saveToFile(path + "/" + g_parsedAssetLocation + "/" + modelName)) {
                    Console::printfn(Locale::get(_ID("MESH_SAVED_TO_FILE")), modelName.c_str());
                } else {
                    Console::printfn(Locale::get(_ID("MESH_NOT_SAVED_TO_FILE")), modelName.c_str());
                }
            }
        } else {
            Console::printfn(Locale::get(_ID("MESH_LOADED_FROM_FILE")), modelName.c_str());
            success = true;
        }

        importTimer.stop();
        Console::d_printfn(Locale::get(_ID("LOAD_MESH_TIME")),
                           modelName.c_str(),
                           Time::MillisecondsToSeconds(importTimer.get()));

        return success;
    }

    Mesh_ptr MeshImporter::loadMesh(const stringImpl& name, const Import::ImportData& dataIn) {
        Time::ProfileTimer importTimer;
        importTimer.start();

        std::shared_ptr<SceneAnimator> animator;
        if (dataIn._hasAnimations) {
            ByteBuffer tempBuffer;
            animator.reset(new SceneAnimator());
            if (tempBuffer.loadFromFile(dataIn._modelPath + "/" + 
                                        g_parsedAssetLocation + "/" +
                                        dataIn._modelName + "." +
                                        g_parsedAssetAnimationExt)) {
                animator->load(tempBuffer);
            } else {
                if (!dataIn._loadedFromFile) {
                    for (const std::shared_ptr<AnimEvaluator>& animation : dataIn._animations) {
                        animator->registerAnimation(animation);
                    }
                    animator->init(dataIn._skeleton, dataIn._bones);
                    animator->save(tempBuffer);
                    if (!tempBuffer.dumpToFile(dataIn._modelPath + "/" + 
                                               g_parsedAssetLocation + "/" +
                                               dataIn._modelName + "." +
                                               g_parsedAssetAnimationExt)) {
                        //handle error
                        DIVIDE_UNEXPECTED_CALL();
                    }
                } else {
                    //handle error. No ASSIMP animation data available
                    DIVIDE_UNEXPECTED_CALL();
                }
            }
        }

        Mesh_ptr mesh(MemoryManager_NEW Mesh(name,
                                             dataIn._modelPath,
                                             dataIn._hasAnimations
                                                 ? Object3D::ObjectFlag::OBJECT_FLAG_SKINNED
                                                 : Object3D::ObjectFlag::OBJECT_FLAG_NONE),
                                DeleteResource());
        if (dataIn._hasAnimations) {
            mesh->setAnimator(animator);
            animator = nullptr;
        }

        mesh->renderState().setDrawState(true);
        mesh->getGeometryVB()->fromBuffer(*dataIn._vertexBuffer);

        SubMesh_ptr tempSubMesh;
        for (const Import::SubMeshData& subMeshData : dataIn._subMeshData) {
            // Submesh is created as a resource when added to the scenegraph
            ResourceDescriptor submeshdesc(subMeshData._name);
            submeshdesc.setFlag(true);
            submeshdesc.setID(subMeshData._index);
            if (subMeshData._boneCount > 0) {
                submeshdesc.setEnumValue(to_const_uint(Object3D::ObjectFlag::OBJECT_FLAG_SKINNED));
            }

            tempSubMesh = CreateResource<SubMesh>(submeshdesc);
            if (!tempSubMesh) {
                continue;
            }
            // it may already be loaded
            if (!tempSubMesh->getParentMesh()) {
                for (const vec3<U32>& triangle : subMeshData._triangles) {
                    tempSubMesh->addTriangle(triangle);
                }
                tempSubMesh->setGeometryPartitionID(subMeshData._partitionOffset);
                Attorney::SubMeshMeshImporter::setGeometryLimits(*tempSubMesh,
                                                                 subMeshData._minPos,
                                                                 subMeshData._maxPos);

                if (!tempSubMesh->getMaterialTpl()) {
                    tempSubMesh->setMaterialTpl(loadSubMeshMaterial(subMeshData._material, subMeshData._boneCount > 0));
                }
            }

            mesh->addSubMesh(tempSubMesh);
        }

        mesh->getGeometryVB()->create(!mesh->getObjectFlag(Object3D::ObjectFlag::OBJECT_FLAG_SKINNED));
        
        importTimer.stop();
        Console::d_printfn(Locale::get(_ID("PARSE_MESH_TIME")),
                           dataIn._modelName.c_str(),
                           Time::MillisecondsToSeconds(importTimer.get()));

        return mesh;
    }

    /// Load the material for the current SubMesh
    Material_ptr MeshImporter::loadSubMeshMaterial(const Import::MaterialData& importData, bool skinned) {
        // See if the material already exists in a cooked state (XML file)
        STUBBED("LOADING MATERIALS FROM XML IS DISABLED FOR NOW! - Ionut")
#if !defined(DEBUG)
            const bool DISABLE_MAT_FROM_FILE = true;
#else
            const bool DISABLE_MAT_FROM_FILE = true;
#endif

        Material_ptr tempMaterial;
        if (!DISABLE_MAT_FROM_FILE) {
            tempMaterial = XML::loadMaterial(importData._name);
            if (tempMaterial) {
                return tempMaterial;
            }
        }

        // If it's not defined in an XML File, see if it was previously loaded by
        // the Resource Cache
        tempMaterial = FindResourceImpl<Material>(importData._name);
        if (tempMaterial) {
            return tempMaterial;
        }

        // If we found it in the Resource Cache, return a copy of it
        ResourceDescriptor materialDesc(importData._name);
        if (skinned) {
            materialDesc.setEnumValue(
                to_const_uint(Object3D::ObjectFlag::OBJECT_FLAG_SKINNED));
        }

        tempMaterial = CreateResource<Material>(materialDesc);

        tempMaterial->setShaderData(importData._shadingData);
        tempMaterial->setShadingMode(importData._shadingMode);
        tempMaterial->setBumpMethod(importData._bumpMethod);
        tempMaterial->setDoubleSided(importData._doubleSided);

        SamplerDescriptor textureSampler;
        for (U32 i = 0; i < to_const_uint(ShaderProgram::TextureUsage::COUNT); ++i) {
            const Import::TextureEntry& tex = importData._textures[i];
            if (!tex._textureName.empty()) {
                textureSampler.toggleSRGBColourSpace(tex._srgbSpace);
                textureSampler.setWrapMode(tex._wrapU, tex._wrapV, tex._wrapW);

                ResourceDescriptor texture(tex._textureName);
                texture.setResourceLocation(tex._texturePath);
                texture.setPropertyDescriptor<SamplerDescriptor>(textureSampler);
                texture.setEnumValue(to_const_uint(TextureType::TEXTURE_2D));
                Texture_ptr textureRes = CreateResource<Texture>(texture);
                assert(textureRes != nullptr);

                tempMaterial->setTexture(static_cast<ShaderProgram::TextureUsage>(i), textureRes, tex._operation);
            }
        }

        // If we don't have a valid opacity map, try to find out whether the diffuse texture has any non-opaque pixels.
        // If we find a few, use it as opacity texture
        if (!importData._ignoreAlpha && importData._textures[to_const_uint(ShaderProgram::TextureUsage::OPACITY)]._textureName.empty()) {
            Texture_ptr diffuse = tempMaterial->getTexture(ShaderProgram::TextureUsage::UNIT0).lock();
            if (diffuse && diffuse->hasTransparency()) {
                Texture_ptr textureRes = CreateResource<Texture>(ResourceDescriptor(diffuse->getName()));
                tempMaterial->setTexture(ShaderProgram::TextureUsage::OPACITY, textureRes, Material::TextureOperation::REPLACE);
            }
        }
        
        return tempMaterial;
    }
}; //namespace Divide

Commits for Divide-Framework/trunk/Source Code/Geometry/Importer/MeshImporter.cpp

Diff revisions: vs.
Revision Author Commited Message
727 Diff Diff IonutCava picture IonutCava Tue 14 Jun, 2016 16:01:38 +0000

[IonutCava]
- Remove node and cmd buffers from GFXDevice and add them as a new BufferData struct to RenderPass class.
— Each render pass holds its own buffers
- Improvements / fixes to the CSM code
- Added a global toggle to enable/disable custom memory allocators

721 Diff Diff IonutCava picture IonutCava Wed 08 Jun, 2016 15:47:49 +0000

[IonutCava]
- Spelling: change all references from our code of “color” to the PROPER British version of “colour” because it sounds 100x better

710 Diff Diff IonutCava picture IonutCava Fri 20 May, 2016 16:24:40 +0000

[IonutCava]
- Code cleanup
- Initial work on Scene loading and unloading with and without unloading assets:
— Need to change AIManager from a Singleton to a per-scene component

709 Diff Diff IonutCava picture IonutCava Thu 19 May, 2016 16:21:46 +0000

[IonutCava]
- Massive rewrite of the resource system:
— ResourceCache now uses a map of weak pointers and passes shared pointers to the call point of CreateResource
— RemoveResource is no longer needed, but resource based smart pointers use a custom deleter that calls unload()
— Keep a shared_ptr of the resource in the entity that needs it and pass shared_ptr references from getter methods
-— All of this removed the need for calls to RemoveResource, REGISTER_TRACKED_DEPENDENCY and UNREGISTER_TRACKED_DEPENDENCY reducing the number of mutex locks and atomic exchanges
- Singleton cleanup:
— Removed ShaderManager singleton and merged it’s data and responsibilities in static methods in both ShaderProgram and Shader classes.
Explanation: Due to the complex interdependency chains in the system, copying, updating, tracking the cache in a thread safe way became a lot more slower than a straight forward smart pointer based implementation. (e.g. scene graph nodes have 3d objects and material instances, 3d objects have materials, materials have textures and shaders, etc)

693 Diff Diff IonutCava picture IonutCava Thu 28 Apr, 2016 16:19:35 +0000

[IonutCava]
- Cleanup Time and Profiling code

692 Diff Diff IonutCava picture IonutCava Wed 27 Apr, 2016 16:24:26 +0000

[IonutCava]
- Resource system cleanup:
— Resource name and resource file location (if any) is now passed only via explicit constructors! (ResourceDescriptors already contain this data, so why use setters?)
- Fix a bug with ortho projection matrix calculation (set m[3][3] to 1. this was skipped when the identity() call was changed to zero() in the ortho() function)
— This also fixed text rendering

680 Diff Diff IonutCava picture IonutCava Thu 14 Apr, 2016 16:15:38 +0000

[IonutCava]
- Added a mat2 class (untested)
- Added static asserts to matrices, vectors and quaternions to allow only arithmetic (sans bool) data types
- Added more vector unit tests
- Added unit tests for matrices
- D32 finally renamed to D64 as the VC++ compiler is considered as the reference compiler

651 Diff Diff IonutCava picture IonutCava Wed 24 Feb, 2016 16:54:46 +0000

[IonutCava]
- Improved component access speed
- Added update flags to SceneNodes
— Currently used to flag bounding box update
- SceneNode bounds are only updated in the sceneUpdate call. BOUNDS_CHANGED flag can be set at any time.
- Changed SceneNode->SceneGraphNode BB update system to use the new SceneNode flag system
- Added initial code for compressed texture support (formats, containers, etc)
- Added STB libraries for future use

650 Diff Diff IonutCava picture IonutCava Tue 23 Feb, 2016 16:54:54 +0000

[IonutCava]
- Fix decoupling between PhysicsComponent and BoundsComponent
— SceneNodes now keep references to all owning SGNs and informs them when the bounds change
- AnimationComponent does not need a SceneAnimator on creation but most functionality will assert if one is not specified
— This was needed for the new component configuration system
- Added placeholder classes for an Inverse Kinematic component and a Ragdoll component
- SNG component configuration is now an upfront requirement: pass a component type mask when adding a node the the scenegraph
- SGN SpatialPartitionFlag is now an update flag that is set and cleared. More flags can be added in a similar fashion to nodes

628 IonutCava picture IonutCava Wed 20 Jan, 2016 17:17:53 +0000

[IonutCava]
- Reworked GenericVertexData ring-buffering system and changed vertex attributes to the vertex format system
— Might be buggy
- Disabled bump-mapping for low-LoD level entities
- Removed a forgotten test line in BRDF shader that prevented lighting calculations to occur properly (an early return)
- Updated auto-reflection system for high shininess materials
- Converted a lot of ‘to_xyz’ calls to ‘to_const_xyz’ calls where appropriate to reduce runtime cost (‘to_const_xyz’ is evaluated at compile time)