multimodel.cpp 7.97 KB
Newer Older
1 2 3 4 5 6 7 8 9
////////////////////////////////////////////////////////
//
// GEM - Graphics Environment for Multimedia
//
// zmoelnig@iem.kug.ac.at
//
// Implementation file
//
//    Copyright (c) 1997-1999 Mark Danks.
zmoelnig's avatar
zmoelnig committed
10
//    Copyright (c) Günther Geiger.
zmoelnig's avatar
zmoelnig committed
11
//    Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
12 13 14 15 16
//    For information on usage and redistribution, and for a DISCLAIMER OF ALL
//    WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
//
/////////////////////////////////////////////////////////
#include "multimodel.h"
17
#include "Gem/State.h"
18 19
#include <stdio.h>

20
CPPEXTERN_NEW_WITH_FOUR_ARGS(multimodel, t_symbol *, A_DEFSYM, t_floatarg, A_DEFFLOAT, t_floatarg, A_DEFFLOAT, t_floatarg, A_DEFFLOAT);
21 22 23 24 25 26 27 28 29 30

/////////////////////////////////////////////////////////
//
// multimodel
//
/////////////////////////////////////////////////////////
// Constructor
//
/////////////////////////////////////////////////////////
multimodel :: multimodel(t_symbol *filename, t_floatarg baseModel,
IOhannes m zmölnig's avatar
IOhannes m zmölnig committed
31
                         t_floatarg topModel, t_floatarg skipRate)
32
  : m_curModel(-1),
zmoelnig's avatar
zmoelnig committed
33
    m_currentH(1.f), m_currentW(1.f)
34 35
{
  inlet_new(this->x_obj, &this->x_obj->ob_pd, &s_float, gensym("mdl_num"));
36
  
37
  // make sure that there are some characters
38
  if (filename->s_name[0]) {
zmoelnig's avatar
zmoelnig committed
39 40 41 42 43
    int skipRatei=static_cast<int>(skipRate);
    int topModeli=static_cast<int>(topModel);
    int baseModeli=static_cast<int>(baseModel);
    if (skipRatei == 0) {
      if (topModeli == 0)
44
        openMess(filename->s_name, 0, baseModeli, 1);
45
      else
46
        openMess(filename->s_name, baseModeli, topModeli, 1);
47
    }
48
    else openMess(filename->s_name, baseModeli, topModeli, skipRatei);
49 50 51
  }
}

IOhannes m zmölnig's avatar
IOhannes m zmölnig committed
52
////////////////////////////////////////////////////////
53 54 55 56 57 58 59 60 61 62 63
// Destructor
//
/////////////////////////////////////////////////////////
multimodel :: ~multimodel()
{
}

/////////////////////////////////////////////////////////
// cleanMultimodel
//
/////////////////////////////////////////////////////////
64
void multimodel :: cleanMultimodel(void)
65
{
66 67 68 69 70
  unsigned int i;
  for(i=0; i<m_loaders.size(); i++) {
    if (m_loaders[i])
      delete m_loaders[i];
    m_loaders[i]=NULL;
71
  }
72
  m_loaders.clear();
73 74 75 76 77 78
}

