////////////////////////////////////////////////////////
//
// GEM - Graphics Environment for Multimedia
//
// mark@danks.org
//
// Implementation file
//
//    Copyright (c) 1997-1999 Mark Danks.
//    For information on usage and redistribution, and for a DISCLAIMER OF ALL
//    WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
//
/////////////////////////////////////////////////////////

#include "model.h"

#include "td.h"

CPPEXTERN_NEW_WITH_ONE_ARG(model, t_symbol *, A_DEFSYM)

/////////////////////////////////////////////////////////
//
// model
//
/////////////////////////////////////////////////////////
// Constructor
//
/////////////////////////////////////////////////////////
model :: model(t_symbol *filename)
       : m_dispList(0), m_rescaleModel(1)
{
    // make sure that there are some characters
    if (filename->s_name[0]) openMess(filename);
}

/////////////////////////////////////////////////////////
// Destructor
//
/////////////////////////////////////////////////////////
model :: ~model()
{
    cleanModel();
}

/////////////////////////////////////////////////////////
// cleanModel
//
/////////////////////////////////////////////////////////
void model :: cleanModel()
{
    if (m_dispList)
    {
	    // destroy display list
	    glDeleteLists(m_dispList, 1);
	    m_dispList = 0;
    }
}

/////////////////////////////////////////////////////////
// rescaleMess
//
/////////////////////////////////////////////////////////
void model :: rescaleMess(int state)
{
	m_rescaleModel = state;
}

/////////////////////////////////////////////////////////
// openMess
//
/////////////////////////////////////////////////////////
void model :: openMess(t_symbol *filename)
{
    cleanModel();
    
    char buf[MAXPDSTRING];
    canvas_makefilename(getCanvas(), filename->s_name, buf, MAXPDSTRING);

    // read the object in
    TDobject *tdObject = tdReadObject(buf);

    if (!tdObject) return;    

    // set the size to -1 to 1
    //
	if (m_rescaleModel)
		tdSize(tdObject, 0.0);

    // generate normals if this
    // object doesn't have them.
    //
    if (tdObject->num_normals == 0)
		tdGenSmoothNormals(tdObject);

    // generate texture vertices if
    // this object doesn't have them
    //
    if (tdObject->num_texvertices == 0)
		tdGenLinearTexvertices(tdObject);
    
    // build a display list
	tdGenTriangles(tdObject);
    m_dispList = tdGenDList(tdObject, TD_TRIANGLES, TD_VERTEX | TD_NORMAL | TD_TEXVERTEX); 

    // nuke it, we don't need it anymore
    tdDeleteObject(tdObject);

    this->setModified();
}

/////////////////////////////////////////////////////////
// render
//
/////////////////////////////////////////////////////////
void model :: render(GemState *)
{
    if (!m_dispList)
		return;
    glCallList(m_dispList);
}

/////////////////////////////////////////////////////////
// static member function
//
/////////////////////////////////////////////////////////
void model :: obj_setupCallback(t_class *classPtr)
{
    class_addmethod(classPtr, (t_method)&model::openMessCallback,
    	    gensym("open"), A_SYMBOL, A_NULL);
    class_addmethod(classPtr, (t_method)&model::rescaleMessCallback,
    	    gensym("rescale"), A_FLOAT, A_NULL);
}
void model :: openMessCallback(void *data, t_symbol *filename)
{
    GetMyClass(data)->openMess(filename);
}
void model :: rescaleMessCallback(void *data, t_floatarg state)
{
    GetMyClass(data)->rescaleMess((int)state);
}
