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

Revision 10619, 11.3 kB (checked in by robert, 5 years ago)

Added remapping of gl_ and ftransform() variables to osg_ equivalents.

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 ftransform as it only works with built-ins
52            replace(source, "ftransform()", "gl_ModelViewProjectionMatrix * gl_Vertex");
53
54            // replace the vertex attributes
55            replace(source, "gl_Vertex", "osg_Vertex");
56            replace(source, "gl_Normal", "osg_Normal");
57            replace(source, "gl_Color", "osg_Color");
58            replace(source, "gl_SecondaryColor", "osg_SecondaryColor");
59            replace(source, "gl_FogCoord", "osg_FogCoord");
60            replace(source, "gl_MultiTexCoord0", "osg_MultiTexCoord0");
61            replace(source, "gl_MultiTexCoord1", "osg_MultiTexCoord1");
62            replace(source, "gl_MultiTexCoord2", "osg_MultiTexCoord2");
63            replace(source, "gl_MultiTexCoord3", "osg_MultiTexCoord3");
64            replace(source, "gl_MultiTexCoord4", "osg_MultiTexCoord4");
65            replace(source, "gl_MultiTexCoord5", "osg_MultiTexCoord5");
66            replace(source, "gl_MultiTexCoord6", "osg_MultiTexCoord6");
67            replace(source, "gl_MultiTexCoord7", "osg_MultiTexCoord7");
68
69            // replace the modelview and project matrices
70            replace(source, "gl_ModelViewMatrix", "osg_ModeViewMatrix");
71            replace(source, "gl_ModelViewProjectionMatrix", "osg_ModelViewProjectionMatrix");
72            replace(source, "gl_ProjectionMatrix", "osg_ProjectionMatrix");
73
74            return source;
75        }
76
77        virtual void reset()
78        {
79            _visited.clear();
80        }
81
82        void apply(osg::Node& node)
83        {
84            if (_visited.count(&node)!=0) return;
85            _visited.insert(&node);
86
87            if (node.getStateSet()) apply(*(node.getStateSet()));
88            traverse(node);
89        }
90
91        void apply(osg::Geode& geode)
92        {
93            if (_visited.count(&geode)!=0) return;
94            _visited.insert(&geode);
95
96            if (geode.getStateSet()) apply(*(geode.getStateSet()));
97
98            for(unsigned int i=0; i<geode.getNumDrawables(); ++i)
99            {
100                if (geode.getDrawable(i)->getStateSet()) apply(*(geode.getDrawable(i)->getStateSet()));
101
102                osg::Geometry* geom = geode.getDrawable(i)->asGeometry();
103                if (geom) apply(*geom);
104            }
105        }
106
107        void replace(std::string& str, const std::string& original_phrase, const std::string& new_phrase)
108        {
109            std::string::size_type pos = 0;
110            while((pos=str.find(original_phrase, pos))!=std::string::npos)
111            {
112                std::string::size_type endOfPhrasePos = pos+original_phrase.size();
113                if (endOfPhrasePos<str.size())
114                {
115                    char c = str[endOfPhrasePos];
116                    if ((c>='0' && c<='9') ||
117                        (c>='a' && c<='z') ||
118                        (c>='A' && c<='Z'))
119                    {
120                        pos = endOfPhrasePos;
121                        continue;
122                    }
123                }
124
125                str.replace(pos, original_phrase.size(), new_phrase);
126            }
127        }
128
129        void apply(osg::Shader& shader)
130        {
131             if (_visited.count(&shader)!=0) return;
132            _visited.insert(&shader);
133
134            osg::notify(osg::NOTICE)<<"Shader "<<shader.getTypename()<<" ----before-----------"<<std::endl;
135            osg::notify(osg::NOTICE)<<shader.getShaderSource()<<std::endl;
136            shader.setShaderSource(convertShader(shader.getShaderSource()));
137            osg::notify(osg::NOTICE)<<"--after-----------"<<std::endl;
138            osg::notify(osg::NOTICE)<<shader.getShaderSource()<<std::endl;
139            osg::notify(osg::NOTICE)<<"---------------------"<<std::endl;
140        }
141
142        void apply(osg::StateSet& stateset)
143        {
144             if (_visited.count(&stateset)!=0) return;
145            _visited.insert(&stateset);
146
147            osg::notify(osg::NOTICE)<<"Found stateset "<<&stateset<<std::endl;
148            osg::Program* program = dynamic_cast<osg::Program*>(stateset.getAttribute(osg::StateAttribute::PROGRAM));
149            if (program)
150            {
151                osg::notify(osg::NOTICE)<<"   Found Program "<<program<<std::endl;
152                for(unsigned int i=0; i<program->getNumShaders(); ++i)
153                {
154                    apply(*(program->getShader(i)));
155                }
156            }
157       }
158
159        void apply(osg::Geometry& geom)
160        {
161            osg::notify(osg::NOTICE)<<"Found geometry "<<&geom<<std::endl;
162            if (geom.getVertexArray())
163            {
164                setVertexAttrib(geom, _vertexAlias, geom.getVertexArray(), false, osg::Geometry::BIND_PER_VERTEX);
165                geom.setVertexArray(0);
166            }
167
168            if (geom.getNormalArray())
169            {
170                setVertexAttrib(geom, _normalAlias, geom.getNormalArray(), true, geom.getNormalBinding());
171                geom.setNormalArray(0);
172            }
173
174            if (geom.getColorArray())
175            {
176                setVertexAttrib(geom, _colorAlias, geom.getColorArray(), true, geom.getColorBinding());
177                geom.setColorArray(0);
178            }
179
180            if (geom.getSecondaryColorArray())
181            {
182                setVertexAttrib(geom, _secondaryColorAlias, geom.getSecondaryColorArray(), true, geom.getSecondaryColorBinding());
183                geom.setSecondaryColorArray(0);
184            }
185
186            if (geom.getFogCoordArray())
187            {
188                // should we normalize the FogCoord array? Don't think so...
189                setVertexAttrib(geom, _fogCoordAlias, geom.getFogCoordArray(), false, geom.getSecondaryColorBinding());
190                geom.setFogCoordArray(0);
191            }
192
193            unsigned int maxNumTexCoords = geom.getNumTexCoordArrays();
194            if (maxNumTexCoords>8)
195            {
196                osg::notify(osg::NOTICE)<<"Warning: Ignoring "<<maxNumTexCoords-8<<" texture coordinate arrays, only 8 are currently supported in vertex attribute conversion code."<<std::endl;
197                maxNumTexCoords = 8;
198            }
199            for(unsigned int i=0; i<maxNumTexCoords; ++i)
200            {
201                if (geom.getTexCoordArray(i))
202                {
203                    setVertexAttrib(geom, _texCoordAlias[i], geom.getTexCoordArray(i), true, geom.getSecondaryColorBinding());
204                    geom.setTexCoordArray(i,0);
205                }
206                else
207                {
208                    osg::notify(osg::NOTICE)<<"Found empty TexCoordArray("<<i<<")"<<std::endl;
209                }
210            }
211        }
212
213        void setVertexAttrib(osg::Geometry& geom, const AttributeAlias& alias, osg::Array* array, bool normalize, osg::Geometry::AttributeBinding binding)
214        {
215            unsigned int index = alias.first;
216            const std::string& name = alias.second;
217            array->setName(name);
218            geom.setVertexAttribArray(index, array);
219            geom.setVertexAttribNormalize(index, normalize);
220            geom.setVertexAttribBinding(index, binding);
221
222            osg::notify(osg::NOTICE)<<"   vertex attrib("<<name<<", index="<<index<<", normalize="<<normalize<<" binding="<<binding<<")"<<std::endl;
223        }
224
225
226        typedef std::set<osg::Object*> Visited;
227        Visited         _visited;
228
229        AttributeAlias _vertexAlias;
230        AttributeAlias _normalAlias;
231        AttributeAlias _colorAlias;
232        AttributeAlias _secondaryColorAlias;
233        AttributeAlias _fogCoordAlias;
234        AttributeAlias _texCoordAlias[8];
235};
236
237
238
239int main(int argc, char *argv[])
240{
241    // use an ArgumentParser object to manage the program arguments.
242    osg::ArgumentParser arguments(&argc,argv);
243
244    // construct the viewer.
245    osgViewer::Viewer viewer(arguments);
246
247    std::string outputFileName;
248    while (arguments.read("-o",outputFileName)) {}
249
250    bool runShaderGen = true;
251    while (arguments.read("--shader-gen")) { runShaderGen = true; }
252    while (arguments.read("--no-shader-gen")) { runShaderGen = false; }
253
254    bool runConvertToVertexAttributes = true;
255    while (arguments.read("--vertex-attrib")) { runConvertToVertexAttributes = true; }
256    while (arguments.read("--no-vertex-attrib")) { runConvertToVertexAttributes = false; }
257
258    osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments);
259    if (!loadedModel.get())
260    {
261        osg::notify(osg::NOTICE)<<"No model loaded, please specify a model filename."<<std::endl;
262        return 1;
263    }
264
265    if (runShaderGen)
266    {
267        // convert fixed function pipeline to shaders
268        osgUtil::ShaderGenVisitor sgv;
269        loadedModel->accept(sgv);
270    }
271
272    if (runConvertToVertexAttributes)
273    {
274        // find any conventional vertex, colour, normal and tex coords arrays and convert to vertex attributes
275        ConvertToVertexAttibArrays ctvaa;
276        loadedModel->accept(ctvaa);
277    }
278
279    if (!outputFileName.empty())
280    {
281        osgDB::writeNodeFile(*loadedModel, outputFileName);
282        return 0;
283    }
284
285    // add a viewport to the viewer and attach the scene graph.
286    viewer.setSceneData(loadedModel.get());
287
288    return viewer.run();
289}
Note: See TracBrowser for help on using the browser.