multimodel.cpp 8.1 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

IOhannes m zmölnig's avatar
IOhannes m zmölnig committed
117 118
  char newName[MAXPDSTRING];
  newName[0]=0;
119
  for (i = 0; i < numModels; i++, realNum += skipRate) {
IOhannes m zmölnig's avatar
IOhannes m zmölnig committed
120 121
    snprintf(newName, MAXPDSTRING, "%s%d%s", bufName, realNum, postName);
    newName[MAXPDSTRING-1]=0;
122

IOhannes m zmölnig's avatar
IOhannes m zmölnig committed
123
    verbose(1, "trying to load '%s'", newName);
124 125 126 127 128
    loaders.push_back(gem::plugins::modelloader::getInstance());
    if(!loaders[i])
      break;
    if(!loaders[i]->open(newName, m_properties))
      break;
129 130
  }

131 132
  if(loaders.size()!=numModels) {
    /* outch, something went wrong! */
IOhannes m zmölnig's avatar
IOhannes m zmölnig committed
133
    error("failed to load model#%d of %d (%s)...resetting to original models", i, numModels, newName);
134

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

144 145 146 147
  cleanMultimodel();
  m_loaders=loaders;
  m_curModel = 0;

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

153

154 155 156 157 158 159
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);
160 161 162
  }
}

163

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

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

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

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

223 224 225
  if (state && (m_currentH != state->texCoordX(2) || m_currentW != state->texCoordY(2))) {
    m_currentH = state->texCoordX(2);
    m_currentW = state->texCoordY(2);
226

227 228 229 230
    m_properties.set("texwidth", m_currentW);
    m_properties.set("texheight", m_currentH);
    applyProperties();
  }
231

232
  m_loaders[m_curModel]->render();
233 234 235 236 237 238 239 240
}

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

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

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