multimodel.cpp 7.51 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 21 22 23
#ifdef _MSC_VER
# define snprintf _snprintf
#endif

24
CPPEXTERN_NEW_WITH_FOUR_ARGS(multimodel, t_symbol *, A_DEFSYM, t_floatarg, A_DEFFLOAT, t_floatarg, A_DEFFLOAT, t_floatarg, A_DEFFLOAT);
25 26 27 28 29 30 31 32 33 34

/////////////////////////////////////////////////////////
//
// multimodel
//
/////////////////////////////////////////////////////////
// Constructor
//
/////////////////////////////////////////////////////////
multimodel :: multimodel(t_symbol *filename, t_floatarg baseModel,
IOhannes m zmölnig's avatar
IOhannes m zmölnig committed
35
                         t_floatarg topModel, t_floatarg skipRate)
36
  : m_curModel(-1),
zmoelnig's avatar
zmoelnig committed
37
    m_currentH(1.f), m_currentW(1.f)
38 39
{
  inlet_new(this->x_obj, &this->x_obj->ob_pd, &s_float, gensym("mdl_num"));
40
  
41
  // make sure that there are some characters
42 43
  if (filename->s_name[0])
    openMess(filename->s_name, baseModel, topModel, skipRate);
44 45
}

IOhannes m zmölnig's avatar
IOhannes m zmölnig committed
46
////////////////////////////////////////////////////////
47 48 49 50 51
// Destructor
//
/////////////////////////////////////////////////////////
multimodel :: ~multimodel()
{
52
  cleanMultimodel();
53 54
}

55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
void multimodel :: openMess(const std::string&filename, 
                            float baseModel, float topModel, float skipRate)
{
  int skipRatei=static_cast<int>(skipRate);
  int topModeli=static_cast<int>(topModel);
  int baseModeli=static_cast<int>(baseModel);
  if (skipRatei == 0) {
    if (topModeli == 0)
      open(filename, 0, baseModeli, 1);
    else
      open(filename, baseModeli, topModeli, 1);
  }
  else open(filename, baseModeli, topModeli, skipRatei);
}


71 72 73 74
/////////////////////////////////////////////////////////
// cleanMultimodel
//
/////////////////////////////////////////////////////////
75
void multimodel :: cleanMultimodel(void)
76
{
77 78 79 80 81
  unsigned int i;
  for(i=0; i<m_loaders.size(); i++) {
    if (m_loaders[i])
      delete m_loaders[i];
    m_loaders[i]=NULL;
82
  }
83
  m_loaders.clear();
84 85 86
}

/////////////////////////////////////////////////////////
87
// open
88 89
//
/////////////////////////////////////////////////////////
90
void multimodel :: open(const std::string&filename, int baseModel, int topModel, int skipRate)
91
{
92
  std::vector<gem::plugins::modelloader*>loaders;
93

94
  if (!topModel) {
95
    error("requires an int for number of models");
96 97 98
    return;
  }
  if (baseModel > topModel) {
99
    error("top range less than base model");
100 101 102 103 104
    return;
  }
  if (skipRate < 1) skipRate = 1;
  char preName[256];
  char postName[256];
105

106
  int i = 0;
107
  const char *strPtr = filename.c_str();
108 109 110 111
  while (strPtr[i] && strPtr[i] != '*') {
    preName[i] = strPtr[i];
    i++;
  }
112

113
  if (!strPtr[i]) {
114
    error("unable to find * in file name");
115 116 117
    return;
  }

118
  preName[i] = '\0';
119 120
  strncpy(postName, &(strPtr[i+1]), 255);
  postName[255]='\0';
121

122
  // need to figure out how many filenames there are to load
123
  int numModels = (topModel + 1 - baseModel) / skipRate;
124 125 126

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

IOhannes m zmölnig's avatar
IOhannes m zmölnig committed
129 130
  char newName[MAXPDSTRING];
  newName[0]=0;
131

132
  for (i = 0; i < numModels; i++, realNum += skipRate) {
IOhannes m zmölnig's avatar
IOhannes m zmölnig committed
133 134 135
    snprintf(newName, MAXPDSTRING, "%s%d%s", bufName, realNum, postName);
    newName[MAXPDSTRING-1]=0;
    verbose(1, "trying to load '%s'", newName);
136 137 138 139 140 141 142 143

    gem::plugins::modelloader*loader=gem::plugins::modelloader::getInstance();
    if(!loader) break;

    if(loader->open(newName, m_properties))
      loaders.push_back(loader);
    else {
      delete loader;
144
      break;
145
    }
146 147
  }

148 149
  if(loaders.size()!=numModels) {
    /* outch, something went wrong! */
IOhannes m zmölnig's avatar
IOhannes m zmölnig committed
150
    error("failed to load model#%d of %d (%s)...resetting to original models", i, numModels, newName);
151 152 153 154 155
    unsigned int ui;
    for(ui=0; ui<loaders.size(); ui++) {
      if(loaders[ui])
        delete loaders[ui];
      loaders[ui]=NULL;
156 157 158
    }
    loaders.clear();
    return;
159 160
  }

161 162 163 164
  cleanMultimodel();
  m_loaders=loaders;
  m_curModel = 0;

165
  post("loaded models: %s %s from %d to %d skipping %d",
166
       bufName, postName, baseModel, topModel, skipRate);
167
  setModified();
168 169
}

