Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/ogre/Tools/MeshUpgrader/src/main.cpp @ 45

Last change on this file since 45 was 6, checked in by anonymous, 18 years ago

=…

File size: 25.5 KB
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2006 Torus Knot Software Ltd
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23
24You may alternatively use this source under the terms of a specific version of
25the OGRE Unrestricted License provided you have obtained such a license from
26Torus Knot Software Ltd.
27-----------------------------------------------------------------------------
28*/
29
30
31#include "Ogre.h"
32#include "OgreMeshSerializer.h"
33#include "OgreSkeletonSerializer.h"
34#include "OgreDefaultHardwareBufferManager.h"
35#include "OgreHardwareVertexBuffer.h"
36
37#include <iostream>
38#include <sys/stat.h>
39
40using namespace std;
41using namespace Ogre;
42
43void help(void)
44{
45    // Print help message
46    cout << endl << "OgreMeshUpgrader: Upgrades .mesh files to the latest version." << endl;
47    cout << "Provided for OGRE by Steve Streeting 2004" << endl << endl;
48    cout << "Usage: OgreMeshUpgrader [-e] sourcefile [destfile] " << endl;
49        cout << "-i             = Interactive mode, prompt for options" << endl;
50        cout << "-l lodlevels   = number of LOD levels" << endl;
51        cout << "-d loddist     = distance increment to reduce LOD" << endl;
52        cout << "-p lodpercent  = Percentage triangle reduction amount per LOD" << endl;
53        cout << "-f lodnumtris  = Fixed vertex reduction per LOD" << endl;
54    cout << "-e         = DON'T generate edge lists (for stencil shadows)" << endl;
55    cout << "-t         = Generate tangents (for normal mapping)" << endl;
56        cout << "-td [uvw|tangent]" << endl;
57        cout << "           = Tangent vertex semantic destination (default tangent)" << endl;
58        cout << "-r         = DON'T reorganise buffers to recommended format" << endl;
59        cout << "-d3d       = Convert to D3D colour formats" << endl;
60        cout << "-gl        = Convert to GL colour formats" << endl;
61        cout << "-srcd3d    = Interpret ambiguous colours as D3D style" << endl;
62        cout << "-srcgl     = Interpret ambiguous colours as GL style" << endl;
63        cout << "-E endian  = Set endian mode 'big' 'little' or 'native' (default)" << endl;
64        cout << "-b         = Recalculate bounding box (static meshes only)" << endl;
65    cout << "sourcefile = name of file to convert" << endl;
66    cout << "destfile   = optional name of file to write to. If you don't" << endl;
67    cout << "             specify this OGRE overwrites the existing file." << endl;
68
69    cout << endl;
70}
71
72struct UpgradeOptions
73{
74        bool interactive;
75        bool suppressEdgeLists;
76        bool generateTangents;
77        VertexElementSemantic tangentSemantic;
78        bool dontReorganise;
79        bool destColourFormatSet;
80        VertexElementType destColourFormat;
81        bool srcColourFormatSet;
82        VertexElementType srcColourFormat;
83        unsigned short numLods;
84        Real lodDist;
85        Real lodPercent;
86        size_t lodFixed;
87        bool usePercent;
88        Serializer::Endian endian;
89        bool recalcBounds;
90
91};
92
93
94// Crappy globals
95// NB some of these are not directly used, but are required to
96//   instantiate the singletons used in the dlls
97LogManager* logMgr = 0;
98Math* mth = 0;
99MaterialManager* matMgr = 0;
100SkeletonManager* skelMgr = 0;
101MeshSerializer* meshSerializer = 0;
102SkeletonSerializer* skeletonSerializer = 0;
103DefaultHardwareBufferManager *bufferManager = 0;
104ResourceGroupManager* rgm = 0;
105MeshManager* meshMgr = 0;
106UpgradeOptions opts;
107
108void parseOpts(UnaryOptionList& unOpts, BinaryOptionList& binOpts)
109{
110        opts.interactive = false;
111        opts.suppressEdgeLists = false;
112        opts.generateTangents = false;
113        opts.tangentSemantic = VES_TANGENT;
114        opts.dontReorganise = false;
115        opts.endian = Serializer::ENDIAN_NATIVE;
116        opts.destColourFormatSet = false;
117        opts.srcColourFormatSet = false;
118
119        opts.lodDist = 500;
120        opts.lodFixed = 0;
121        opts.lodPercent = 20;
122        opts.numLods = 0;
123        opts.usePercent = true;
124        opts.recalcBounds = false;
125
126
127        UnaryOptionList::iterator ui = unOpts.find("-e");
128        opts.suppressEdgeLists = ui->second;
129        ui = unOpts.find("-t");
130        opts.generateTangents = ui->second;
131        ui = unOpts.find("-i");
132        opts.interactive = ui->second;
133        ui = unOpts.find("-r");
134        opts.dontReorganise = ui->second;
135        ui = unOpts.find("-d3d");
136        if (ui->second)
137        {
138                opts.destColourFormatSet = true;
139                opts.destColourFormat = VET_COLOUR_ARGB;
140        }
141        ui = unOpts.find("-gl");
142        if (ui->second)
143        {
144                opts.destColourFormatSet = true;
145                opts.destColourFormat = VET_COLOUR_ABGR;
146        }
147        ui = unOpts.find("-srcd3d");
148        if (ui->second)
149        {
150                opts.srcColourFormatSet = true;
151                opts.srcColourFormat = VET_COLOUR_ARGB;
152        }
153        ui = unOpts.find("-srcgl");
154        if (ui->second)
155        {
156                opts.srcColourFormatSet = true;
157                opts.srcColourFormat = VET_COLOUR_ABGR;
158        }
159        ui = unOpts.find("-b");
160        if (ui->second)
161        {
162                opts.recalcBounds = true;
163        }
164
165
166        BinaryOptionList::iterator bi = binOpts.find("-l");
167        if (!bi->second.empty())
168        {
169                opts.numLods = StringConverter::parseInt(bi->second);
170        }
171
172        bi = binOpts.find("-d");
173        if (!bi->second.empty())
174        {
175                opts.lodDist = StringConverter::parseReal(bi->second);
176        }
177
178        bi = binOpts.find("-p");
179        if (!bi->second.empty())
180        {
181                opts.lodPercent = StringConverter::parseReal(bi->second);
182                opts.usePercent = true;
183        }
184
185
186        bi = binOpts.find("-f");
187        if (!bi->second.empty())
188        {
189                opts.lodFixed = StringConverter::parseInt(bi->second);
190                opts.usePercent = false;
191        }
192
193        bi = binOpts.find("-E");
194        if (!bi->second.empty())
195        {
196            if (bi->second == "big")
197            opts.endian = Serializer::ENDIAN_BIG;
198            else if (bi->second == "little")
199            opts.endian = Serializer::ENDIAN_LITTLE;
200            else 
201            opts.endian = Serializer::ENDIAN_NATIVE;
202    }
203        bi = binOpts.find("-td");
204        if (!bi->second.empty())
205        {
206                if (bi->second == "uvw")
207                        opts.tangentSemantic = VES_TEXTURE_COORDINATES;
208                else // if (bi->second == "tangent"), or anything else
209                        opts.tangentSemantic = VES_TANGENT;
210        }
211}
212
213String describeSemantic(VertexElementSemantic sem)
214{
215        switch (sem)
216        {
217        case VES_POSITION:
218                return "Positions";
219        case VES_NORMAL:
220                return "Normals";
221        case VES_BLEND_WEIGHTS:
222                return "Blend Weights";
223        case VES_BLEND_INDICES:
224                return "Blend Indices";
225        case VES_DIFFUSE:
226                return "Diffuse";
227        case VES_SPECULAR:
228                return "Specular";
229        case VES_TEXTURE_COORDINATES:
230                return "Texture coordinates";
231        case VES_BINORMAL:
232                return "Binormals";
233        case VES_TANGENT:
234                return "Tangents";
235        };
236    return "";
237}
238void displayVertexBuffers(VertexDeclaration::VertexElementList& elemList)
239{
240        // Iterate per buffer
241        unsigned short currentBuffer = 999;
242        unsigned short elemNum = 0;
243        VertexDeclaration::VertexElementList::iterator i, iend;
244        iend = elemList.end();
245        for (i = elemList.begin(); i != iend; ++i)
246        {
247                if (i->getSource() != currentBuffer)
248                {
249                        currentBuffer = i->getSource();
250                        cout << "> Buffer " << currentBuffer << ":" << endl;
251                }
252                cout << "   - Element " << elemNum++ << ": " << describeSemantic(i->getSemantic());
253                if (i->getSemantic() == VES_TEXTURE_COORDINATES)
254                {
255                        cout << " (index " << i->getIndex() << ")"; 
256                }
257                cout << endl;
258
259        }
260}
261// Sort routine for VertexElement
262bool vertexElementLess(const VertexElement& e1, const VertexElement& e2)
263{
264        // Sort by source first
265        if (e1.getSource() < e2.getSource())
266        {
267                return true;
268        }
269        else if (e1.getSource() == e2.getSource())
270        {
271                // Use ordering of semantics to sort
272                if (e1.getSemantic() < e2.getSemantic())
273                {
274                        return true;
275                }
276                else if (e1.getSemantic() == e2.getSemantic())
277                {
278                        // Use index to sort
279                        if (e1.getIndex() < e2.getIndex())
280                        {
281                                return true;
282                        }
283                }
284        }
285        return false;
286}
287void copyElems(VertexDeclaration* decl, VertexDeclaration::VertexElementList* elemList)
288{
289       
290        elemList->clear();
291        const VertexDeclaration::VertexElementList& origElems = decl->getElements();
292    VertexDeclaration::VertexElementList::const_iterator i, iend;
293        iend = origElems.end();
294        for (i = origElems.begin(); i != iend; ++i)
295        {
296                elemList->push_back(*i);
297        }
298        elemList->sort(VertexDeclaration::vertexElementLess);
299}
300// Utility function to allow the user to modify the layout of vertex buffers.
301void reorganiseVertexBuffers(const String& desc, Mesh& mesh, VertexData* vertexData)
302{
303        cout << endl << desc << ":- " << endl;
304        // Copy elements into a list
305        VertexDeclaration::VertexElementList elemList;
306        copyElems(vertexData->vertexDeclaration, &elemList);
307
308        bool finish = false;
309        bool anyChanges = false;
310        while (!finish)
311        {
312                displayVertexBuffers(elemList);
313                cout << endl;
314
315                cout << "Options: (a)utomatic" << endl;
316        cout << "         (m)ove element" << endl;
317                cout << "         (d)elete element" << endl;
318                cout << "         (r)eset" << endl;
319                cout << "         (f)inish" << endl;
320                String response = "";
321                while (response.empty())
322                {
323                        cin >> response;
324                        StringUtil::toLowerCase(response);
325
326                        if (response == "m")
327                        {
328                                String moveResp;
329                                cout << "Which element do you want to move (type number): ";
330                                cin >> moveResp;
331                                if (!moveResp.empty())
332                                {
333                                        int eindex = StringConverter::parseInt(moveResp);
334                                        VertexDeclaration::VertexElementList::iterator movei = elemList.begin();
335                                        std::advance(movei, eindex);
336                                        cout << endl << "Move element " << eindex << "(" + describeSemantic(movei->getSemantic()) << ") to which buffer: ";
337                                        cin >> moveResp;
338                                        if (!moveResp.empty())
339                                        {
340                                                int bindex = StringConverter::parseInt(moveResp);
341                                                // Move (note offset will be wrong)
342                                                *movei = VertexElement(bindex, 0, movei->getType(),
343                                                        movei->getSemantic(), movei->getIndex());
344                                                elemList.sort(vertexElementLess);
345                        anyChanges = true;
346                                                               
347                                        }
348                                }
349                        }
350            else if (response == "a")
351            {
352                // Automatic
353                VertexDeclaration* newDcl = 
354                    vertexData->vertexDeclaration->getAutoOrganisedDeclaration(
355                        mesh.hasSkeleton(), mesh.hasVertexAnimation());
356                copyElems(newDcl, &elemList);
357                HardwareBufferManager::getSingleton().destroyVertexDeclaration(newDcl);
358                anyChanges = true;
359
360            }
361                        else if (response == "d")
362                        {
363                                String moveResp;
364                                cout << "Which element do you want to delete (type number): ";
365                                cin >> moveResp;
366                                if (!moveResp.empty())
367                                {
368                                        int eindex = StringConverter::parseInt(moveResp);
369                                        VertexDeclaration::VertexElementList::iterator movei = elemList.begin();
370                                        std::advance(movei, eindex);
371                    cout << std::endl << "Delete element " << eindex << "(" + describeSemantic(movei->getSemantic()) << ")?: ";
372                                        cin >> moveResp;
373                                        StringUtil::toLowerCase(moveResp);
374                                        if (moveResp == "y")
375                                        {
376                                                elemList.erase(movei);
377                        anyChanges = true;
378                                        }
379                                }
380                        }
381                        else if (response == "r")
382                        {
383                                // reset
384                                copyElems(vertexData->vertexDeclaration, &elemList);
385                                anyChanges = false;
386                        }
387                        else if (response == "f")
388                        {
389                                // finish
390                                finish = true;
391                        }
392                        else
393                        {
394                                response == "";
395                        }
396                       
397                }
398        }
399
400        if (anyChanges)
401        {
402                String response;
403                while (response.empty())
404                {
405                        displayVertexBuffers(elemList);
406                        cout << "Really reorganise the vertex buffers this way?";
407                        cin >> response;
408                        StringUtil::toLowerCase(response);
409                        if (response == "y")
410                        {
411                                VertexDeclaration* newDecl = HardwareBufferManager::getSingleton().createVertexDeclaration();
412                                VertexDeclaration::VertexElementList::iterator i, iend;
413                                iend = elemList.end();
414                                unsigned short currentBuffer = 999;
415                                size_t offset;
416                                for (i = elemList.begin(); i != iend; ++i)
417                                {
418                                        // Calc offsets since reorg changes them
419                                        if (i->getSource() != currentBuffer)
420                                        {
421                                                offset = 0;
422                                                currentBuffer = i->getSource();
423                                        }
424                                        newDecl->addElement(
425                                                currentBuffer,
426                                                offset,
427                                                i->getType(),
428                                                i->getSemantic(),
429                                                i->getIndex());
430
431                                        offset += VertexElement::getTypeSize(i->getType());
432                                       
433                                }
434                // Usages don't matter here since we're onlly exporting
435                BufferUsageList bufferUsages;
436                for (size_t u = 0; u <= newDecl->getMaxSource(); ++u)
437                    bufferUsages.push_back(HardwareBuffer::HBU_STATIC_WRITE_ONLY);
438                                vertexData->reorganiseBuffers(newDecl, bufferUsages);
439                        }
440                        else if (response == "n")
441                        {
442                                // do nothing
443                        }
444                        else
445                        {
446                                response = "";
447                        }
448        }
449               
450        }
451               
452
453       
454}
455// Utility function to allow the user to modify the layout of vertex buffers.
456void reorganiseVertexBuffers(Mesh& mesh)
457{
458        if (mesh.sharedVertexData)
459        {
460                if (opts.interactive)
461                        reorganiseVertexBuffers("Shared Geometry", mesh, mesh.sharedVertexData);
462                else
463                {
464                        // Automatic
465                        VertexDeclaration* newDcl = 
466                                mesh.sharedVertexData->vertexDeclaration->getAutoOrganisedDeclaration(
467                                mesh.hasSkeleton(), mesh.hasVertexAnimation());
468                        if (*newDcl != *(mesh.sharedVertexData->vertexDeclaration))
469                        {
470                                // Usages don't matter here since we're onlly exporting
471                                BufferUsageList bufferUsages;
472                                for (size_t u = 0; u <= newDcl->getMaxSource(); ++u)
473                                        bufferUsages.push_back(HardwareBuffer::HBU_STATIC_WRITE_ONLY);
474                                mesh.sharedVertexData->reorganiseBuffers(newDcl, bufferUsages);
475                        }
476
477                }
478        }
479
480    Mesh::SubMeshIterator smIt = mesh.getSubMeshIterator();
481        unsigned short idx = 0;
482        while (smIt.hasMoreElements())
483        {
484                SubMesh* sm = smIt.getNext();
485                if (!sm->useSharedVertices)
486                {
487                        if (opts.interactive)
488                        {
489                                StringUtil::StrStreamType str;
490                                str << "SubMesh " << idx++; 
491                                reorganiseVertexBuffers(str.str(), mesh, sm->vertexData);
492                        }
493                        else
494                        {
495                                // Automatic
496                                VertexDeclaration* newDcl = 
497                                        sm->vertexData->vertexDeclaration->getAutoOrganisedDeclaration(
498                                        mesh.hasSkeleton(), mesh.hasVertexAnimation());
499                                if (*newDcl != *(sm->vertexData->vertexDeclaration))
500                                {
501                                        // Usages don't matter here since we're onlly exporting
502                                        BufferUsageList bufferUsages;
503                                        for (size_t u = 0; u <= newDcl->getMaxSource(); ++u)
504                                                bufferUsages.push_back(HardwareBuffer::HBU_STATIC_WRITE_ONLY);
505                                        sm->vertexData->reorganiseBuffers(newDcl, bufferUsages);
506                                }
507                               
508                        }
509                }
510        }
511}
512
513
514void vertexBufferReorg(Mesh& mesh)
515{
516        String response;
517
518        if (opts.interactive)
519        {
520
521                // Check to see whether we would like to reorganise vertex buffers
522                std::cout << "\nWould you like to reorganise the vertex buffers for this mesh?";
523                while (response.empty())
524                {
525                        cin >> response;
526                        StringUtil::toLowerCase(response);
527                        if (response == "y")
528                        {
529                                reorganiseVertexBuffers(mesh);
530                        }
531                        else if (response == "n")
532                        {
533                                // Do nothing
534                        }
535                        else
536                        {
537                                response = "";
538                        }
539                }
540        }
541        else if (!opts.dontReorganise)
542        {
543                reorganiseVertexBuffers(mesh);
544        }
545
546}
547
548void buildLod(Mesh* mesh)
549{       
550        String response;
551
552        // Prompt for LOD generation?
553        bool genLod = false;
554        bool askLodDtls = false;
555        if (!opts.interactive) // derive from params if in batch mode
556        {
557                askLodDtls = false;
558                if (opts.numLods == 0)
559                {
560                        genLod = false;
561                }
562                else
563                {
564                        genLod = true;
565                }
566        }
567        else if(opts.numLods == 0) // otherwise only ask if not specified on command line
568        {
569                if (mesh->getNumLodLevels() > 1)
570                {
571                        std::cout << "\nXML already contains level-of detail information.\n"
572                                "Do you want to: (u)se it, (r)eplace it, or (d)rop it?";
573                        while (response == "")
574                        {
575                                cin >> response;
576                                StringUtil::toLowerCase(response);
577                                if (response == "u")
578                                {
579                                        // Do nothing
580                                }
581                                else if (response == "d")
582                                {
583                                        mesh->removeLodLevels();
584                                }
585                                else if (response == "r")
586                                {
587                                        genLod = true;
588                                        askLodDtls = true;
589
590                                }
591                                else
592                                {
593                                        response = "";
594                                }
595                        }// while response == ""
596                }
597                else // no existing LOD
598                {
599                        std::cout << "\nWould you like to generate LOD information? (y/n)";
600                        while (response == "")
601                        {
602                                cin >> response;
603                                StringUtil::toLowerCase(response);
604                                if (response == "n")
605                                {
606                                        // Do nothing
607                                }
608                                else if (response == "y")
609                                {
610                                        genLod = true;
611                                        askLodDtls = true;
612                                }
613                        }
614                }
615        }
616
617        if (genLod)
618        {
619                unsigned short numLod;
620                ProgressiveMesh::VertexReductionQuota quota;
621                Real reduction;
622                Mesh::LodDistanceList distanceList;
623
624                if (askLodDtls)
625                {
626                        cout << "\nHow many extra LOD levels would you like to generate?";
627                        cin >> numLod;
628
629                        cout << "\nWhat unit of reduction would you like to use:" <<
630                                "\n(f)ixed or (p)roportional?";
631                        cin >> response;
632                        StringUtil::toLowerCase(response);
633                        if (response == "f")
634                        {
635                                quota = ProgressiveMesh::VRQ_CONSTANT;
636                                cout << "\nHow many vertices should be removed at each LOD?";
637                        }
638                        else
639                        {
640                                quota = ProgressiveMesh::VRQ_PROPORTIONAL;
641                                cout << "\nWhat percentage of remaining vertices should be removed "
642                                        "\at each LOD (e.g. 50)?";
643                        }
644                        cin >> reduction;
645                        if (quota == ProgressiveMesh::VRQ_PROPORTIONAL)
646                        {
647                                // Percentage -> parametric
648                                reduction = reduction * 0.01f;
649                        }
650
651                        cout << "\nEnter the distance for each LOD to come into effect.";
652
653                        Real distance;
654                        for (unsigned short iLod = 0; iLod < numLod; ++iLod)
655                        {
656                                cout << "\nLOD Level " << (iLod+1) << ":";
657                                cin >> distance;
658                                distanceList.push_back(distance);
659                        }
660                }
661                else
662                {
663                        numLod = opts.numLods;
664                        quota = opts.usePercent? 
665                                ProgressiveMesh::VRQ_PROPORTIONAL : ProgressiveMesh::VRQ_CONSTANT;
666                        if (opts.usePercent)
667                        {
668                                reduction = opts.lodPercent * 0.01f;
669                        }
670                        else
671                        {
672                                reduction = opts.lodFixed;
673                        }
674                        Real currDist = 0;
675                        for (unsigned short iLod = 0; iLod < numLod; ++iLod)
676                        {
677                                currDist += opts.lodDist;
678                                distanceList.push_back(currDist);
679                        }
680
681                }
682
683                mesh->generateLodLevels(distanceList, quota, reduction);
684        }
685
686}
687
688void checkColour(VertexData* vdata, bool &hasColour, bool &hasAmbiguousColour,
689        VertexElementType& originalType)
690{
691        const VertexDeclaration::VertexElementList& elemList = vdata->vertexDeclaration->getElements();
692        for (VertexDeclaration::VertexElementList::const_iterator i = elemList.begin();
693                i != elemList.end(); ++i)
694        {
695                const VertexElement& elem = *i;
696                switch (elem.getType())
697                {
698                case VET_COLOUR:
699                        hasAmbiguousColour = true;
700                case VET_COLOUR_ABGR:
701                case VET_COLOUR_ARGB:
702                        hasColour = true;
703                        originalType = elem.getType();
704                default:
705                        // do nothing
706                        ;
707                };
708        }
709
710}
711
712void resolveColourAmbiguities(Mesh* mesh)
713{
714        // Check what we're dealing with
715        bool hasColour = false;
716        bool hasAmbiguousColour = false;
717        VertexElementType originalType;
718        if (mesh->sharedVertexData)
719        {
720                checkColour(mesh->sharedVertexData, hasColour, hasAmbiguousColour, originalType);
721        }
722        for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i)
723        {
724                SubMesh* sm = mesh->getSubMesh(i);
725                if (sm->useSharedVertices == false)
726                {
727                        checkColour(sm->vertexData, hasColour, hasAmbiguousColour, originalType);
728                }
729        }
730
731        String response;
732        if (hasAmbiguousColour)
733        {
734                if (opts.srcColourFormatSet)
735                {
736                        originalType = opts.srcColourFormat;
737                }
738                else
739                {
740                        // unknown input colour, have to ask
741                        std::cout << "\nYour mesh has vertex colours but I don't know whether they were generated\n"
742                                << "using GL or D3D ordering. Please indicate which was used when the mesh was\n"
743                                << "created (type 'gl' or 'd3d').\n";
744                        while (response.empty())
745                        {
746                                cin >> response;
747                                StringUtil::toLowerCase(response);
748                                if (response == "d3d")
749                                {
750                                        originalType = VET_COLOUR_ARGB;
751                                }
752                                else if (response == "gl")
753                                {
754                                        originalType = VET_COLOUR_ABGR;
755                                }
756                                else
757                                {
758                                        response = "";
759                                }
760                        }
761                }
762        }
763
764        // Ask what format we want to save in
765        VertexElementType desiredType;
766        if (hasColour)
767        {
768                if (opts.destColourFormatSet)
769                {
770                        desiredType = opts.destColourFormat;
771                }
772                else
773                {
774                        if (opts.interactive)
775                        {
776
777                                response = "";
778                                std::cout << "\nYour mesh has vertex colours, which can be stored in one of two layouts,\n"
779                                        << "each of which will be slightly faster to load in a different render system.\n"
780                                        << "Do you want to prefer Direct3D (d3d) or OpenGL (gl)?\n";
781                                while (response.empty())
782                                {
783                                        cin >> response;
784                                        StringUtil::toLowerCase(response);
785                                        if (response == "d3d")
786                                        {
787                                                desiredType = VET_COLOUR_ARGB;
788                                        }
789                                        else if (response == "gl")
790                                        {
791                                                desiredType = VET_COLOUR_ABGR;
792                                        }
793                                        else
794                                        {
795                                                response = "";
796                                        }
797                                }
798                        }
799                        else
800                        {
801                                // 'do no harm'
802                                return;
803                        }
804                }
805
806        }
807
808        if (mesh->sharedVertexData && hasColour)
809        {
810                mesh->sharedVertexData->convertPackedColour(originalType, desiredType);
811        }
812        for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i)
813        {
814                SubMesh* sm = mesh->getSubMesh(i);
815                if (sm->useSharedVertices == false && hasColour)
816                {
817                        sm->vertexData->convertPackedColour(originalType, desiredType);
818                }
819        }
820
821
822}
823
824void recalcBounds(const VertexData* vdata, AxisAlignedBox& aabb, Real& radius)
825{
826        const VertexElement* posElem = 
827                vdata->vertexDeclaration->findElementBySemantic(VES_POSITION);
828       
829        const HardwareVertexBufferSharedPtr buf = vdata->vertexBufferBinding->getBuffer(
830                posElem->getSource());
831        void* pBase = buf->lock(HardwareBuffer::HBL_READ_ONLY);
832
833        for (size_t v = 0; v < vdata->vertexCount; ++v)
834        {
835                float* pFloat;
836                posElem->baseVertexPointerToElement(pBase, &pFloat);
837               
838                Vector3 pos(pFloat[0], pFloat[1], pFloat[2]);
839                aabb.merge(pos);
840                radius = std::max(radius, pos.length());
841
842                pBase = static_cast<void*>(static_cast<char*>(pBase) + buf->getVertexSize());
843
844        }
845
846        buf->unlock();
847
848}
849
850void recalcBounds(Mesh* mesh)
851{
852        AxisAlignedBox aabb;
853        Real radius = 0.0f;
854
855        if (mesh->sharedVertexData)
856                recalcBounds(mesh->sharedVertexData, aabb, radius);
857        for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i)
858        {
859                SubMesh* sm = mesh->getSubMesh(i);
860                if (!sm->useSharedVertices)
861                        recalcBounds(sm->vertexData, aabb, radius);
862        }
863
864        mesh->_setBounds(aabb, false);
865        mesh->_setBoundingSphereRadius(radius);
866}
867
868int main(int numargs, char** args)
869{
870    if (numargs < 2)
871    {
872        help();
873        return -1;
874    }
875
876        int retCode = 0;
877        try 
878        {
879                logMgr = new LogManager();
880                logMgr->createLog("OgreMeshUpgrade.log", true);
881                rgm = new ResourceGroupManager();
882                mth = new Math();
883                matMgr = new MaterialManager();
884                matMgr->initialise();
885                skelMgr = new SkeletonManager();
886                meshSerializer = new MeshSerializer();
887                skeletonSerializer = new SkeletonSerializer();
888                bufferManager = new DefaultHardwareBufferManager(); // needed because we don't have a rendersystem
889                meshMgr = new MeshManager();
890                // don't pad during upgrade
891                meshMgr->setBoundsPaddingFactor(0.0f);
892
893           
894                UnaryOptionList unOptList;
895                BinaryOptionList binOptList;
896
897                unOptList["-i"] = false;
898                unOptList["-e"] = false;
899                unOptList["-t"] = false;
900                unOptList["-r"] = false;
901                unOptList["-gl"] = false;
902                unOptList["-d3d"] = false;
903                unOptList["-srcgl"] = false;
904                unOptList["-srcd3d"] = false;
905                unOptList["-b"] = false;
906                binOptList["-l"] = "";
907                binOptList["-d"] = "";
908                binOptList["-p"] = "";
909                binOptList["-f"] = "";
910                binOptList["-E"] = "";
911                binOptList["-td"] = "";
912
913                int startIdx = findCommandLineOpts(numargs, args, unOptList, binOptList);
914                parseOpts(unOptList, binOptList);
915
916                String source(args[startIdx]);
917
918
919                // Load the mesh
920                struct stat tagStat;
921
922                FILE* pFile = fopen( source.c_str(), "rb" );
923                if (!pFile)
924                {
925                        OGRE_EXCEPT(Exception::ERR_FILE_NOT_FOUND, 
926                                "File " + source + " not found.", "OgreMeshUpgrade");
927                }
928                stat( source.c_str(), &tagStat );
929                MemoryDataStream* memstream = new MemoryDataStream(source, tagStat.st_size, true);
930                fread( (void*)memstream->getPtr(), tagStat.st_size, 1, pFile );
931                fclose( pFile );
932
933                Mesh mesh(meshMgr, "conversion", 0, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
934
935                DataStreamPtr stream(memstream);
936                meshSerializer->importMesh(stream, &mesh);
937
938                // Write out the converted mesh
939                String dest;
940                if (numargs == startIdx + 2)
941                {
942                        dest = args[startIdx + 1];
943                }
944                else
945                {
946                        dest = source;
947                }
948
949                String response;
950
951                vertexBufferReorg(mesh);
952
953                // Deal with VET_COLOUR ambiguities
954                resolveColourAmbiguities(&mesh);
955               
956                buildLod(&mesh);
957
958                // Make sure we generate edge lists, provided they are not deliberately disabled
959                if (!opts.suppressEdgeLists)
960                {
961                        cout << "\nGenerating edge lists.." << std::endl;
962                        mesh.buildEdgeList();
963                }
964                else
965                {
966                        mesh.freeEdgeList();
967                }
968
969                // Generate tangents?
970                if (opts.generateTangents)
971                {
972                        unsigned short srcTex, destTex;
973                        bool existing = mesh.suggestTangentVectorBuildParams(opts.tangentSemantic, srcTex, destTex);
974                        if (existing)
975                        {
976                                if (opts.interactive)
977                                {
978                                        std::cout << "\nThis mesh appears to already have a set of tangents, " <<
979                                                "which would suggest tangent vectors have already been calculated. Do you really " <<
980                                                "want to generate new tangent vectors (may duplicate)? (y/n)";
981                                        while (response == "")
982                                        {
983                                                cin >> response;
984                                                StringUtil::toLowerCase(response);
985                                                if (response == "y")
986                                                {
987                                                        // Do nothing
988                                                }
989                                                else if (response == "n")
990                                                {
991                                                        opts.generateTangents = false;
992                                                }
993                                                else
994                                                {
995                                                        response = "";
996                                                }
997                                        }
998                                }
999                                else
1000                                {
1001                                        // safe
1002                                        opts.generateTangents = false;
1003                                }
1004
1005                        }
1006                        if (opts.generateTangents)
1007                        {
1008                                cout << "Generating tangent vectors...." << std::endl;
1009                                mesh.buildTangentVectors(opts.tangentSemantic, srcTex, destTex);
1010                        }
1011                }
1012
1013
1014                if (opts.recalcBounds)
1015                        recalcBounds(&mesh);
1016
1017                meshSerializer->exportMesh(&mesh, dest, opts.endian);
1018   
1019        }
1020        catch (Exception& e)
1021        {
1022                cout << "Exception caught: " << e.getDescription();
1023                retCode = 1;
1024        }
1025
1026
1027    delete meshMgr;
1028    delete skeletonSerializer;
1029    delete meshSerializer;
1030    delete skelMgr;
1031    delete matMgr;
1032    delete mth;
1033    delete rgm;
1034    delete logMgr;
1035
1036    return retCode;
1037
1038}
1039
Note: See TracBrowser for help on using the repository browser.