const CBoundingBoxAligned CModel::GetObjectSelectionBoundsRec() { CBoundingBoxAligned objBounds = GetObjectBounds(); // updates the (children-not-included) object-space bounds if necessary // now extend these bounds to include the props' selection bounds (if any) for (size_t i = 0; i < m_Props.size(); ++i) { const Prop& prop = m_Props[i]; if (prop.m_Hidden) continue; // prop is hidden from rendering, so it also shouldn't be used for selection CBoundingBoxAligned propSelectionBounds = prop.m_Model->GetObjectSelectionBoundsRec(); if (propSelectionBounds.IsEmpty()) continue; // submodel does not wish to participate in selection box, exclude it // We have the prop's bounds in its own object-space; now we need to transform them so they can be properly added // to the bounds in our object-space. For that, we need the transform of the prop attachment point. // // We have the prop point information; however, it's not trivial to compute its exact location in our object-space // since it may or may not be attached to a bone (see SPropPoint), which in turn may or may not be in the middle of // an animation. The bone matrices might be of interest, but they're really only meant to be used for the animation // system and are quite opaque to use from the outside (see @ref ValidatePosition). // // However, a nice side effect of ValidatePosition is that it also computes the absolute world-space transform of // our props and sets it on their respective models. In particular, @ref ValidatePosition will compute the prop's // world-space transform as either // // T' = T x B x O // or // T' = T x O // // where T' is the prop's world-space transform, T is our world-space transform, O is the prop's local // offset/rotation matrix, and B is an optional transformation matrix of the bone the prop is attached to // (taking into account animation and everything). // // From this, it is clear that either O or B x O is the object-space transformation matrix of the prop. So, // all we need to do is apply our own inverse world-transform T^(-1) to T' to get our desired result. Luckily, // this is precomputed upon setting the transform matrix (see @ref SetTransform), so it is free to fetch. CMatrix3D propObjectTransform = prop.m_Model->GetTransform(); // T' propObjectTransform.Concatenate(GetInvTransform()); // T^(-1) x T' // Transform the prop's bounds into our object coordinate space CBoundingBoxAligned transformedPropSelectionBounds; propSelectionBounds.Transform(propObjectTransform, transformedPropSelectionBounds); objBounds += transformedPropSelectionBounds; } return objBounds; }
CodeGenFunction::EquivSet CodeGenFunction::EmitEquivalenceSet(const EquivalenceSet *S) { auto Result = EquivSets.find(S); if(Result != EquivSets.end()) return Result->second; // Find the bounds of the set int64_t LowestBound = 0; int64_t HighestBound = 0; for(auto I : S->getObjects()) { auto Bounds = GetObjectBounds(I.Var, I.E); LowestBound = std::min(Bounds.first, LowestBound); HighestBound = std::max(Bounds.second, HighestBound); LocalVariablesInEquivSets.insert(std::make_pair(I.Var, Bounds.first)); } EquivSet Set; // FIXME: more accurate alignment? Set.Ptr= Builder.Insert(new llvm::AllocaInst(CGM.Int8Ty, llvm::ConstantInt::get(CGM.SizeTy, HighestBound - LowestBound), CGM.getDataLayout().getTypeStoreSize(CGM.DoubleTy)), "equivalence-set"); Set.LowestBound = LowestBound; EquivSets.insert(std::make_pair(S, Set)); return Set; }