170

171 172 173 174 175 176
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);
177 178 179
  }
}

180

181 182 183 184 185 186
/////////////////////////////////////////////////////////
// materialMess
//
/////////////////////////////////////////////////////////
void multimodel :: textureMess(int state)
{
187
  std::string textype;
188
  switch(state) {
189
  case 0:
190
    textype="linear";
191
    break;
192
  case 1:
193
    textype="spheremap";
194 195
    break;
  case 2:
196
    textype="UV";
197 198
    break;
  default:
199
    break;
200
  }
201 202 203 204 205 206 207
  if(textype.empty()) {
    m_properties.erase("textype");
  } else {
    gem::any value=textype;
    m_properties.set("textype", value);
  }
  applyProperties();
208 209
}

210 211 212 213 214 215 216 217 218
/////////////////////////////////////////////////////////
// smoothMess
//
/////////////////////////////////////////////////////////
void multimodel :: smoothMess(float fsmooth)
{  
  m_properties.set("smooth", fsmooth);
  applyProperties();
}
219

220 221 222 223 224
/////////////////////////////////////////////////////////
// matrialMess
//
/////////////////////////////////////////////////////////
void multimodel :: rescaleMess(bool state)
225
{
226 227 228
  gem::any value=state;
  m_properties.set("rescale", value);
  applyProperties();
229
}
230

231 232 233 234
/////////////////////////////////////////////////////////
// render
//
/////////////////////////////////////////////////////////
235
void multimodel :: render(GemState *state)
236
{
237
  if (0==m_loaders.size() || m_curModel<0 || ((unsigned int)m_curModel)>=m_loaders.size())
238
    return;
239

240 241 242
  if (state && (m_currentH != state->texCoordX(2) || m_currentW != state->texCoordY(2))) {
    m_currentH = state->texCoordX(2);
    m_currentW = state->texCoordY(2);
243

244 245 246 247
    m_properties.set("texwidth", m_currentW);
    m_properties.set("texheight", m_currentH);
    applyProperties();
  }
248 249
  #warning multimodel.render
  //m_loaders[m_curModel]->render();
250 251 252 253 254 255 256 257
}

/////////////////////////////////////////////////////////
// changeModel
//
/////////////////////////////////////////////////////////
void multimodel :: changeModel(int modelNum)
{
258
  if (modelNum < 0 || ((unsigned int)modelNum) >= m_loaders.size()) {
259 260 261
    error("selection %d out of range: 0..%d", modelNum, m_loaders.size()-1);
    return;
  }
262
  m_curModel = modelNum;
263
  //  setModified();
264 265 266 267 268 269 270 271
}

/////////////////////////////////////////////////////////
// static member function
//
/////////////////////////////////////////////////////////
void multimodel :: obj_setupCallback(t_class *classPtr)
{
zmoelnig's avatar
zmoelnig committed
272
  class_addmethod(classPtr, reinterpret_cast<t_method>(&multimodel::openMessCallback),
IOhannes m zmölnig's avatar
IOhannes m zmölnig committed
273
                  gensym("open"), A_SYMBOL, A_FLOAT, A_DEFFLOAT, A_DEFFLOAT, A_NULL);
274 275 276 277 278

  CPPEXTERN_MSG1(classPtr, "mdl_num", changeModel, int);
  CPPEXTERN_MSG1(classPtr, "rescale", rescaleMess, bool);
  CPPEXTERN_MSG1(classPtr, "texture", textureMess, int);
  CPPEXTERN_MSG1(classPtr, "smooth", smoothMess, float);
279
}
280
void multimodel :: openMessCallback(void *data, t_symbol *filesymbol, t_float baseModel,
IOhannes m zmölnig's avatar
IOhannes m zmölnig committed
281
                                    t_floatarg topModel, t_floatarg skipRate)
282
{
283
  GetMyClass(data)->openMess(filesymbol->s_name, baseModel, topModel, skipRate);
284
}