source: GTP/trunk/Lib/Vis/Preprocessing/src/mixkit/MxSMF.cxx @ 1097

Revision 1097, 9.9 KB checked in by mattausch, 18 years ago (diff)
Line 
1/************************************************************************
2
3  MxSMF
4
5  Copyright (C) 1998 Michael Garland.  See "COPYING.txt" for details.
6 
7  $Id: MxSMF.cxx,v 1.1 2002/09/24 16:53:54 wimmer Exp $
8
9 ************************************************************************/
10
11#include "stdmix.h"
12#include "mixio.h"
13#include "MxSMF.h"
14#include "MxVector.h"
15
16#define SMF_MAXLINE 65536
17
18
19MxSMFReader::cmd_entry MxSMFReader::read_cmds[] = {
20    { "v", &MxSMFReader::vertex },
21    { "t", &MxSMFReader::face },
22    { "f", &MxSMFReader::face },
23
24    // Properties and binding -- this is the new way to handle things
25    { "bind", &MxSMFReader::prop_bind },
26    { "n", &MxSMFReader::prop_normal },
27    { "c", &MxSMFReader::prop_color },
28    { "r", &MxSMFReader::prop_texcoord },
29
30    { "begin", &MxSMFReader::begin },
31    { "end", &MxSMFReader::end },
32
33    { "trans", &MxSMFReader::trans },
34    { "rot", &MxSMFReader::rot },
35    { "scale", &MxSMFReader::scale },
36
37    { "tex", &MxSMFReader::read_texture },
38    { "t_trans", &MxSMFReader::t_trans },
39    { "t_scale", &MxSMFReader::t_scale },
40
41    { NULL, NULL }
42};
43
44
45MxSMFReader::MxSMFReader()
46    : vx_stack(Mat4::I, 2), tx_stack(Mat4::I, 2),
47      vcorrect_stack(0, 2), vfirst_stack(1, 2)
48{
49    next_vertex=1;
50    next_face=1;
51    quad_count=0;
52    poly_count=0;
53    line_buffer = new char[SMF_MAXLINE];
54    unparsed_hook = NULL;
55
56    define_avars();
57}
58
59MxSMFReader::~MxSMFReader()
60{
61    delete[] line_buffer;
62}
63
64void MxSMFReader::v_xform(Vec3& v)
65{
66    Vec4 v2 = vx_stack.top() * Vec4(v,1);
67
68    v[X] = v2[X]/v2[W];
69    v[Y] = v2[Y]/v2[W];
70    v[Z] = v2[Z]/v2[W];
71}
72
73void MxSMFReader::t_xform(Vec2& v)
74{
75    Vec4 v2 = tx_stack.top() * Vec4(v[X],v[Y],0,1);
76
77    v[X] = v2[X]/v2[W];
78    v[Y] = v2[Y]/v2[W];
79}
80
81unsigned int MxSMFReader::vid_xform(int id)
82{
83    if( id < 0 )
84        id += next_vertex;
85    else
86        id += vcorrect_stack.top() + (vfirst_stack.top() - 1);
87
88    return id;
89}
90
91////////////////////////////////////////////////////////////////////////
92
93void MxSMFReader::define_avars()
94{
95    asp_store()->defvar("vertex_correction", MXASP_INT, &vcorrect_stack.top());
96}
97
98void MxSMFReader::update_avars()
99{
100    MxAspVar *avar;
101
102    avar = asp_store()->lookup("vertex_correction");
103    if( avar )
104        avar->bind("vertex_correction", MXASP_INT, &vcorrect_stack.top());
105}
106
107void MxSMFReader::begin(int, char *[], MxStdModel&)
108{
109    vx_stack.push();
110    tx_stack.push();
111    vfirst_stack.push(next_vertex);
112    vcorrect_stack.push();
113    update_avars();
114}
115
116void MxSMFReader::end(int, char *[], MxStdModel&)
117{
118    vx_stack.pop();
119    tx_stack.pop();
120    vfirst_stack.pop();
121    vcorrect_stack.pop();
122    update_avars();
123}
124
125void MxSMFReader::trans(int, char *argv[], MxStdModel&)
126{
127    Mat4 M = Mat4::trans(atof(argv[0]), atof(argv[1]), atof(argv[2]));
128    vx_stack.top() = vx_stack.top() * M;
129}
130
131void MxSMFReader::rot(int, char *argv[], MxStdModel&)
132{
133    Mat4 M;
134    switch( argv[0][0] )
135    {
136    case 'x':
137        M = Mat4::xrot(atof(argv[1]) * M_PI/180.0);
138        break;
139    case 'y':
140        M = Mat4::yrot(atof(argv[1]) * M_PI/180.0);
141        break;
142    case 'z':
143        M = Mat4::zrot(atof(argv[1]) * M_PI/180.0);
144        break;
145    default:
146        mxmsg_signal(MXMSG_WARN, "Malformed SMF rotation command.");
147        break;
148    }
149
150    vx_stack.top() = vx_stack.top() * M;
151}
152
153void MxSMFReader::scale(int, char *argv[], MxStdModel&)
154{
155    Mat4 M = Mat4::scale(atof(argv[0]), atof(argv[1]), atof(argv[2]));
156    vx_stack.top() = vx_stack.top() * M;
157}
158
159void MxSMFReader::t_trans(int, char *argv[], MxStdModel&)
160{
161    Mat4 M = Mat4::trans(atof(argv[0]), atof(argv[1]), 0.0);
162    tx_stack.top() = tx_stack.top() * M;
163}
164
165void MxSMFReader::t_scale(int, char *argv[], MxStdModel&)
166{
167    Mat4 M = Mat4::scale(atof(argv[0]), atof(argv[1]), 1.0);
168    tx_stack.top() = tx_stack.top() * M;
169}
170
171void MxSMFReader::vertex(int, char *argv[], MxStdModel& m)
172{
173    Vec3 v(atof(argv[0]), atof(argv[1]), atof(argv[2]));
174
175    v_xform(v);
176    next_vertex++;
177
178    m.add_vertex((float)v[X], (float)v[Y], (float)v[Z]);
179}
180
181void MxSMFReader::prop_bind(int argc, char *argv[], MxStdModel& m)
182{
183    if( argc < 2 )  return;     // Not enough arguments
184
185    switch( argv[0][0] )
186    {
187    case 'n': m.normal_binding(m.parse_binding(argv[1])); break;
188    case 'c': m.color_binding(m.parse_binding(argv[1])); break;
189    case 'r': m.texcoord_binding(m.parse_binding(argv[1])); break;
190    }
191}
192
193void MxSMFReader::prop_normal(int /*argc*/, char *argv[], MxStdModel& m)
194{
195    Vec3 n(atof(argv[0]), atof(argv[1]), atof(argv[2]));
196    //v_xform(n);  //!!BUG: Need to transform normals appropriately
197    unitize(n);
198    m.add_normal((float)n[X], (float)n[Y], (float)n[Z]);
199}
200
201void MxSMFReader::prop_color(int /*argc*/, char *argv[], MxStdModel& m)
202{
203    float r = (float)atof(argv[0]);
204    float g = (float)atof(argv[1]);
205    float b = (float)atof(argv[2]);
206    m.add_color(r, g, b);
207}
208
209void MxSMFReader::prop_texcoord(int /*argc*/, char *argv[], MxStdModel& m)
210{
211    Vec2 v(atof(argv[0]), atof(argv[1]));
212    t_xform(v);
213    m.add_texcoord((float)v[X], (float)v[Y]);
214}
215
216void MxSMFReader::read_texture(int /*argc*/, char *argv[], MxStdModel& m)
217{
218    ifstream in(argv[0]);
219    MxRaster *tex = pnm_read(in);
220    tex->vflip();
221    m.add_texmap(tex, argv[0]);
222}
223
224void MxSMFReader::face(int argc, char *argv[], MxStdModel& m)
225{
226    if( argc == 3 )
227    {
228        unsigned int v0 = vid_xform(atoi(argv[0]));
229        unsigned int v1 = vid_xform(atoi(argv[1]));
230        unsigned int v2 = vid_xform(atoi(argv[2]));
231
232        next_face++;
233        m.add_face(v0 - 1, v1 - 1, v2 - 1);
234    }
235    else if( argc == 4 )
236    {
237        if( !quad_count )
238            mxmsg_signalf(MXMSG_NOTE,
239            "Input polygon #%d is a quadrilateral.  Splitting it.", next_face);
240
241        quad_count++;
242
243        unsigned int v[4];
244        v[0] = vid_xform(atoi(argv[0])) - 1;
245        v[1] = vid_xform(atoi(argv[1])) - 1;
246        v[2] = vid_xform(atoi(argv[2])) - 1;
247        v[3] = vid_xform(atoi(argv[3])) - 1;
248
249        float e[4][3];
250        mxv_unitize(mxv_sub(e[0], m.vertex(v[1]), m.vertex(v[0]), 3), 3);
251        mxv_unitize(mxv_sub(e[1], m.vertex(v[2]), m.vertex(v[1]), 3), 3);
252        mxv_unitize(mxv_sub(e[2], m.vertex(v[3]), m.vertex(v[2]), 3), 3);
253        mxv_unitize(mxv_sub(e[3], m.vertex(v[0]), m.vertex(v[3]), 3), 3);
254
255        float a_02 = (1-mxv_dot(e[0], e[3], 3)) + (1-mxv_dot(e[1], e[2], 3));
256        float a_13 = (1-mxv_dot(e[1], e[0], 3)) + (1-mxv_dot(e[3], e[2], 3));
257
258        if( a_02 <= a_13 )
259        {
260            next_face++;  m.add_face(v[0], v[1], v[2]);
261            next_face++;  m.add_face(v[0], v[2], v[3]);
262        }
263        else
264        {
265            next_face++;  m.add_face(v[0], v[1], v[3]);
266            next_face++;  m.add_face(v[1], v[2], v[3]);
267        }
268    }
269    else
270    {
271        mxmsg_signalf(MXMSG_WARN,
272                      "Input polygon #%d has more than 4 sides.  Ignoring it.",
273                      next_face);
274       
275        poly_count++;
276    }
277}
278
279////////////////////////////////////////////////////////////////////////
280
281bool MxSMFReader::execute_command(const MxCmd& cmd, void *closure)
282{
283    MxStdModel& m = *(MxStdModel *)closure;
284    int argc = cmd.phrases[0].length();
285    char **argv = (char **)&cmd.phrases[0][0];
286
287    cmd_entry *entry = &read_cmds[0];
288    bool handled = false;
289
290    while( entry->name && !handled )
291        if( streq(entry->name, cmd.op) )
292        {
293            (this->*(entry->cmd))(argc, argv, m);
294            handled = true;
295        }
296        else
297            entry++;
298
299    if( !handled )
300        if( !unparsed_hook ||
301            unparsed_hook && !(*unparsed_hook)(cmd.op, argc, argv, m) )
302        {
303            return false;
304        }
305
306    return true;
307}
308
309void MxSMFReader::parse_line(char *line, MxStdModel& m)
310{
311    MxCmdParser::parse_line(line, &m);
312}
313
314MxStdModel *MxSMFReader::read(istream& in, MxStdModel *m)
315{
316    if( !m )
317        m = new MxStdModel(8, 16);
318
319    begin(0, NULL, *m);
320    while( !in.eof() )
321    {
322        in >> ws;
323        if( in.peek() == '#' )
324            in.ignore(SMF_MAXLINE, '\n');
325        else if( in.getline(line_buffer, SMF_MAXLINE, '\n').good() )
326            parse_line(line_buffer, *m);
327    }
328    end(0, NULL, *m);
329
330    if( quad_count )
331        mxmsg_signalf(MXMSG_WARN,
332                      "Split %d input quadrilaterals.  "
333                      "Auto-splitting does not preserve properties!",
334                      quad_count);
335    if( poly_count )
336        mxmsg_signalf(MXMSG_WARN,
337                      "Ignored %d input polygons of more than 4 sides.",
338                      poly_count);
339
340
341    return m;
342}
343
344#ifndef MIX_ANSI_IOSTREAMS
345MxStdModel *MxSMFReader::read(int fd, MxStdModel *m)
346{
347    ifstream in(dup(fd));       // Duplicate handle will be closed on exit
348    return read(in, m);
349}
350#endif
351
352
353
354MxSMFWriter::MxSMFWriter()
355{
356    vertex_annotate = NULL;
357    face_annotate = NULL;
358}
359
360void MxSMFWriter::write(ostream& out, MxStdModel& m)
361{
362    unsigned int i;
363
364    out << "begin" << endl;
365
366    for(unsigned int v=0; v<m.vert_count(); v++)
367    {
368        // We must output all vertices since numbering is implicit
369        if( vertex_annotate )  (*vertex_annotate)(out, m, v);
370        out << m.vertex(v) << endl;
371    }
372
373    for(unsigned int f=0; f<m.face_count(); f++)
374        if( m.face_is_valid(f) )
375        {
376            if( face_annotate ) (*face_annotate)(out, m, f);
377            out << m.face(f) << endl;
378        }
379
380    if( m.normal_binding() != MX_UNBOUND )
381    {
382        out << "bind n " << m.binding_name(m.normal_binding()) << endl;
383        for(i=0; i<m.normal_count(); i++)
384            out << m.normal(i) << endl;
385    }
386
387    if( m.color_binding() != MX_UNBOUND )
388    {
389        out << "bind c " << m.binding_name(m.color_binding()) << endl;
390        for(i=0; i<m.color_count(); i++)
391            out << m.color(i) << endl;
392    }
393
394    if( m.texcoord_binding() != MX_UNBOUND )
395    {
396        out << "tex " << m.texmap_name() << endl;
397        out << "bind r " << m.binding_name(m.texcoord_binding()) << endl;
398        for(i=0; i<m.texcoord_count(); i++)
399            out << m.texcoord(i) << endl;
400    }
401
402    out << "end" << endl;
403}
404
405#ifndef MIX_ANSI_IOSTREAMS
406void MxSMFWriter::write(int fd, MxStdModel& m)
407{
408    ofstream out(dup(fd));      // Duplicate handle will be closed on exit
409    write(out, m);
410}
411#endif
Note: See TracBrowser for help on using the repository browser.