void SpacePlane::anim(double dt){ WarSpace *ws = *w; if(!ws){ st::anim(dt); return; } if(bbody && !warping){ const btTransform &tra = bbody->getCenterOfMassTransform(); pos = btvc(tra.getOrigin()); rot = btqc(tra.getRotation()); velo = btvc(bbody->getLinearVelocity()); } /* forget about beaten enemy */ if(enemy && (enemy->getHealth() <= 0. || enemy->w != w)) enemy = NULL; Mat4d mat; transform(mat); if(0 < health){ Entity *collideignore = NULL; if(ai){ if(ai->control(this, dt)){ ai->unlink(this); ai = NULL; } if(!w) return; } else if(task == sship_undock){ if(undocktime < 0.){ inputs.press &= ~PL_W; task = sship_idle; } else{ inputs.press |= PL_W; undocktime -= dt; } } else if(controller){ } else if(!enemy && task == sship_parade){ Entity *pm = mother ? mother->e : NULL; if(mother){ if(paradec == -1) paradec = mother->enumParadeC(mother->Frigate); Vec3d target, target0(1.5, -1., -1.); Quatd q2, q1; target0[0] += paradec % 10 * 300.; target0[2] += paradec / 10 * -300.; target = pm->rot.trans(target0); target += pm->pos; Vec3d dr = this->pos - target; if(dr.slen() < .10 * .10){ q1 = pm->rot; inputs.press &= ~PL_W; // parking = 1; this->velo += dr * (-dt * .5); q2 = Quatd::slerp(this->rot, q1, 1. - exp(-dt)); this->rot = q2; } else{ // p->throttle = dr.slen() / 5. + .01; steerArrival(dt, target, pm->velo, 1. / 10., 1.); } } else task = sship_idle; } else if(task == sship_idle){ if(race != 0 /*RandomSequence((unsigned long)this + (unsigned long)(w->war_time() / .0001)).nextd() < .0001*/){ command(&DockCommand()); } inputs.press = 0; } else{ inputs.press = 0; } } else{ this->w = NULL; return; } st::anim(dt); // inputs.press is filtered in st::anim, so we put tefpol updates after it. for(int i = 0; i < engines.size(); i++) if(pf[i]){ pf[i]->move(mat.vp3(engines[i]), avec3_000, cs_orangeburn.t, !(inputs.press & PL_W)); } // engineHeat = approach(engineHeat, direction & PL_W ? 1.f : 0.f, dt, 0.); // Exponential approach is more realistic (but costs more CPU cycles) engineHeat = direction & PL_W ? engineHeat + (1. - engineHeat) * (1. - exp(-dt)) : engineHeat * exp(-dt); #if 0 if(p->pf){ int i; avec3_t pos, pos0[numof(p->pf)] = { {.0, -.003, .045}, }; for(i = 0; i < numof(p->pf); i++){ MAT4VP3(pos, mat, pos0[i]); MoveTefpol3D(p->pf[i], pos, avec3_000, cs_orangeburn.t, 0); } } #endif }
size_t BVH4MB::rotate(Base* nodeID, size_t depth) { /*! nothing to rotate if we reached a leaf node. */ if (nodeID->isLeaf()) return 0; Node* parent = nodeID->node(); /*! rotate all children first */ ssei cdepth; for (size_t c=0; c<4; c++) cdepth[c] = (int)rotate(parent->child[c],depth+1); /* compute current area of all children */ ssef sizeX = parent->upper_x-parent->lower_x; ssef sizeY = parent->upper_y-parent->lower_y; ssef sizeZ = parent->upper_z-parent->lower_z; ssef childArea = sizeX*(sizeY + sizeZ) + sizeY*sizeZ; /*! transpose node bounds */ ssef plower0,plower1,plower2,plower3; transpose(parent->lower_x,parent->lower_y,parent->lower_z,ssef(zero),plower0,plower1,plower2,plower3); ssef pupper0,pupper1,pupper2,pupper3; transpose(parent->upper_x,parent->upper_y,parent->upper_z,ssef(zero),pupper0,pupper1,pupper2,pupper3); BBox<ssef> other0(plower0,pupper0), other1(plower1,pupper1), other2(plower2,pupper2), other3(plower3,pupper3); /*! Find best rotation. We pick a target child of a first child, and swap this with an other child. We perform the best such swap. */ float bestCost = pos_inf; int bestChild = -1, bestTarget = -1, bestOther = -1; for (size_t c=0; c<4; c++) { /*! ignore leaf nodes as we cannot descent into */ if (parent->child[c]->isLeaf()) continue; Node* child = parent->child[c]->node(); /*! transpose child bounds */ ssef clower0,clower1,clower2,clower3; transpose(child->lower_x,child->lower_y,child->lower_z,ssef(zero),clower0,clower1,clower2,clower3); ssef cupper0,cupper1,cupper2,cupper3; transpose(child->upper_x,child->upper_y,child->upper_z,ssef(zero),cupper0,cupper1,cupper2,cupper3); BBox<ssef> target0(clower0,cupper0), target1(clower1,cupper1), target2(clower2,cupper2), target3(clower3,cupper3); /*! put other0 at each target position */ float cost00 = halfArea3f(merge(other0 ,target1,target2,target3)); float cost01 = halfArea3f(merge(target0,other0 ,target2,target3)); float cost02 = halfArea3f(merge(target0,target1,other0 ,target3)); float cost03 = halfArea3f(merge(target0,target1,target2,other0 )); ssef cost0 = ssef(cost00,cost01,cost02,cost03); ssef min0 = vreduce_min(cost0); int pos0 = (int)__bsf(movemask(min0 == cost0)); /*! put other1 at each target position */ float cost10 = halfArea3f(merge(other1 ,target1,target2,target3)); float cost11 = halfArea3f(merge(target0,other1 ,target2,target3)); float cost12 = halfArea3f(merge(target0,target1,other1 ,target3)); float cost13 = halfArea3f(merge(target0,target1,target2,other1 )); ssef cost1 = ssef(cost10,cost11,cost12,cost13); ssef min1 = vreduce_min(cost1); int pos1 = (int)__bsf(movemask(min1 == cost1)); /*! put other2 at each target position */ float cost20 = halfArea3f(merge(other2 ,target1,target2,target3)); float cost21 = halfArea3f(merge(target0,other2 ,target2,target3)); float cost22 = halfArea3f(merge(target0,target1,other2 ,target3)); float cost23 = halfArea3f(merge(target0,target1,target2,other2 )); ssef cost2 = ssef(cost20,cost21,cost22,cost23); ssef min2 = vreduce_min(cost2); int pos2 = (int)__bsf(movemask(min2 == cost2)); /*! put other3 at each target position */ float cost30 = halfArea3f(merge(other3 ,target1,target2,target3)); float cost31 = halfArea3f(merge(target0,other3 ,target2,target3)); float cost32 = halfArea3f(merge(target0,target1,other3 ,target3)); float cost33 = halfArea3f(merge(target0,target1,target2,other3 )); ssef cost3 = ssef(cost30,cost31,cost32,cost33); ssef min3 = vreduce_min(cost3); int pos3 = (int)__bsf(movemask(min3 == cost3)); /*! find best other child */ ssef otherCost = ssef(extract<0>(min0),extract<0>(min1),extract<0>(min2),extract<0>(min3)); int pos[4] = { pos0,pos1,pos2,pos3 }; sseb valid = ssei(int(depth+1))+cdepth <= ssei(maxDepth); // only select swaps that fulfill depth constraints if (none(valid)) continue; size_t n = select_min(valid,otherCost); float cost = otherCost[n]-childArea[c]; //< increasing the original child bound is bad, decreasing good /*! accept a swap when it reduces cost and is not swapping a node with itself */ if (cost < bestCost && n != c) { bestCost = cost; bestChild = (int)c; bestOther = (int)n; bestTarget = pos[n]; } } /*! if we did not find a swap that improves the SAH then do nothing */ if (bestCost >= 0) return 1+reduce_max(cdepth); /*! perform the best found tree rotation */ Node* child = parent->child[bestChild]->node(); swap(parent,bestOther,child,bestTarget); parent->lower_x[bestChild] = reduce_min(child->lower_x); parent->lower_y[bestChild] = reduce_min(child->lower_y); parent->lower_z[bestChild] = reduce_min(child->lower_z); parent->upper_x[bestChild] = reduce_max(child->upper_x); parent->upper_y[bestChild] = reduce_max(child->upper_y); parent->upper_z[bestChild] = reduce_max(child->upper_z); parent->lower_dx[bestChild] = reduce_min(child->lower_dx); parent->lower_dy[bestChild] = reduce_min(child->lower_dy); parent->lower_dz[bestChild] = reduce_min(child->lower_dz); parent->upper_dx[bestChild] = reduce_max(child->upper_dx); parent->upper_dy[bestChild] = reduce_max(child->upper_dy); parent->upper_dz[bestChild] = reduce_max(child->upper_dz); /*! This returned depth is conservative as the child that was * pulled up in the tree could have been on the critical path. */ cdepth[bestOther]++; // bestOther was pushed down one level return 1+reduce_max(cdepth); }