root/OpenSceneGraph/trunk/examples/osgvertexattributes/osgvertexattributes.cpp @ 10618

Revision 10618, 10.8 kB (checked in by robert, 5 years ago)

Implemented remapping of gl_ builtins vertex attributes to osg_ equivlants.

Line 
1/* OpenSceneGraph example, osgvertexattributes.
2*
3*  Permission is hereby granted, free of charge, to any person obtaining a copy
4*  of this software and associated documentation files (the "Software"), to deal
5*  in the Software without restriction, including without limitation the rights
6*  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7*  copies of the Software, and to permit persons to whom the Software is
8*  furnished to do so, subject to the following conditions:
9*
10*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
11*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
13*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
15*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
16*  THE SOFTWARE.
17*/
18
19#include <osgUtil/ShaderGen>
20#include <osgDB/ReadFile>
21#include <osgDB/WriteFile>
22#include <osgViewer/Viewer>
23
24class ConvertToVertexAttibArrays : public osg::NodeVisitor
25{
26    public:
27
28        typedef std::pair<unsigned int, std::string> AttributeAlias;
29
30        ConvertToVertexAttibArrays():
31            osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
32        {
33            // mappings taken from http://www.opengl.org/registry/specs/NV/vertex_program.txt
34            _vertexAlias = AttributeAlias(0, "osg_Vertex");
35            _normalAlias = AttributeAlias(2, "osg_Normal");
36            _colorAlias = AttributeAlias(3, "osg_Color");
37            _secondaryColorAlias = AttributeAlias(4, "osg_SecondaryColor");
38            _fogCoordAlias = AttributeAlias(5, "osg_FogCoord");
39            _texCoordAlias[0] = AttributeAlias(8, "osg_MultiTexCoord0");
40            _texCoordAlias[1] = AttributeAlias(9, "osg_MultiTexCoord1");
41            _texCoordAlias[2] = AttributeAlias(10, "osg_MultiTexCoord2");
42            _texCoordAlias[3] = AttributeAlias(11, "osg_MultiTexCoord3");
43            _texCoordAlias[4] = AttributeAlias(12, "osg_MultiTexCoord4");
44            _texCoordAlias[5] = AttributeAlias(13, "osg_MultiTexCoord5");
45            _texCoordAlias[6] = AttributeAlias(14, "osg_MultiTexCoord6");
46            _texCoordAlias[7] = AttributeAlias(15, "osg_MultiTexCoord7");
47        }
48
49        std::string convertShader(std::string source)
50        {
51            replace(source, "gl_Vertex", "osg_Vertex");
52            replace(source, "gl_Normal", "osg_Normal");
53            replace(source, "gl_Color", "osg_Color");
54            replace(source, "gl_SecondaryColor", "osg_SecondaryColor");
55            replace(source, "gl_FogCoord", "osg_FogCoord");
56            replace(source, "gl_MultiTexCoord0", "osg_MultiTexCoord0");
57            replace(source, "gl_MultiTexCoord1", "osg_MultiTexCoord1");
58            replace(source, "gl_MultiTexCoord2", "osg_MultiTexCoord2");
59            replace(source, "gl_MultiTexCoord3", "osg_MultiTexCoord3");
60            replace(source, "gl_MultiTexCoord4", "osg_MultiTexCoord4");
61            replace(source, "gl_MultiTexCoord5", "osg_MultiTexCoord5");
62            replace(source, "gl_MultiTexCoord6", "osg_MultiTexCoord6");
63            replace(source, "gl_MultiTexCoord7", "osg_MultiTexCoord7");
64            return source;
65        }
66
67        virtual void reset()
68        {
69            _visited.clear();
70        }
71
72        void apply(osg::Node& node)
73        {
74            if (_visited.count(&node)!=0) return;
75            _visited.insert(&node);
76
77            if (node.getStateSet()) apply(*(node.getStateSet()));
78            traverse(node);
79        }
80
81        void apply(osg::Geode& geode)
82        {
83            if (_visited.count(&geode)!=0) return;
84            _visited.insert(&geode);
85
86            if (geode.getStateSet()) apply(*(geode.getStateSet()));
87
88            for(unsigned int i=0; i<geode.getNumDrawables(); ++i)
89            {
90                if (geode.getDrawable(i)->getStateSet()) apply(*(geode.getDrawable(i)->getStateSet()));
91
92                osg::Geometry* geom = geode.getDrawable(i)->asGeometry();
93                if (geom) apply(*geom);
94            }
95        }
96
97        void replace(std::string& str, const std::string& original_phrase, const std::string& new_phrase)
98        {
99            std::string::size_type pos = 0;
100            while((pos=str.find(original_phrase, pos))!=std::string::npos)
101            {
102                std::string::size_type endOfPhrasePos = pos+original_phrase.size();
103                if (endOfPhrasePos<str.size())
104                {
105                    char c = str[endOfPhrasePos];
106                    if ((c>='0' && c<='9') ||
107                        (c>='a' && c<='z') ||
108                        (c>='A' && c<='Z'))
109                    {
110                        pos = endOfPhrasePos;
111                        continue;
112                    }
113                }
114
115                str.replace(pos, original_phrase.size(), new_phrase);
116            }
117        }
118
119        void apply(osg::Shader& shader)
120        {
121             if (_visited.count(&shader)!=0) return;
122            _visited.insert(&shader);
123
124            osg::notify(osg::NOTICE)<<"Shader "<<shader.getTypename()<<" ----before-----------"<<std::endl;
125            osg::notify(osg::NOTICE)<<shader.getShaderSource()<<std::endl;
126            shader.setShaderSource(convertShader(shader.getShaderSource()));
127            osg::notify(osg::NOTICE)<<"--after-----------"<<std::endl;
128            osg::notify(osg::NOTICE)<<shader.getShaderSource()<<std::endl;
129            osg::notify(osg::NOTICE)<<"---------------------"<<std::endl;
130        }
131
132        void apply(osg::StateSet& stateset)
133        {
134             if (_visited.count(&stateset)!=0) return;
135            _visited.insert(&stateset);
136
137            osg::notify(osg::NOTICE)<<"Found stateset "<<&stateset<<std::endl;
138            osg::Program* program = dynamic_cast<osg::Program*>(stateset.getAttribute(osg::StateAttribute::PROGRAM));
139            if (program)
140            {
141                osg::notify(osg::NOTICE)<<"   Found Program "<<program<<std::endl;
142                for(unsigned int i=0; i<program->getNumShaders(); ++i)
143                {
144                    apply(*(program->getShader(i)));
145                }
146            }
147       }
148
149        void apply(osg::Geometry& geom)
150        {
151            osg::notify(osg::NOTICE)<<"Found geometry "<<&geom<<std::endl;
152            if (geom.getVertexArray())
153            {
154                setVertexAttrib(geom, _vertexAlias, geom.getVertexArray(), false, osg::Geometry::BIND_PER_VERTEX);
155                geom.setVertexArray(0);
156            }
157
158            if (geom.getNormalArray())
159            {
160                setVertexAttrib(geom, _normalAlias, geom.getNormalArray(), true, geom.getNormalBinding());
161                geom.setNormalArray(0);
162            }
163
164            if (geom.getColorArray())
165            {
166                setVertexAttrib(geom, _colorAlias, geom.getColorArray(), true, geom.getColorBinding());
167                geom.setColorArray(0);
168            }
169
170            if (geom.getSecondaryColorArray())
171            {
172                setVertexAttrib(geom, _secondaryColorAlias, geom.getSecondaryColorArray(), true, geom.getSecondaryColorBinding());
173                geom.setSecondaryColorArray(0);
174            }
175
176            if (geom.getFogCoordArray())
177            {
178                // should we normalize the FogCoord array? Don't think so...
179                setVertexAttrib(geom, _fogCoordAlias, geom.getFogCoordArray(), false, geom.getSecondaryColorBinding());
180                geom.setFogCoordArray(0);
181            }
182
183            unsigned int maxNumTexCoords = geom.getNumTexCoordArrays();
184            if (maxNumTexCoords>8)
185            {
186                osg::notify(osg::NOTICE)<<"Warning: Ignoring "<<maxNumTexCoords-8<<" texture coordinate arrays, only 8 are currently supported in vertex attribute conversion code."<<std::endl;
187                maxNumTexCoords = 8;
188            }
189            for(unsigned int i=0; i<maxNumTexCoords; ++i)
190            {
191                if (geom.getTexCoordArray(i))
192                {
193                    setVertexAttrib(geom, _texCoordAlias[i], geom.getTexCoordArray(i), true, geom.getSecondaryColorBinding());
194                    geom.setTexCoordArray(i,0);
195                }
196                else
197                {
198                    osg::notify(osg::NOTICE)<<"Found empty TexCoordArray("<<i<<")"<<std::endl;
199                }
200            }
201        }
202
203        void setVertexAttrib(osg::Geometry& geom, const AttributeAlias& alias, osg::Array* array, bool normalize, osg::Geometry::AttributeBinding binding)
204        {
205            unsigned int index = alias.first;
206            const std::string& name = alias.second;
207            array->setName(name);
208            geom.setVertexAttribArray(index, array);
209            geom.setVertexAttribNormalize(index, normalize);
210            geom.setVertexAttribBinding(index, binding);
211
212            osg::notify(osg::NOTICE)<<"   vertex attrib("<<name<<", index="<<index<<", normalize="<<normalize<<" binding="<<binding<<")"<<std::endl;
213        }
214
215
216        typedef std::set<osg::Object*> Visited;
217        Visited         _visited;
218
219        AttributeAlias _vertexAlias;
220        AttributeAlias _normalAlias;
221        AttributeAlias _colorAlias;
222        AttributeAlias _secondaryColorAlias;
223        AttributeAlias _fogCoordAlias;
224        AttributeAlias _texCoordAlias[8];
225};
226
227
228
229int main(int argc, char *argv[])
230{
231    // use an ArgumentParser object to manage the program arguments.
232    osg::ArgumentParser arguments(&argc,argv);
233
234    // construct the viewer.
235    osgViewer::Viewer viewer(arguments);
236
237    std::string outputFileName;
238    while (arguments.read("-o",outputFileName)) {}
239
240    bool runShaderGen = true;
241    while (arguments.read("--shader-gen")) { runShaderGen = true; }
242    while (arguments.read("--no-shader-gen")) { runShaderGen = false; }
243
244    bool runConvertToVertexAttributes = true;
245    while (arguments.read("--vertex-attrib")) { runConvertToVertexAttributes = true; }
246    while (arguments.read("--no-vertex-attrib")) { runConvertToVertexAttributes = false; }
247
248    osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments);
249    if (!loadedModel.get())
250    {
251        osg::notify(osg::NOTICE)<<"No model loaded, please specify a model filename."<<std::endl;
252        return 1;
253    }
254
255    if (runShaderGen)
256    {
257        // convert fixed function pipeline to shaders
258        osgUtil::ShaderGenVisitor sgv;
259        loadedModel->accept(sgv);
260    }
261
262    if (runConvertToVertexAttributes)
263    {
264        // find any conventional vertex, colour, normal and tex coords arrays and convert to vertex attributes
265        ConvertToVertexAttibArrays ctvaa;
266        loadedModel->accept(ctvaa);
267    }
268
269    if (!outputFileName.empty())
270    {
271        osgDB::writeNodeFile(*loadedModel, outputFileName);
272        return 0;
273    }
274
275    // add a viewport to the viewer and attach the scene graph.
276    viewer.setSceneData(loadedModel.get());
277
278    return viewer.run();
279}
Note: See TracBrowser for help on using the browser.