aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/mimesh/mimesh.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/others/mimesh/mimesh.cpp')
-rw-r--r--src/others/mimesh/mimesh.cpp396
1 files changed, 396 insertions, 0 deletions
diff --git a/src/others/mimesh/mimesh.cpp b/src/others/mimesh/mimesh.cpp
new file mode 100644
index 0000000..e710c4c
--- /dev/null
+++ b/src/others/mimesh/mimesh.cpp
@@ -0,0 +1,396 @@
1/*
2 This is a wrapper around the libg3d mesh loading library.
3
4 Copyright (c) 2010, Dawid Seikel.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; version 2 of the License.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#include "linden_common.h"
21#include "m3math.h"
22#include "m4math.h"
23#include "llcamera.h"
24#include "llpartdata.h"
25#include "lldrawable.h"
26#include "llface.h"
27#include "llvovolume.h"
28#include "pipeline.h"
29#include "glib.h" // For G_BEGIN_DECLS
30#include "gl.h"
31#include "mimesh.h"
32#include "g3d/plugins.h"
33
34void cmdline_printchat(std::string message);
35
36
37G3DContext* mimesh::context;
38
39void mimesh::startup(void)
40{
41 GSList *item;
42
43 context = g3d_context_new();
44
45 // Print the details.
46 for (item = context->plugins; item != NULL; item = item->next)
47 {
48 G3DPlugin *plugin = (G3DPlugin *) item->data;
49 gchar **pext = plugin->extensions;
50 std::string message;
51
52 if (plugin->type == G3D_PLUGIN_IMPORT)
53 message = "Model";
54 else
55 message = "Image";
56 message += " loader " + std::string(plugin->name) + " - " + std::string(plugin->desc_func(context)) + "\n For file extensions : ";
57
58 while(*pext)
59 {
60 message += std::string(*pext) + " ";
61 pext ++;
62 }
63 LL_WARNS("startup") << message << LL_ENDL;
64 cmdline_printchat(message);
65 }
66}
67
68void mimesh::load(LLViewerObject* object, std::string URL)
69{
70 if ((URL.substr(0, 7).compare("file://") == 0) || (URL.substr(0, 7).compare("http://") == 0))
71 {
72 if ((NULL == object->mimeshModel) || (0 != object->mimeshURL.compare(URL)))
73 {
74 // Also check if it's not been moved to the volume.
75 if (object->getVolume() && (object->getVolume()->mimeshModel))
76 {
77 if (0 == object->mimeshURL.compare(URL))
78 return;
79 }
80 object->mimeshURL = URL;
81 std::string temp_URL = URL;
82 if (temp_URL.substr(0, 7).compare("file://") == 0)
83 temp_URL = temp_URL.substr(6);
84 if (NULL != context)
85 {
86 G3DModel* model;
87
88 model = g3d_model_load(context, temp_URL.c_str());
89 if (model)
90 {
91 texture_load_all_textures(model);
92 cmdline_printchat("Loaded model " + temp_URL);
93 if (object->mimeshModel)
94 {
95 cmdline_printchat("Freeing old model.");
96 g3d_model_free(object->mimeshModel);
97 }
98 // OK, this is BEFORE the volume is set in the VeiwerObject. Grumble.
99 object->mimeshModel = model;
100 }
101 else
102 cmdline_printchat("Failed to load model " + URL);
103 }
104 else
105 cmdline_printchat("No G3D context!");
106 }
107 }
108 else
109 object->mimeshURL.clear();
110}
111
112
113/*
114 What to do with the data?
115
116LLVeiwerObject contains a pointer to a LLDrawable
117
118LLDrawable has our LLVOVolume
119 contains a LLViewerObject, which apparently can be cast to a LLVOVolume
120 LLVOVolume inherits from LLViewerObject <- LLPrimitive <- LLXform
121 LLVOAvataer inherits from LLViewerObject and LLCharacter
122 LLPrimitive contains a protected pointer to LLVolume mVolumep, with a public getVolume().
123
124LLVOVolume->mVolumeChanged = TRUE;
125
126LLVOVolume::processUpdateMesssages calls the parent (LLViewerObject) version first.
127 THAT loads our model.
128Modified LLVOVolume::processUpdateMesssages to stuff the model into llVolumeParams.
129 Which calls LLVOVolume::setVolume()
130 Which calls LLPrimitive::setVolume() only thing that does outside of LLPrimitive (oh and llvotextbubble).
131 Then for sculpties it calls LLVOVolume->sculpt() which does the actual work.
132
133We want to intercept LLVolume->sculpt() to load our mesh data instead.
134Actually load our mesh data before sculpt(), then disable that from ever being called.
135
136LLVolumeParams::mSculptID is the sculptie map texture UUID.
137
138LLVolume->mMesh gets the original prim and sculpty data.
139llmath/LLVolume->mMesh is - std::vector<Point> mMesh; // Can treat it like an array.
140mMesh is protected.
141Point contains a LLVector3 - Point->mPos (-0.5 to 0.5)
142LLVolumeFace->mVertices gets a copy.
143LLFace->mVertexBuffer gets a copy.
144 Does the actual drawing (pushing vertices and such to GL).
145 Has pointers to LLDrawable and LLViewerObject.
146
147Hmmm, does everything assume that a LLVolume has a path and a profile?
148
149G3DModel
150 gint32 glflags =
151 // G3D_FLAG_GL_SPECULAR |
152 G3D_FLAG_GL_SHININESS |
153 G3D_FLAG_GL_ALLTWOSIDE |
154 G3D_FLAG_GL_TEXTURES;
155
156 for(f = 1.0; f >= 0.0; f -= 0.2)
157 {
158 G3DFloat min_a = f, max_a = f + 0.2;
159 gl_draw_objects(glflags, model->objects, min_a, max_a);
160
161 GSList *olist = model->objects;
162 while(olist != NULL)
163 {
164 int i;
165 G3DObject object = (G3DObject *) olist->data;
166 olist = olist->next;
167 dont_render = FALSE;
168 // don't render invisible objects.
169 if(object->hide) continue;
170
171 for(i = 0; i < object->_num_faces; i++)
172 {
173 gl_draw_face(glflags, object, i, min_a, max_a, &dont_render, &init);
174
175 // draw triangles
176 for(j = 0; j < 3; j++)
177 {
178 if((glflags & G3D_FLAG_GL_TEXTURES) && (object->_flags[i] & G3D_FLAG_FAC_TEXMAP))
179 {
180 glTexCoord2f( object->_tex_coords[(i * 3 + j) * 2 + 0],
181 object->_tex_coords[(i * 3 + j) * 2 + 1]);
182 }
183
184 glNormal3f( object->_normals[(i * 3 + j) * 3 + 0],
185 object->_normals[(i * 3 + j) * 3 + 1],
186 object->_normals[(i * 3 + j) * 3 + 2]);
187 glVertex3f( object->vertex_data[object->_indices[i * 3 + j] * 3 + 0],
188 object->vertex_data[object->_indices[i * 3 + j] * 3 + 1],
189 object->vertex_data[object->_indices[i * 3 + j] * 3 + 2]);
190 } // 1 .. 3
191 } // all faces.
192
193 // handle sub-objects recursively.
194 gl_draw_objects(glflags, object->objects, min_a, max_a);
195 }
196 }
197*/
198
199
200static int countTriangles(GSList *objects)
201{
202 int result = 0;
203
204 while(objects != NULL)
205 {
206 G3DObject *object = (G3DObject *) objects->data;
207
208 objects = objects->next;
209 if (object->hide) continue;
210 result += object->_num_faces;
211 result += countTriangles(object->objects);
212 }
213 return result;
214}
215
216
217static void getVerticesAndStuff(GSList *objects, std::vector<LLVolume::Point> mesh, LLVolumeFace& vf, int *i, LLVector3& face_min, LLVector3& face_max)
218{
219 while(objects != NULL)
220 {
221 G3DObject *object = (G3DObject *) objects->data;
222 int j, k;
223 int count = object->_num_faces;
224
225 objects = objects->next;
226 if (object->hide) continue;
227
228 for (k = 0 ; k < count; k++)
229 {
230 for (j = 0; j < 3; j++)
231 {
232// mesh[*i].mPos.mV[0] = object->vertex_data[ object->_indices [k * 3 + j] * 3 + 0];
233// mesh[*i].mPos.mV[1] = object->vertex_data[ object->_indices [k * 3 + j] * 3 + 1];
234// mesh[*i].mPos.mV[2] = object->vertex_data[ object->_indices [k * 3 + j] * 3 + 2];
235 mesh[*i].mPos = LLVector3( object->vertex_data [(k * 3 + j) * 3 + 0], // F64() = G3DFloat()
236 object->vertex_data [(k * 3 + j) * 3 + 1],
237 object->vertex_data [(k * 3 + j) * 3 + 2]);
238
239 vf.mVertices[*i].mPosition = mesh[*i].mPos;
240// vf.mVertices[*i].mTexCoord = LLVector2( object->_tex_coords [(k * 3 + j) * 2 + 0], // F32() = G3DFloat()
241// object->_tex_coords [(k * 3 + j) * 2 + 1]);
242
243 vf.mVertices[*i].mNormal = LLVector3( object->_normals [(k * 3 + j) * 3 + 0], // F64() = G3DFloat()
244 object->_normals [(k * 3 + j) * 3 + 1],
245 object->_normals [(k * 3 + j) * 3 + 2]);
246
247 vf.mVertices[*i].mBinormal = LLVector3(0,0,0); // Um, do we have binormals? Viewer does not seem to have them either. shrugs
248
249 if (0 == *i)
250 {
251 face_min = face_max = mesh[*i].mPos;
252 }
253 else
254 {
255 update_min_max(face_min, face_max, mesh[*i].mPos);
256 }
257
258 // Damn, at this point viewer wants quads, but the library uses triangles.
259 // Those few times when the library deals with quads, the forth is just the next index.
260 // No idea what the edges are for. -1 seems to mean no edge, so go with that for now.
261 vf.mIndices [(*i) * 6 + j] = object->_indices[k * 3 + j];
262 vf.mEdge [(*i) * 6 + j] = -1;
263 }
264 vf.mIndices [(*i) * 6 + 3] = object->_indices[k * 3 + 0]; // U16 = guint32
265 vf.mIndices [(*i) * 6 + 4] = object->_indices[k * 3 + 3];
266 vf.mIndices [(*i) * 6 + 5] = object->_indices[k * 3 + 1];
267 vf.mEdge [(*i) * 6 + 3] = -1; // S32 = Fucked if I know.
268 vf.mEdge [(*i) * 6 + 4] = -1;
269 vf.mEdge [(*i) * 6 + 5] = -1;
270 (*i)++;
271 }
272
273 getVerticesAndStuff(object->objects, mesh, vf, i, face_min, face_max);
274 }
275}
276
277
278void mimesh::getData(LLVolume* volume)
279{
280 G3DModel *model = volume->mimeshModel;
281 if ((model) && (model->objects))
282 {
283 int vertices = countTriangles(model->objects) * 3;
284 int index = 0;
285
286 LL_WARNS("getData") << "Transferring model data for " << std::string(model->filename) << " with " << vertices << " vertices." << LL_ENDL;
287
288 /*
289 sculpt_calc_mesh_resolution(sculpt_width, sculpt_height, sculpt_type, sculpt_detail, requested_sizeS, requested_sizeT);
290 vertices = T * S / 4 = faces / 16 * 16 / 4 = T
291 ratio = T / S = faces / 16 / 16 = faces / 256
292 s = sqrt(vertices / ratio) = T / faces / 256 = faces / 16 / faces / 256 = 16 (sqrt = 4)
293 s = llmax(s, 4); // no degenerate sizes, please = 4
294 t = vertices / s; = T / 4 = faces / 64
295 t = llmax(t, 4); // no degenerate sizes, please
296 s = vertices / t; = T / s = faces / 16 / s
297 */
298 S32 requested_sizeS = llmax (((int) sqrt(vertices)), 4);
299 S32 requested_sizeT = llmax(vertices / requested_sizeS, 4);
300 // create meshes with high LOD always
301 F32 sculpt_detail = 4.0;
302
303LL_WARNS("getData") << "mimesh 0" << LL_ENDL;
304 volume->mPathp->generate(volume->mParams.getPathParams(), sculpt_detail, 0, TRUE, requested_sizeS);
305 volume->mProfilep->generate(volume->mParams.getProfileParams(), volume->mPathp->isOpen(), sculpt_detail, 0, TRUE, requested_sizeT);
306
307 S32 sizeS = volume->mPathp->mPath.size(); // we requested a specific size, now see what we really got
308 S32 sizeT = volume->mProfilep->mProfile.size(); // we requested a specific size, now see what we really got
309
310LL_WARNS("getData") << "mimesh 1 S " << requested_sizeS << "->" << sizeS << " T " << requested_sizeT << "->" << sizeT << " = " << (sizeS * sizeT) << LL_ENDL;
311 volume->sNumMeshPoints -= volume->mMesh.size();
312 volume->mMesh.resize(sizeS * sizeT);
313 volume->sNumMeshPoints += volume->mMesh.size();
314LL_WARNS("getData") << "mimesh 2" << LL_ENDL;
315 volume->mFaceMask = LLVolumeFace::SIDE_MASK | LLVolumeFace::OUTER_MASK; // Seems to be the default.
316 volume->mSculptLevel = -2;
317 volume->mimeshNeedData = FALSE;
318
319LL_WARNS("getData") << "mimesh 3" << LL_ENDL;
320 // Delete any existing faces so that they get regenerated
321 volume->mVolumeFaces.clear();
322LL_WARNS("getData") << "mimesh 4" << LL_ENDL;
323// volume->createVolumeFaces();
324 S32 num_faces = volume->mProfilep->mFaces.size();
325 volume->mVolumeFaces.resize(num_faces);
326
327LL_WARNS("getData") << "mimesh 5 " << num_faces << LL_ENDL;
328 // It's pretending to be a sculpty, so only one "face / side".
329 // Initialize volume faces with parameter data
330 for (S32 i = 0; i < num_faces; i++)
331 {
332LL_WARNS("getData") << "mimesh 5.0 " << LL_ENDL;
333 LLVolumeFace& vf = volume->mVolumeFaces[i];
334 LLProfile::Face& face = volume->mProfilep->mFaces[i];
335 LLVector3& face_min = vf.mExtents[0];
336 LLVector3& face_max = vf.mExtents[1];
337
338 vf.mTypeMask = volume->mFaceMask;
339 vf.mBeginS = face.mIndex;
340 vf.mNumS = face.mCount;
341 vf.mBeginT = 0;
342 vf.mNumT = volume->getPath().mPath.size();
343 vf.mID = i;
344
345 // Just to confuse matters, S and T are reversed from what it is above. Blame LL.
346LL_WARNS("getData") << "mimesh 5.1 S " << vf.mBeginS << "->" << vf.mNumS << " T " << vf.mBeginT << "->" << vf.mNumT << LL_ENDL;
347// vf.create(volume, FALSE);
348 S32 num_vertices = vf.mNumS * vf.mNumT;
349 S32 num_indices = (vf.mNumS - 1) * (vf.mNumT - 1) * 6;
350
351LL_WARNS("getData") << "mimesh 5.2 " << LL_ENDL;
352 vf.mVertices.resize(vertices);
353 vf.mIndices.resize(num_indices);
354 vf.mEdge.resize(num_indices);
355
356LL_WARNS("getData") << "mimesh 5.3 " << LL_ENDL;
357 vf.mCenter.clearVec();
358
359LL_WARNS("getData") << "mimesh 5.4 " << LL_ENDL;
360 getVerticesAndStuff(model->objects, volume->mMesh, vf, &index, face_min, face_max);
361
362LL_WARNS("getData") << "mimesh 5.5 " << LL_ENDL;
363 vf.mCenter = (face_min + face_max) * 0.5f;
364
365LL_WARNS("getData") << "mimesh 5.6 " << LL_ENDL;
366 }
367LL_WARNS("getData") << "mimesh 6" << LL_ENDL;
368 }
369LL_WARNS("getData") << "mimesh 7" << LL_ENDL;
370}
371
372
373void mimesh::render(LLViewerObject* object)
374{
375 gl_draw_model(object->mimeshModel);
376}
377
378void mimesh::unload(LLViewerObject* object)
379{
380 cmdline_printchat("VO Deleting model data for " + std::string(object->mimeshModel->filename));
381 g3d_model_free(object->mimeshModel);
382 object->mimeshModel = NULL;
383 object->mimeshURL.clear();
384}
385
386void mimesh::unload(LLVolume* volume)
387{
388 cmdline_printchat("V Deleting model data for " + std::string(volume->mimeshModel->filename));
389 g3d_model_free(volume->mimeshModel);
390 volume->mimeshModel = NULL;
391}
392
393void mimesh::shutdown(void)
394{
395 g3d_context_free(context);
396}