const csBox3& csMeshWrapper::GetWorldBoundingBox () { if (wor_bbox_movablenr != movable.GetUpdateNumber ()) { wor_bbox_movablenr = movable.GetUpdateNumber (); if (movable.IsFullTransformIdentity ()) wor_bbox = GetObjectModel ()->GetObjectBoundingBox (); else { const csBox3& obj_bbox = GetObjectModel ()->GetObjectBoundingBox (); // @@@ Maybe it would be better to really calculate the bounding box // here instead of just transforming the object space bounding box? csReversibleTransform mt = movable.GetFullTransform (); wor_bbox.StartBoundingBox (mt.This2Other (obj_bbox.GetCorner (0))); wor_bbox.AddBoundingVertexSmart (mt.This2Other (obj_bbox.GetCorner (1))); wor_bbox.AddBoundingVertexSmart (mt.This2Other (obj_bbox.GetCorner (2))); wor_bbox.AddBoundingVertexSmart (mt.This2Other (obj_bbox.GetCorner (3))); wor_bbox.AddBoundingVertexSmart (mt.This2Other (obj_bbox.GetCorner (4))); wor_bbox.AddBoundingVertexSmart (mt.This2Other (obj_bbox.GetCorner (5))); wor_bbox.AddBoundingVertexSmart (mt.This2Other (obj_bbox.GetCorner (6))); wor_bbox.AddBoundingVertexSmart (mt.This2Other (obj_bbox.GetCorner (7))); } } return wor_bbox; }
csHitBeamResult csMeshWrapper::HitBeamBBox ( const csVector3 &start, const csVector3 &end) { csHitBeamResult rc; const csBox3& b = GetObjectModel ()->GetObjectBoundingBox (); csSegment3 seg (start, end); rc.facehit = csIntersect3::BoxSegment (b, seg, rc.isect, &rc.r); return rc; }
float csMeshWrapper::GetSquaredDistance (const csVector3& pos) { // calculate distance from pos to mesh const csBox3& obox = GetObjectModel ()->GetObjectBoundingBox (); csVector3 obj_center = (obox.Min () + obox.Max ()) / 2; csVector3 wor_center; if (movable.IsFullTransformIdentity ()) wor_center = obj_center; else wor_center = movable.GetFullTransform ().This2Other (obj_center); float wor_sq_dist = csSquaredDist::PointPoint (pos, wor_center); return wor_sq_dist; }
csBox3 csMeshWrapper::GetTransformedBoundingBox ( const csReversibleTransform &trans) { csBox3 cbox; const csBox3& box = GetObjectModel ()->GetObjectBoundingBox (); cbox.StartBoundingBox (trans * box.GetCorner (0)); cbox.AddBoundingVertexSmart (trans * box.GetCorner (1)); cbox.AddBoundingVertexSmart (trans * box.GetCorner (2)); cbox.AddBoundingVertexSmart (trans * box.GetCorner (3)); cbox.AddBoundingVertexSmart (trans * box.GetCorner (4)); cbox.AddBoundingVertexSmart (trans * box.GetCorner (5)); cbox.AddBoundingVertexSmart (trans * box.GetCorner (6)); cbox.AddBoundingVertexSmart (trans * box.GetCorner (7)); return cbox; }
void csMeshWrapper::PlaceMesh () { iSectorList *movable_sectors = movable.GetSectors (); if (movable_sectors->GetCount () == 0) return ; // Do nothing csSphere sphere; float radius; GetObjectModel ()->GetRadius (radius, sphere.GetCenter ()); iSector *sector = movable_sectors->Get (0); movable.SetSector (sector); // Make sure all other sectors are removed // Transform the sphere from object to world space. sphere.SetRadius (radius); if (!movable.IsFullTransformIdentity ()) sphere = movable.GetFullTransform ().This2Other (sphere); radius = sphere.GetRadius (); //float max_sq_radius = radius * radius; csRef<iMeshWrapperIterator> it = engine->GetNearbyMeshes (sector, sphere.GetCenter (), radius, true); int j; while (it->HasNext ()) { iMeshWrapper* mesh = it->Next (); iPortalContainer* portals = mesh->GetPortalContainer (); if (!portals) continue; // No portals. int pc_count = portals->GetPortalCount (); for (j = 0 ; j < pc_count ; j++) { iPortal *portal = portals->GetPortal (j); iSector *dest_sector = portal->GetSector (); if (movable_sectors->Find (dest_sector) == -1) { const csSphere& portal_sphere = portal->GetWorldSphere (); if (portal_sphere.TestIntersect (sphere)) movable_sectors->Add (dest_sector); } } } }
void csMeshWrapper::GetFullBBox (csBox3& box) { box = GetObjectModel ()->GetObjectBoundingBox (); csMovable* mov = &movable; while (mov) { if (!mov->IsTransformIdentity ()) { const csReversibleTransform& trans = mov->GetTransform (); csBox3 b (trans.This2Other (box.GetCorner (0))); b.AddBoundingVertexSmart (trans.This2Other (box.GetCorner (1))); b.AddBoundingVertexSmart (trans.This2Other (box.GetCorner (2))); b.AddBoundingVertexSmart (trans.This2Other (box.GetCorner (3))); b.AddBoundingVertexSmart (trans.This2Other (box.GetCorner (4))); b.AddBoundingVertexSmart (trans.This2Other (box.GetCorner (5))); b.AddBoundingVertexSmart (trans.This2Other (box.GetCorner (6))); b.AddBoundingVertexSmart (trans.This2Other (box.GetCorner (7))); box = b; } mov = ((csMovable*)mov)->GetParent (); } }
void DrawOOBM() { uint tt = timeGetTime(); renderer->BeginBatchDrawing(); SetTransformMatrix(&vpmatrix); mshbatch->begin(); for(int t = 0; t < strMaterials.len; t++) { int txset = 0; for(int a = 0; a < 2; a++) { int afset = 0; GrowList<GameObject*> *l = 0; // = &((oobm[a])[t]); for(int i = 0; i < oobm[a].len; i++) if(oobm[a].getpnt(i)->tid == t) {l = oobm[a].getpnt(i)->objs; break;} if(!l) continue; for(int i = 0; i < l->len; i++) { GameObject *o = l->get(i); int dif = -1; if((o->flags & FGO_SELECTED) || (currentSelection == o)) { if((o->flags & FGO_SELECTED) && (currentSelection == o)) dif = 0xFFFF00FF; else dif = (currentSelection==o)?0xFFFF0000:0xFF0000FF; } //Model *md = o->objdef->subtypes[o->subtype].appear[o->appearance].def; Model *md = GetObjectModel(o); if(showrepresentations && o->objdef->representation) md = o->objdef->representation; md->prepare(); md->mesh->prepare(); Mesh *msh = md->mesh; // If md != md->mesh, this means that md is an Anim! SetMatrices(o->scale, -o->orientation, o->position); Matrix mWorldCopy = mWorld; uint tm = (int)(current_time*1000.0f) - o->animtimeref; // If the current task has SYNCH_ANIMATION_TO_FRACTION, use it. if(md != md->mesh) if(o->ordercfg.order.len) { STask *st = &o->ordercfg.order.first->value.task.first->value; if(st->type->satf) { SequenceEnv env; env.self = o; tm = st->type->satf->get(&env) * ((Anim*)md)->dur; tm = st->lastsatf + (tm - st->lastsatf) * elapsed_time * 0.5f; if(tm >= ((Anim*)md)->dur) tm = ((Anim*)md)->dur - 1; st->lastsatf = tm; } } if(o->animlooping) if(md != md->mesh) tm %= ((Anim*)md)->dur; for(int g = 0; g < msh->ngrp; g++) if((msh->lstmatflags[g] == a) && (msh->lstmattid[g] == t)) { if(!txset) {txset = 1; SetTexture(0, msh->lstmattex[g]);} if(!afset) {afset = 1; if(a) renderer->EnableAlphaTest(); else renderer->DisableAlphaTest();} (animsEnabled?md:md->mesh)->drawInBatch(mshbatch, g, o->color, dif, tm); } for(int j = 0; j < msh->nAttachPnts; j++) if(msh->attachPnts[j].model) if(md->isAttachPointOn(j, tm)) { Model *apmd = msh->attachPnts[j].model; Mesh *apms = apmd->mesh; for(int g = 0; g < apms->ngrp; g++) if((apms->lstmatflags[g] == a) && (apms->lstmattid[g] == t)) { if(!txset) {txset = 1; SetTexture(0, apms->lstmattex[g]);} if(!afset) {afset = 1; if(a) renderer->EnableAlphaTest(); else renderer->DisableAlphaTest();} uint aptm = current_time * 1000; if(apmd != apmd->mesh) aptm %= ((Anim*)apmd)->dur; Vector3 p, s; md->getAttachPointPos(&s, j, tm); TransformVector3(&p, &s, &mWorldCopy); SetMatrices(Vector3(1,1,1), Vector3(0,0,0), p); (animsEnabled?apmd:apms)->drawInBatch(mshbatch, g, o->color, dif, aptm); } } } l->clear(); mshbatch->flush(); } mshbatch->flush(); } mshbatch->end(); }
void DrawObj(GameObject *o) { float pntz; if((o->renderable && o->objdef->subtypes[o->subtype].appear[o->appearance].def) || (showrepresentations && o->objdef->representation)) { if(IsPointOnScreen(o->position, &pntz)) { //Model *md = o->objdef->subtypes[o->subtype].appear[o->appearance].def; Model *md = GetObjectModel(o); if(showrepresentations && o->objdef->representation) md = o->objdef->representation; md->prepare(); md->mesh->prepare(); Mesh *msh = md->mesh; objsdrawn++; SetMatrices(o->scale, -o->orientation, o->position); Vector3 sphPos = o->position; sphPos.y += msh->sphere[1] * o->scale.y; if((newSelZ == -1) || (pntz < newSelZ)) if(SphereIntersectsRay(&sphPos, msh->sphere[3]*o->scale.y/2.0f, &raystart, &raydir)) {newSelection = o; newSelZ = pntz;} if(multiSel) { Vector3 tdp; TransformCoord3(&tdp, &nullvector, &matrix); float ba = (float)((mselx<mouseX)?mselx:mouseX) * 2.0f / scrw - 1; float bb = (float)((msely<mouseY)?msely:mouseY) * 2.0f / scrh - 1; float bc = (float)((mselx>mouseX)?mselx:mouseX) * 2.0f / scrw - 1; float bd = (float)((msely>mouseY)?msely:mouseY) * 2.0f / scrh - 1; if((tdp.x >= ba) && (tdp.x <= bc) && (-tdp.y >= bb) && (-tdp.y <= bd)) msellist.add(o); } if(!meshbatching) { if((o->flags & FGO_SELECTED) || (currentSelection == o)) { renderer->EnableColorBlend(); if((o->flags & FGO_SELECTED) && (currentSelection == o)) renderer->SetBlendColor(0xFFFF00FF); else renderer->SetBlendColor((currentSelection==o)?0xFFFF0000:0xFF0000FF); } SetTransformMatrix(&matrix); msh->draw(o->color); if((o->flags & FGO_SELECTED) || (currentSelection == o)) renderer->DisableColorBlend(); } else { auto f = [o](Mesh *msh) { msh->prepare(); for(int i = 0; i < msh->ngrp; i++) { OOBMTex *ot; int f = msh->lstmatflags[i]&1; int t = msh->lstmattid[i]; for(int j = 0; j < oobm[f].len; j++) { ot = oobm[f].getpnt(j); if(ot->tid == t) {ot->objs->add(o); goto nextgrp;} } ot = oobm[f].addp(); ot->tid = t; ot->objs = new GrowList<GameObject*>; ot->objs->add(o); nextgrp: ; } }; f(msh); for(int i = 0; i < msh->nAttachPnts; i++) if(msh->attachPnts[i].model) f(msh->attachPnts[i].model->mesh); } } } for(DynListEntry<GameObject> *e = o->children.first; e; e = e->next) DrawObj(&e->value); }