/////////////////////////////////////////////////////////
// openMess
//
/////////////////////////////////////////////////////////
79
void multimodel :: openMess(const std::string&filename, int baseModel, int topModel, int skipRate)
80
{
81
  std::vector<gem::plugins::modelloader*>loaders;
82

83
  if (!topModel) {
84
    error("requires an int for number of models");
85 86 87
    return;
  }
  if (baseModel > topModel) {
88
    error("top range less than base model");
89 90 91 92 93
    return;
  }
  if (skipRate < 1) skipRate = 1;
  char preName[256];
  char postName[256];
94

95
  int i = 0;
96
  const char *strPtr = filename.c_str();
97 98 99 100
  while (strPtr[i] && strPtr[i] != '*') {
    preName[i] = strPtr[i];
    i++;
  }
101

102
  if (!strPtr[i]) {
103
    error("unable to find * in file name");
104 105 106
    return;
  }

107
  preName[i] = '\0';
108
  strcpy(postName, &(strPtr[i+1]));
109

110
  // need to figure out how many filenames there are to load
111
  int numModels = (topModel + 1 - baseModel) / skipRate;
112 113 114

  int realNum = baseModel;
  char bufName[MAXPDSTRING];
zmoelnig's avatar
zmoelnig committed
115
  canvas_makefilename(const_cast<t_canvas*>(getCanvas()), preName, bufName, MAXPDSTRING);
116

117
  for (i = 0; i < numModels; i++, realNum += skipRate) {
118 119
    char newName[256];
    sprintf(newName, "%s%d%s", bufName, realNum, postName);
120

121 122 123 124 125
    loaders.push_back(gem::plugins::modelloader::getInstance());
    if(!loaders[i])
      break;
    if(!loaders[i]->open(newName, m_properties))
      break;
126 127
  }

128 129 130
  if(loaders.size()!=numModels) {
    /* outch, something went wrong! */
    error("failed to load model#%d of %d...resetting to original models", i, numModels);
131

132 133 134 135 136 137 138
    for(i=0; i<loaders.size(); i++) {
      if(loaders[i])
        delete loaders[i];
      loaders[i]=NULL;
    }
    loaders.clear();
    return;
139 140
  }

141 142 143 144
  cleanMultimodel();
  m_loaders=loaders;
  m_curModel = 0;

145
  post("loaded models: %s %s from %d to %d skipping %d",
146
       bufName, postName, baseModel, topModel, skipRate);
147
  setModified();
148 149
}

150

151 152 153 154 155 156
void multimodel :: applyProperties(void)
{
  unsigned int i;
  for(i=0; i<m_loaders.size(); i++) {
    if(m_loaders[i])
      m_loaders[i]->setProperties(m_properties);
157 158 159
  }
}

160

161 162 163 164 165 166
/////////////////////////////////////////////////////////
// materialMess
//
/////////////////////////////////////////////////////////
void multimodel :: textureMess(int state)
{
167
  std::string textype;
168
  switch(state) {
169
  case 0:
170
    textype="linear";
171
    break;
172
  case 1:
173
    textype="spheremap";
174 175
    break;
  case 2:
176
    textype="UV";
177 178
    break;
  default:
179
    break;
180
  }
181 182 183 184 185 186 187
  if(textype.empty()) {
    m_properties.erase("textype");
  } else {
    gem::any value=textype;
    m_properties.set("textype", value);
  }
  applyProperties();
188 189
}

190 191 192 193 194 195 196 197 198
/////////////////////////////////////////////////////////
// smoothMess
//
/////////////////////////////////////////////////////////
void multimodel :: smoothMess(float fsmooth)
{  
  m_properties.set("smooth", fsmooth);
  applyProperties();
}
199

200 201 202 203 204
/////////////////////////////////////////////////////////
// matrialMess
//
/////////////////////////////////////////////////////////
void multimodel :: rescaleMess(bool state)
205
{
206 207 208
  gem::any value=state;
  m_properties.set("rescale", value);
  applyProperties();
209
}
210

211 212 213 214
/////////////////////////////////////////////////////////
// render
//
/////////////////////////////////////////////////////////
215
void multimodel :: render(GemState *state)
216
{
217 218
  if (0==m_loaders.size() || m_curModel<0 || m_curModel>=m_loaders.size())
    return;
219

220 221 222
  if (state && (m_currentH != state->texCoordX(2) || m_currentW != state->texCoordY(2))) {
    m_currentH = state->texCoordX(2);
    m_currentW = state->texCoordY(2);
223

224 225 226 227
    m_properties.set("texwidth", m_currentW);
    m_properties.set("texheight", m_currentH);
    applyProperties();
  }
228

229
  m_loaders[m_curModel]->render();
230 231 232 233 234 235 236 237
}

