PageRenderTime 44ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/CS/migrated/branches/R0_92/plugins/mesh/surf/object/surf.cpp

#
C++ | 547 lines | 435 code | 65 blank | 47 comment | 42 complexity | 25dc314da3d1ab727db1015022f791bf MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, LGPL-2.0
  1. /*
  2. Copyright (C) 2001 by Jorrit Tyberghein
  3. This library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Library General Public
  5. License as published by the Free Software Foundation; either
  6. version 2 of the License, or (at your option) any later version.
  7. This library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Library General Public License for more details.
  11. You should have received a copy of the GNU Library General Public
  12. License along with this library; if not, write to the Free
  13. Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. */
  15. #include "cssysdef.h"
  16. #include "csgeom/math3d.h"
  17. #include "surf.h"
  18. #include "iengine/movable.h"
  19. #include "iengine/rview.h"
  20. #include "ivideo/graph3d.h"
  21. #include "ivideo/graph2d.h"
  22. #include "ivideo/material.h"
  23. #include "ivideo/vbufmgr.h"
  24. #include "iengine/material.h"
  25. #include "iengine/camera.h"
  26. #include "igeom/clip2d.h"
  27. #include "iengine/engine.h"
  28. #include "iengine/light.h"
  29. #include "iutil/objreg.h"
  30. #include "qsqrt.h"
  31. //#define SURF_DEBUG
  32. CS_IMPLEMENT_PLUGIN
  33. SCF_IMPLEMENT_IBASE (csSurfMeshObject)
  34. SCF_IMPLEMENTS_INTERFACE (iMeshObject)
  35. SCF_IMPLEMENTS_EMBEDDED_INTERFACE (iSurfaceState)
  36. SCF_IMPLEMENTS_EMBEDDED_INTERFACE (iVertexBufferManagerClient)
  37. SCF_IMPLEMENT_IBASE_END
  38. SCF_IMPLEMENT_EMBEDDED_IBASE (csSurfMeshObject::SurfaceState)
  39. SCF_IMPLEMENTS_INTERFACE (iSurfaceState)
  40. SCF_IMPLEMENT_EMBEDDED_IBASE_END
  41. SCF_IMPLEMENT_EMBEDDED_IBASE (csSurfMeshObject::eiVertexBufferManagerClient)
  42. SCF_IMPLEMENTS_INTERFACE (iVertexBufferManagerClient)
  43. SCF_IMPLEMENT_EMBEDDED_IBASE_END
  44. csSurfMeshObject::csSurfMeshObject (iMeshObjectFactory* factory)
  45. {
  46. SCF_CONSTRUCT_IBASE (NULL);
  47. SCF_CONSTRUCT_EMBEDDED_IBASE (scfiSurfaceState);
  48. SCF_CONSTRUCT_EMBEDDED_IBASE (scfiVertexBufferManagerClient);
  49. logparent = NULL;
  50. csSurfMeshObject::factory = factory;
  51. initialized = false;
  52. cur_cameranr = -1;
  53. cur_movablenr = -1;
  54. xres = yres = 4;
  55. topleft.Set (-.5, -.5, 0);
  56. xscale = yscale = 1;
  57. material = NULL;
  58. MixMode = 0;
  59. vis_cb = NULL;
  60. surf_vertices = NULL;
  61. surf_colors = NULL;
  62. surf_texels = NULL;
  63. mesh.triangles = NULL;
  64. mesh.vertex_fog = NULL;
  65. corner[0] = corner[1] = corner[2] = corner[3] = csVector3(0,0,0);
  66. shapenr = 0;
  67. do_lighting = true;
  68. color.red = 0;
  69. color.green = 0;
  70. color.blue = 0;
  71. current_lod = 1;
  72. current_features = 0;
  73. vbuf = NULL;
  74. vbufmgr = NULL;
  75. }
  76. csSurfMeshObject::~csSurfMeshObject ()
  77. {
  78. if (vis_cb) vis_cb->DecRef ();
  79. if (vbufmgr) vbufmgr->RemoveClient (&scfiVertexBufferManagerClient);
  80. if (vbuf) vbuf->DecRef ();
  81. delete[] surf_vertices;
  82. delete[] surf_colors;
  83. delete[] surf_texels;
  84. delete[] mesh.triangles;
  85. delete[] mesh.vertex_fog;
  86. }
  87. void csSurfMeshObject::GetTransformedBoundingBox (long cameranr,
  88. long movablenr, const csReversibleTransform& trans, csBox3& cbox)
  89. {
  90. if (cur_cameranr == cameranr && cur_movablenr == movablenr)
  91. {
  92. cbox = camera_bbox;
  93. return;
  94. }
  95. cur_cameranr = cameranr;
  96. cur_movablenr = movablenr;
  97. camera_bbox.StartBoundingBox (trans * corner[0]);
  98. camera_bbox.AddBoundingVertexSmart (trans * corner[1]);
  99. camera_bbox.AddBoundingVertexSmart (trans * corner[2]);
  100. camera_bbox.AddBoundingVertexSmart (trans * corner[3]);
  101. cbox = camera_bbox;
  102. }
  103. static void Perspective (const csVector3& v, csVector2& p, float fov,
  104. float sx, float sy)
  105. {
  106. float iz = fov / v.z;
  107. p.x = v.x * iz + sx;
  108. p.y = v.y * iz + sy;
  109. }
  110. float csSurfMeshObject::GetScreenBoundingBox (long cameranr,
  111. long movablenr, float fov, float sx, float sy,
  112. const csReversibleTransform& trans, csBox2& sbox, csBox3& cbox)
  113. {
  114. csVector2 oneCorner;
  115. GetTransformedBoundingBox (cameranr, movablenr, trans, cbox);
  116. // if the entire bounding box is behind the camera, we're done
  117. if ((cbox.MinZ () < 0) && (cbox.MaxZ () < 0))
  118. {
  119. return -1;
  120. }
  121. // Transform from camera to screen space.
  122. if (cbox.MinZ () <= 0)
  123. {
  124. // Sprite is very close to camera.
  125. // Just return a maximum bounding box.
  126. sbox.Set (-10000, -10000, 10000, 10000);
  127. }
  128. else
  129. {
  130. Perspective (cbox.Max (), oneCorner, fov, sx, sy);
  131. sbox.StartBoundingBox (oneCorner);
  132. csVector3 v (cbox.MinX (), cbox.MinY (), cbox.MaxZ ());
  133. Perspective (v, oneCorner, fov, sx, sy);
  134. sbox.AddBoundingVertexSmart (oneCorner);
  135. Perspective (cbox.Min (), oneCorner, fov, sx, sy);
  136. sbox.AddBoundingVertexSmart (oneCorner);
  137. v.Set (cbox.MaxX (), cbox.MaxY (), cbox.MinZ ());
  138. Perspective (v, oneCorner, fov, sx, sy);
  139. sbox.AddBoundingVertexSmart (oneCorner);
  140. }
  141. return cbox.MaxZ ();
  142. }
  143. void csSurfMeshObject::GenerateSurface (G3DTriangleMesh& mesh)
  144. {
  145. csVector3* vertices = new csVector3[10000]; // Temporary only
  146. csVector2* uvverts = new csVector2[10000];
  147. csTriangle* triangles = new csTriangle[10000];
  148. float rx = 0, ry = 0, u, v;
  149. int x, y;
  150. int num_vertices = 0;
  151. for (y = 0 ; y <= yres ; y++)
  152. {
  153. v = float (y) / float (yres);
  154. ry = topleft.y + yscale * v;
  155. for (x = 0 ; x <= xres ; x++)
  156. {
  157. u = float (x) / float (xres);
  158. rx = topleft.x + xscale * u;
  159. vertices[num_vertices].Set (rx, ry, topleft.z);
  160. uvverts[num_vertices].Set (u, v);
  161. num_vertices++;
  162. }
  163. }
  164. // Using the last values used in loop
  165. corner[0] = topleft;
  166. corner[1] = csVector3( topleft.x, ry, topleft.z);
  167. corner[2] = csVector3( rx, ry, topleft.z);
  168. corner[3] = csVector3( rx, topleft.y, topleft.z);
  169. int num_triangles = 0;
  170. int i = 0;
  171. for (y = 0 ; y < yres ; y++)
  172. {
  173. for (x = 0 ; x < xres ; x++, i++)
  174. {
  175. triangles[num_triangles].c = i;
  176. triangles[num_triangles].b = i+1;
  177. triangles[num_triangles].a = i+xres+1;
  178. num_triangles++;
  179. triangles[num_triangles].c = i+1;
  180. triangles[num_triangles].b = i+xres+1+1;
  181. triangles[num_triangles].a = i+xres+1;
  182. num_triangles++;
  183. }
  184. i++;
  185. }
  186. // Setup the mesh and normal array.
  187. num_surf_vertices = num_vertices;
  188. surf_vertices = new csVector3[num_vertices];
  189. memcpy (surf_vertices, vertices, sizeof(csVector3)*num_vertices);
  190. surf_texels = new csVector2[num_vertices];
  191. memcpy (surf_texels, uvverts, sizeof(csVector2)*num_vertices);
  192. surf_colors = new csColor[num_vertices];
  193. for (i = 0 ; i < num_vertices ; i++)
  194. surf_colors[i].Set (1, 1, 1);
  195. mesh.vertex_fog = new G3DFogInfo[num_vertices];
  196. mesh.num_triangles = num_triangles;
  197. mesh.triangles = new csTriangle[num_triangles];
  198. memcpy (mesh.triangles, triangles, sizeof(csTriangle)*num_triangles);
  199. delete[] vertices;
  200. delete[] uvverts;
  201. delete[] triangles;
  202. }
  203. void csSurfMeshObject::RecalcObjectBBox ()
  204. {
  205. object_bbox.StartBoundingBox (corner[0]);
  206. int i;
  207. for (i = 1 ; i < 3 ; i++)
  208. object_bbox.AddBoundingVertexSmart (corner[i]);
  209. float xx = object_bbox.MaxX ()-object_bbox.MinX (); xx /= 2.;
  210. float yy = object_bbox.MaxY ()-object_bbox.MinY (); yy /= 2.;
  211. float zz = object_bbox.MaxZ ()-object_bbox.MinZ (); zz /= 2.;
  212. max_radius.Set (qsqrt (xx*xx+xx*xx), qsqrt (yy*yy+yy*yy),
  213. qsqrt (zz*zz+zz*zz));
  214. }
  215. void csSurfMeshObject::RecalcSurfaceNormal ()
  216. {
  217. csVector3 v1 = surf_vertices[1] - surf_vertices[0];
  218. csVector3 v2 = surf_vertices[xres+1] - surf_vertices[0];
  219. surface_normal = v1 % v2;
  220. surface_normal.Normalize ();
  221. }
  222. void csSurfMeshObject::SetupObject ()
  223. {
  224. if (!initialized)
  225. {
  226. initialized = true;
  227. SetupVertexBuffer ();
  228. delete[] surf_vertices;
  229. delete[] surf_colors;
  230. delete[] surf_texels;
  231. delete[] mesh.triangles;
  232. delete[] mesh.vertex_fog;
  233. surf_vertices = NULL;
  234. surf_colors = NULL;
  235. surf_texels = NULL;
  236. mesh.triangles = NULL;
  237. mesh.vertex_fog = NULL;
  238. GenerateSurface (mesh);
  239. RecalcObjectBBox ();
  240. RecalcSurfaceNormal ();
  241. mesh.morph_factor = 0;
  242. mesh.num_vertices_pool = 1;
  243. mesh.do_morph_texels = false;
  244. mesh.do_morph_colors = false;
  245. mesh.vertex_mode = G3DTriangleMesh::VM_WORLDSPACE;
  246. }
  247. }
  248. void csSurfMeshObject::SetupVertexBuffer ()
  249. {
  250. if (!vbuf)
  251. {
  252. iObjectRegistry* object_reg = ((csSurfMeshObjectFactory*)factory)
  253. ->object_reg;
  254. iGraphics3D* g3d = CS_QUERY_REGISTRY (object_reg, iGraphics3D);
  255. // @@@ priority should be a parameter.
  256. vbufmgr = g3d->GetVertexBufferManager ();
  257. g3d->DecRef ();
  258. vbuf = vbufmgr->CreateBuffer (0);
  259. vbufmgr->AddClient (&scfiVertexBufferManagerClient);
  260. mesh.buffers[0] = vbuf;
  261. }
  262. }
  263. bool csSurfMeshObject::DrawTest (iRenderView* rview, iMovable* movable)
  264. {
  265. SetupObject ();
  266. iGraphics3D* g3d = rview->GetGraphics3D ();
  267. iCamera* camera = rview->GetCamera ();
  268. // First create the transformation from object to camera space directly:
  269. // W = Mow * O - Vow;
  270. // C = Mwc * (W - Vwc)
  271. // ->
  272. // C = Mwc * (Mow * O - Vow - Vwc)
  273. // C = Mwc * Mow * O - Mwc * (Vow + Vwc)
  274. csReversibleTransform tr_o2c = camera->GetTransform ()
  275. * movable->GetFullTransform ().GetInverse ();
  276. float fov = camera->GetFOV ();
  277. float shiftx = camera->GetShiftX ();
  278. float shifty = camera->GetShiftY ();
  279. // Test visibility of entire ball by clipping bounding box against clipper.
  280. // There are three possibilities:
  281. // 1. box is not visible -> ball is not visible.
  282. // 2. box is entirely visible -> ball is visible and need not be clipped.
  283. // 3. box is partially visible -> ball is visible and needs to be clipped
  284. // if rview has do_clip_plane set to true.
  285. csBox2 sbox;
  286. csBox3 cbox;
  287. if (GetScreenBoundingBox (camera->GetCameraNumber (),
  288. movable->GetUpdateNumber (), fov, shiftx, shifty,
  289. tr_o2c, sbox, cbox) < 0)
  290. return false;
  291. int clip_portal, clip_plane, clip_z_plane;
  292. if (rview->ClipBBox (sbox, cbox, clip_portal, clip_plane,
  293. clip_z_plane) == false)
  294. return false;
  295. iClipper2D* clipper; clipper = rview->GetClipper ();
  296. g3d->SetObjectToCamera (&tr_o2c);
  297. mesh.clip_portal = clip_portal;
  298. mesh.clip_plane = clip_plane;
  299. mesh.clip_z_plane = clip_z_plane;
  300. mesh.do_mirror = camera->IsMirrored ();
  301. return true;
  302. }
  303. void csSurfMeshObject::UpdateLighting (iLight** lights, int num_lights,
  304. iMovable* movable)
  305. {
  306. SetupObject ();
  307. int i, l;
  308. csColor* colors = surf_colors;
  309. // Set all colors to ambient light (@@@ NEED TO GET AMBIENT!)
  310. for (i = 0 ; i < num_surf_vertices ; i++)
  311. colors[i] = color;
  312. if (!do_lighting) return;
  313. // @@@ it is not effiecient to do this all the time.
  314. // Do the lighting.
  315. csVector3 obj_center (0);
  316. csReversibleTransform trans = movable->GetFullTransform ();
  317. csVector3 wor_center = trans.This2Other (obj_center);
  318. csColor color;
  319. for (l = 0 ; l < num_lights ; l++)
  320. {
  321. iLight* li = lights[l];
  322. // Compute light position in object coordinates
  323. csVector3 wor_light_pos = li->GetCenter ();
  324. float wor_sq_dist = csSquaredDist::PointPoint (wor_light_pos, wor_center);
  325. if (wor_sq_dist >= li->GetSquaredRadius ()) continue;
  326. csVector3 obj_light_pos = trans.Other2This (wor_light_pos);
  327. float obj_sq_dist = csSquaredDist::PointPoint (obj_light_pos, obj_center);
  328. float in_obj_dist = qisqrt (obj_sq_dist);
  329. csVector3 obj_light_dir = (obj_light_pos - obj_center);
  330. csColor light_color = li->GetColor () * (256. / NORMAL_LIGHT_LEVEL)
  331. * li->GetBrightnessAtDistance (qsqrt (wor_sq_dist));
  332. csVector3 normal = surface_normal;
  333. float cosinus;
  334. if (obj_sq_dist < SMALL_EPSILON) cosinus = 1;
  335. else cosinus = obj_light_dir * normal;
  336. if (cosinus > 0)
  337. {
  338. color = light_color;
  339. if (obj_sq_dist >= SMALL_EPSILON) cosinus *= in_obj_dist;
  340. if (cosinus < 1) color *= cosinus;
  341. for (i = 0 ; i < num_surf_vertices ; i++)
  342. colors[i] += color;
  343. }
  344. }
  345. // Clamp all vertex colors to 2.
  346. for (i = 0 ; i < num_surf_vertices ; i++)
  347. {
  348. colors[i].ClampDown ();
  349. colors[i].Clamp (2., 2., 2.);
  350. }
  351. }
  352. bool csSurfMeshObject::Draw (iRenderView* rview, iMovable* /*movable*/,
  353. csZBufMode mode)
  354. {
  355. // @@@ TODO:
  356. // - Z fill vs Z use
  357. if (!material)
  358. {
  359. printf ("INTERNAL ERROR: surface used without material!\n");
  360. return false;
  361. }
  362. iMaterialHandle* mat = material->GetMaterialHandle ();
  363. if (!mat)
  364. {
  365. printf ("INTERNAL ERROR: surface used without valid material handle!\n");
  366. return false;
  367. }
  368. if (vis_cb) if (!vis_cb->BeforeDrawing (this, rview)) return false;
  369. iGraphics3D* g3d = rview->GetGraphics3D ();
  370. SetupVertexBuffer ();
  371. // Prepare for rendering.
  372. g3d->SetRenderState (G3DRENDERSTATE_ZBUFFERMODE, mode);
  373. material->Visit ();
  374. mesh.mat_handle = mat;
  375. mesh.use_vertex_color = true;
  376. mesh.mixmode = MixMode | CS_FX_GOURAUD;
  377. CS_ASSERT (!vbuf->IsLocked ());
  378. vbufmgr->LockBuffer (vbuf, surf_vertices, surf_texels,
  379. surf_colors, num_surf_vertices, 0);
  380. rview->CalculateFogMesh (g3d->GetObjectToCamera (), mesh);
  381. g3d->DrawTriangleMesh (mesh);
  382. vbufmgr->UnlockBuffer (vbuf);
  383. return true;
  384. }
  385. void csSurfMeshObject::GetObjectBoundingBox (csBox3& bbox, int /*type*/)
  386. {
  387. SetupObject ();
  388. bbox = object_bbox;
  389. }
  390. void csSurfMeshObject::HardTransform (const csReversibleTransform& t)
  391. {
  392. SetupObject ();
  393. int i;
  394. for (i = 0 ; i < num_surf_vertices ; i++)
  395. surf_vertices[i] = t.This2Other (surf_vertices[i]);
  396. for (i = 0; i < 4; i++ )
  397. corner[i] = t.This2Other(corner[i]);
  398. RecalcObjectBBox ();
  399. RecalcSurfaceNormal ();
  400. shapenr++;
  401. }
  402. bool csSurfMeshObject::HitBeamOutline (const csVector3& start,
  403. const csVector3& end, csVector3& isect, float* pr)
  404. {
  405. return HitBeamObject (start, end, isect, pr);
  406. }
  407. bool csSurfMeshObject::HitBeamObject(const csVector3& start,
  408. const csVector3& end, csVector3& isect, float *pr)
  409. {
  410. csSegment3 seg (start, end);
  411. if (csIntersect3::IntersectTriangle (corner[0], corner[2], corner[1], seg, isect)
  412. || csIntersect3::IntersectTriangle (corner[0], corner[3], corner[2], seg, isect))
  413. {
  414. if (pr)
  415. *pr = qsqrt (csSquaredDist::PointPoint (start, isect) /
  416. csSquaredDist::PointPoint (start, end));
  417. return true;
  418. }
  419. return false;
  420. }
  421. void csSurfMeshObject::eiVertexBufferManagerClient::ManagerClosing ()
  422. {
  423. if (scfParent->vbuf)
  424. {
  425. scfParent->vbuf->DecRef ();
  426. scfParent->vbuf = NULL;
  427. scfParent->vbufmgr = NULL;
  428. }
  429. }
  430. //----------------------------------------------------------------------
  431. SCF_IMPLEMENT_IBASE (csSurfMeshObjectFactory)
  432. SCF_IMPLEMENTS_INTERFACE (iMeshObjectFactory)
  433. SCF_IMPLEMENT_IBASE_END
  434. csSurfMeshObjectFactory::csSurfMeshObjectFactory (iBase *pParent,
  435. iObjectRegistry* object_reg)
  436. {
  437. SCF_CONSTRUCT_IBASE (pParent);
  438. csSurfMeshObjectFactory::object_reg = object_reg;
  439. logparent = NULL;
  440. }
  441. csSurfMeshObjectFactory::~csSurfMeshObjectFactory ()
  442. {
  443. }
  444. iMeshObject* csSurfMeshObjectFactory::NewInstance ()
  445. {
  446. csSurfMeshObject* cm = new csSurfMeshObject ((iMeshObjectFactory*)this);
  447. iMeshObject* im = SCF_QUERY_INTERFACE (cm, iMeshObject);
  448. im->DecRef ();
  449. return im;
  450. }
  451. //----------------------------------------------------------------------
  452. SCF_IMPLEMENT_IBASE (csSurfMeshObjectType)
  453. SCF_IMPLEMENTS_INTERFACE (iMeshObjectType)
  454. SCF_IMPLEMENTS_EMBEDDED_INTERFACE (iComponent)
  455. SCF_IMPLEMENT_IBASE_END
  456. SCF_IMPLEMENT_EMBEDDED_IBASE (csSurfMeshObjectType::eiComponent)
  457. SCF_IMPLEMENTS_INTERFACE (iComponent)
  458. SCF_IMPLEMENT_EMBEDDED_IBASE_END
  459. SCF_IMPLEMENT_FACTORY (csSurfMeshObjectType)
  460. SCF_EXPORT_CLASS_TABLE (surf)
  461. SCF_EXPORT_CLASS (csSurfMeshObjectType, "crystalspace.mesh.object.surface",
  462. "Crystal Space Surface Mesh Type")
  463. SCF_EXPORT_CLASS_TABLE_END
  464. csSurfMeshObjectType::csSurfMeshObjectType (iBase* pParent)
  465. {
  466. SCF_CONSTRUCT_IBASE (pParent);
  467. SCF_CONSTRUCT_EMBEDDED_IBASE(scfiComponent);
  468. }
  469. csSurfMeshObjectType::~csSurfMeshObjectType ()
  470. {
  471. }
  472. iMeshObjectFactory* csSurfMeshObjectType::NewFactory ()
  473. {
  474. csSurfMeshObjectFactory* cm = new csSurfMeshObjectFactory (this,
  475. object_reg);
  476. iMeshObjectFactory* ifact = SCF_QUERY_INTERFACE (cm, iMeshObjectFactory);
  477. ifact->DecRef ();
  478. return ifact;
  479. }