PageRenderTime 50ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

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

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