/////////////////////////////////////////////////////////
// changeModel
//
/////////////////////////////////////////////////////////
void multimodel :: changeModel(int modelNum)
{
238 239 240 241
  if (modelNum < 0 || modelNum >= m_loaders.size()) {
    error("selection %d out of range: 0..%d", modelNum, m_loaders.size()-1);
    return;
  }
242
  m_curModel = modelNum;
243
  //  setModified();
244 245 246 247 248 249 250 251
}

/////////////////////////////////////////////////////////
// static member function
//
/////////////////////////////////////////////////////////
void multimodel :: obj_setupCallback(t_class *classPtr)
{
zmoelnig's avatar
zmoelnig committed
252
  class_addmethod(classPtr, reinterpret_cast<t_method>(&multimodel::openMessCallback),
IOhannes m zmölnig's avatar
IOhannes m zmölnig committed
253
                  gensym("open"), A_SYMBOL, A_FLOAT, A_DEFFLOAT, A_DEFFLOAT, A_NULL);
zmoelnig's avatar
zmoelnig committed
254
  class_addmethod(classPtr, reinterpret_cast<t_method>(&multimodel::changeModelCallback),
IOhannes m zmölnig's avatar
IOhannes m zmölnig committed
255
                  gensym("mdl_num"), A_FLOAT, A_NULL);
zmoelnig's avatar
zmoelnig committed
256
  class_addmethod(classPtr, reinterpret_cast<t_method>(&multimodel::rescaleMessCallback),
IOhannes m zmölnig's avatar
IOhannes m zmölnig committed
257
                  gensym("rescale"), A_FLOAT, A_NULL);
zmoelnig's avatar
zmoelnig committed
258
  class_addmethod(classPtr, reinterpret_cast<t_method>(&multimodel::textureMessCallback),
IOhannes m zmölnig's avatar
IOhannes m zmölnig committed
259
                  gensym("texture"), A_FLOAT, A_NULL);
260
}
261
void multimodel :: openMessCallback(void *data, t_symbol *filesymbol, t_floatarg baseModel,
IOhannes m zmölnig's avatar
IOhannes m zmölnig committed
262
                                    t_floatarg topModel, t_floatarg skipRate)
263
{
zmoelnig's avatar
zmoelnig committed
264 265 266
  int skipRatei=static_cast<int>(skipRate);
  int topModeli=static_cast<int>(topModel);
  int baseModeli=static_cast<int>(baseModel);
267
  std::string filename=filesymbol->s_name;
zmoelnig's avatar
zmoelnig committed
268 269

  if (skipRatei == 0)
270
    {
zmoelnig's avatar
zmoelnig committed
271
      if (topModeli == 0)
IOhannes m zmölnig's avatar
IOhannes m zmölnig committed
272
        GetMyClass(data)->openMess(filename, 0, topModeli, 0);
273
      else
IOhannes m zmölnig's avatar
IOhannes m zmölnig committed
274
        GetMyClass(data)->openMess(filename, baseModeli, topModeli, 0);
275 276
    }
  else
zmoelnig's avatar
zmoelnig committed
277
    GetMyClass(data)->openMess(filename, baseModeli, topModeli, skipRatei);
278 279 280
}
void multimodel :: changeModelCallback(void *data, t_floatarg modelNum)
{
zmoelnig's avatar
zmoelnig committed
281
  GetMyClass(data)->changeModel(static_cast<int>(modelNum));
282 283 284
}
void multimodel :: rescaleMessCallback(void *data, t_floatarg state)
{
zmoelnig's avatar
zmoelnig committed
285
  GetMyClass(data)->rescaleMess(static_cast<int>(state));
286
}
287 288
void multimodel :: textureMessCallback(void *data, t_floatarg state)
{
zmoelnig's avatar
zmoelnig committed
289
  GetMyClass(data)->textureMess(static_cast<int>(state));
290
}