void Transformable::moveBy(const Vector3d& vector, bool global) { Vector3d offset; if (global) { offset = Matrix3d(globalTransform().inverted() * localTransform()) * vector; } else { offset = Matrix3d(localTransform()) * vector; } setPosition(position() + offset); }
/* * @brief The affine transformation for this node, relative to the game's world. */ mat33 Node::absoluteTransform() const { if(_absoluteTransformDirty) { if(_parent != nullptr) { _absoluteTransform = _parent->absoluteTransform() * localTransform(); } else { _absoluteTransform = localTransform(); } _absoluteTransformDirty = false; } return _absoluteTransform; }
void MergeBounds(Ogre::SceneNode* node, Ogre::SceneNode* rootNode, const Ogre::Matrix4& parentTransform, Ogre::AxisAlignedBox& aabb) { // Get this nodes current transform Ogre::Matrix4 currentTransform = parentTransform; if (node != rootNode) { Ogre::Matrix4 localTransform(node->getOrientation()); localTransform.setTrans(node->getPosition()); currentTransform = currentTransform * localTransform; } // Merge this nodes objects Ogre::SceneNode::ObjectIterator object = node->getAttachedObjectIterator(); while (object.hasMoreElements()) { Ogre::AxisAlignedBox localAABB = object.getNext()->getBoundingBox(); localAABB.transform(currentTransform); aabb.merge(localAABB); } // Iterate through all children and call this function on them Ogre::SceneNode::ChildNodeIterator child = node->getChildIterator(); while (child.hasMoreElements()) { MergeBounds(static_cast<Ogre::SceneNode*>(child.getNext()), rootNode, currentTransform, aabb); } }
Matrix4d Transformable::globalTransform() const { Matrix4d parentTransform; if (Transformable* p = dynamic_cast<Transformable*>(parent())) { parentTransform = p->globalTransform(); } return parentTransform * localTransform(); }
void RenderForeignObject::computeAbsoluteRepaintRect(IntRect& r, bool f) { AffineTransform transform = translationForAttributes() * localTransform(); r = transform.mapRect(r); RenderBlock::computeAbsoluteRepaintRect(r, f); }
void RenderForeignObject::paint(PaintInfo& paintInfo, int parentX, int parentY) { if (paintInfo.context->paintingDisabled()) return; paintInfo.context->save(); paintInfo.context->concatCTM(AffineTransform().translate(parentX, parentY)); paintInfo.context->concatCTM(localTransform()); paintInfo.context->concatCTM(translationForAttributes()); paintInfo.context->clip(getClipRect(parentX, parentY)); float opacity = style()->opacity(); if (opacity < 1.0f) // FIXME: Possible optimization by clipping to bbox here, once relativeBBox is implemented & clip, mask and filter support added. paintInfo.context->beginTransparencyLayer(opacity); PaintInfo pi(paintInfo); pi.rect = absoluteTransform().inverse().mapRect(paintInfo.rect); RenderBlock::paint(pi, 0, 0); if (opacity < 1.0f) paintInfo.context->endTransparencyLayer(); paintInfo.context->restore(); }
void RenderPath::paint(PaintInfo& paintInfo, int, int) { if (paintInfo.context->paintingDisabled() || style()->visibility() == HIDDEN || m_path.isEmpty()) return; paintInfo.context->save(); paintInfo.context->concatCTM(localTransform()); SVGResourceFilter* filter = 0; FloatRect boundingBox = relativeBBox(true); if (paintInfo.phase == PaintPhaseForeground) { PaintInfo savedInfo(paintInfo); prepareToRenderSVGContent(this, paintInfo, boundingBox, filter); if (style()->svgStyle()->shapeRendering() == SR_CRISPEDGES) paintInfo.context->setShouldAntialias(false); fillAndStrokePath(m_path, paintInfo.context, style(), this); if (static_cast<SVGStyledElement*>(element())->supportsMarkers()) m_markerBounds = drawMarkersIfNeeded(paintInfo.context, paintInfo.rect, m_path); finishRenderSVGContent(this, paintInfo, boundingBox, filter, savedInfo.context); } if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth()) paintOutline(paintInfo.context, static_cast<int>(boundingBox.x()), static_cast<int>(boundingBox.y()), static_cast<int>(boundingBox.width()), static_cast<int>(boundingBox.height()), style()); paintInfo.context->restore(); }
void RenderSVGImage::paint(PaintInfo& paintInfo, int, int) { if (paintInfo.context->paintingDisabled() || style()->visibility() == HIDDEN) return; paintInfo.context->save(); paintInfo.context->concatCTM(localTransform()); if (paintInfo.phase == PaintPhaseForeground) { SVGResourceFilter* filter = 0; PaintInfo savedInfo(paintInfo); prepareToRenderSVGContent(this, paintInfo, m_localBounds, filter); FloatRect destRect = m_localBounds; FloatRect srcRect(0, 0, image()->width(), image()->height()); SVGImageElement* imageElt = static_cast<SVGImageElement*>(node()); if (imageElt->preserveAspectRatio()->align() != SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_NONE) adjustRectsForAspectRatio(destRect, srcRect, imageElt->preserveAspectRatio()); paintInfo.context->drawImage(image(), destRect, srcRect); finishRenderSVGContent(this, paintInfo, m_localBounds, filter, savedInfo.context); } paintInfo.context->restore(); }
void RenderForeignObject::computeRectForRepaint(RenderBox* repaintContainer, IntRect& rect, bool fixed) { TransformationMatrix transform = translationForAttributes() * localTransform(); rect = transform.mapRect(rect); RenderBlock::computeRectForRepaint(repaintContainer, rect, fixed); }
void DecalObject::applyTransform() { TerrainChunk::PolishView& vx = chunk(); updateTransform(); Tempest::Matrix4x4 mat = localTransform(vx); MVertex *v = &vx.geometry.vertex[glocation]; float x, y, z, w = 1, tu, tv; for( size_t i=0; i<model->vertex.size(); ++i, ++v ){ const MVertex & s = model->vertex[i]; *v = s; mat.project( s.x, s.y, s.z - vx.zView/sizeZ(), 1, x, y, z, w ); v->x = x; v->y = y; v->z = z; float tz = t->heightAt(x+vx.posX, y+vx.posY); if( z < tz ){//s.z - vx.zView/sizeZ() <=0 ){ //z = tz; v->nx = 0; v->ny = 0; v->nz = 1; v->bx = 1; v->by = 0; v->bz = 0; } t->mkTexCoord(tu, tv, x+vx.posX, y+vx.posY); v->u = tu;//(x+vx.posX)*0.01; v->v = tv;//(y+vx.posY)*0.01; mat.project( v->nx, v->ny, v->nz, 0, x, y, z, w ); v->nx = x; v->ny = y; v->nz = z; mat.project( v->bx, v->by, v->bz, 0, x, y, z, w ); v->bx = x; v->by = y; v->bz = z; } uint16_t * id = &vx.geometry.index[ ilocation ]; for( size_t i=0; i<model->index.size(); ++i, ++id ){ *id = glocation+model->index[i]; } needToUpdate = false; }
bool RenderSVGForeignObject::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction) { FloatPoint localPoint = localTransform().inverse().mapPoint(pointInParent); // Early exit if local point is not contained in clipped viewport area if (SVGRenderSupport::isOverflowHidden(this) && !m_viewport.contains(localPoint)) return false; return RenderBlock::nodeAtPoint(request, result, roundedLayoutPoint(localPoint), LayoutPoint(), hitTestAction); }
void Transformable::joinParent() { if (isGenerated()) return; Matrix4d matrix; if (Transformable* p = dynamic_cast<Transformable*>(parent())) { matrix = p->globalTransform().inverted(); } setMatrix(matrix * localTransform()); }
bool RenderSVGForeignObject::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction) { // Embedded content is drawn in the foreground phase. if (hitTestAction != HitTestForeground) return false; FloatPoint localPoint = localTransform().inverse().mapPoint(pointInParent); // Early exit if local point is not contained in clipped viewport area if (SVGRenderSupport::isOverflowHidden(this) && !m_viewport.contains(localPoint)) return false; // FOs establish a stacking context, so we need to hit-test all layers. HitTestLocation hitTestLocation(roundedLayoutPoint(localPoint)); return RenderBlock::nodeAtPoint(request, result, hitTestLocation, LayoutPoint(), HitTestForeground) || RenderBlock::nodeAtPoint(request, result, hitTestLocation, LayoutPoint(), HitTestFloat) || RenderBlock::nodeAtPoint(request, result, hitTestLocation, LayoutPoint(), HitTestChildBlockBackgrounds); }
void RenderSVGForeignObject::paint(PaintInfo& paintInfo, const LayoutPoint&) { if (paintInfo.context().paintingDisabled()) return; if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection) return; PaintInfo childPaintInfo(paintInfo); GraphicsContextStateSaver stateSaver(childPaintInfo.context()); childPaintInfo.applyTransform(localTransform()); if (SVGRenderSupport::isOverflowHidden(*this)) childPaintInfo.context().clip(m_viewport); SVGRenderingContext renderingContext; if (paintInfo.phase == PaintPhaseForeground) { renderingContext.prepareToRenderSVGContent(*this, childPaintInfo); if (!renderingContext.isRenderingPrepared()) return; } LayoutPoint childPoint = IntPoint(); if (paintInfo.phase == PaintPhaseSelection) { RenderBlock::paint(childPaintInfo, childPoint); return; } // Paint all phases of FO elements atomically, as though the FO element established its // own stacking context. childPaintInfo.phase = PaintPhaseBlockBackground; RenderBlock::paint(childPaintInfo, childPoint); childPaintInfo.phase = PaintPhaseChildBlockBackgrounds; RenderBlock::paint(childPaintInfo, childPoint); childPaintInfo.phase = PaintPhaseFloat; RenderBlock::paint(childPaintInfo, childPoint); childPaintInfo.phase = PaintPhaseForeground; RenderBlock::paint(childPaintInfo, childPoint); childPaintInfo.phase = PaintPhaseOutline; RenderBlock::paint(childPaintInfo, childPoint); }
void RenderSVGForeignObject::paint(PaintInfo& paintInfo, const LayoutPoint&) { if (paintInfo.context->paintingDisabled()) return; PaintInfo childPaintInfo(paintInfo); GraphicsContextStateSaver stateSaver(*childPaintInfo.context); childPaintInfo.applyTransform(localTransform()); if (SVGRenderSupport::isOverflowHidden(this)) childPaintInfo.context->clip(m_viewport); float opacity = style()->opacity(); if (opacity < 1.0f) childPaintInfo.context->beginTransparencyLayer(opacity); RenderBlock::paint(childPaintInfo, IntPoint()); if (opacity < 1.0f) childPaintInfo.context->endTransparencyLayer(); }
void SmallGraphicsObject::applyTransform() { TerrainChunk::PolishView& vx = chunk(); updateTransform(); Tempest::Matrix4x4 mat = localTransform(vx); MVertex *v = &vx.geometry.vertex[glocation]; float x, y, z, w = 1; for( size_t i=0; i<model->vertex.size(); ++i, ++v ){ const MVertex & s = model->vertex[i]; *v = s; mat.project( s.x, s.y, s.z - vx.zView/sizeZ(), 1, x, y, z, w ); v->x = x; v->y = y; v->z = z; mat.project( s.nx, s.ny, s.nz, 0, x, y, z, w ); v->nx = x; v->ny = y; v->nz = z; mat.project( s.bx, s.by, s.bz, 0, x, y, z, w ); v->bx = x; v->by = y; v->bz = z; } uint16_t * id = &vx.geometry.index[ ilocation ]; for( size_t i=0; i<model->index.size(); ++i, ++id ){ *id = glocation+model->index[i]; } needToUpdate = false; }
void RenderSVGForeignObject::paint(PaintInfo& paintInfo, const LayoutPoint&) { if (paintInfo.context->paintingDisabled() || (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection)) return; PaintInfo childPaintInfo(paintInfo); GraphicsContextStateSaver stateSaver(*childPaintInfo.context); childPaintInfo.applyTransform(localTransform()); if (SVGRenderSupport::isOverflowHidden(this)) childPaintInfo.context->clip(m_viewport); SVGRenderingContext renderingContext; bool continueRendering = true; if (paintInfo.phase == PaintPhaseForeground) { renderingContext.prepareToRenderSVGContent(this, childPaintInfo); continueRendering = renderingContext.isRenderingPrepared(); } if (continueRendering) { // Paint all phases of FO elements atomically, as though the FO element established its // own stacking context. bool preservePhase = paintInfo.phase == PaintPhaseSelection || paintInfo.phase == PaintPhaseTextClip; LayoutPoint childPoint = IntPoint(); childPaintInfo.phase = preservePhase ? paintInfo.phase : PaintPhaseBlockBackground; RenderBlock::paint(childPaintInfo, IntPoint()); if (!preservePhase) { childPaintInfo.phase = PaintPhaseChildBlockBackgrounds; RenderBlock::paint(childPaintInfo, childPoint); childPaintInfo.phase = PaintPhaseFloat; RenderBlock::paint(childPaintInfo, childPoint); childPaintInfo.phase = PaintPhaseForeground; RenderBlock::paint(childPaintInfo, childPoint); childPaintInfo.phase = PaintPhaseOutline; RenderBlock::paint(childPaintInfo, childPoint); } } }
void RenderSVGContainer::applyContentTransforms(PaintInfo& paintInfo) { if (!localTransform().isIdentity()) paintInfo.context->concatCTM(localTransform()); }
void RenderSVGContainer::paint(PaintInfo& paintInfo, int parentX, int parentY) { if (paintInfo.context->paintingDisabled()) return; // This should only exist for <svg> renderers if (hasBoxDecorations() && (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection)) paintBoxDecorations(paintInfo, m_x + parentX, m_y + parentY); if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth() && style()->visibility() == VISIBLE) paintOutline(paintInfo.context, parentX, parentY, width(), height(), style()); if (paintInfo.phase != PaintPhaseForeground || !drawsContents()) return; const SVGRenderStyle* svgStyle = style()->svgStyle(); AtomicString filterId(SVGURIReference::getTarget(svgStyle->filter())); #if ENABLE(SVG_EXPERIMENTAL_FEATURES) SVGResourceFilter* filter = getFilterById(document(), filterId); #endif if (!firstChild() #if ENABLE(SVG_EXPERIMENTAL_FEATURES) && !filter #endif ) return; // Spec: groups w/o children still may render filter content. paintInfo.context->save(); if (!parent()->isSVGContainer()) { // Translate from parent offsets (html renderers) to a relative transform (svg renderers) IntPoint origin; origin.move(parentX, parentY); origin.move(m_x, m_y); origin.move(borderLeft(), borderTop()); origin.move(paddingLeft(), paddingTop()); if (origin.x() || origin.y()) { paintInfo.context->concatCTM(AffineTransform().translate(origin.x(), origin.y())); paintInfo.rect.move(-origin.x(), -origin.y()); } parentX = parentY = 0; SVGSVGElement* svg = static_cast<SVGSVGElement*>(element()); paintInfo.context->concatCTM(AffineTransform().scale(svg->currentScale())); } else { // Only the root <svg> element should need any translations using the HTML/CSS system // parentX, parentY are also non-zero for first-level kids of these // CSS-transformed <svg> root-elements (due to RenderBox::paint) for any other element // they should be 0. m_x, m_y should always be 0 for non-root svg containers ASSERT(m_x == 0); ASSERT(m_y == 0); } if (!viewport().isEmpty()) { if (style()->overflowX() != OVISIBLE) paintInfo.context->clip(enclosingIntRect(viewport())); // FIXME: Eventually we'll want float-precision clipping paintInfo.context->concatCTM(AffineTransform().translate(viewport().x(), viewport().y())); } if (!localTransform().isIdentity()) paintInfo.context->concatCTM(localTransform()); if (!parent()->isSVGContainer()) { SVGSVGElement* svg = static_cast<SVGSVGElement*>(element()); paintInfo.context->concatCTM(AffineTransform().translate(svg->currentTranslate().x(), svg->currentTranslate().y())); } FloatRect strokeBBox = relativeBBox(true); SVGElement* svgElement = static_cast<SVGElement*>(element()); ASSERT(svgElement && svgElement->document() && svgElement->isStyled()); SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(svgElement); AtomicString clipperId(SVGURIReference::getTarget(svgStyle->clipPath())); AtomicString maskerId(SVGURIReference::getTarget(svgStyle->maskElement())); SVGResourceClipper* clipper = getClipperById(document(), clipperId); SVGResourceMasker* masker = getMaskerById(document(), maskerId); if (clipper) { clipper->addClient(styledElement); clipper->applyClip(paintInfo.context, strokeBBox); } else if (!clipperId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(clipperId, styledElement); if (masker) { masker->addClient(styledElement); masker->applyMask(paintInfo.context, strokeBBox); } else if (!maskerId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(maskerId, styledElement); float opacity = style()->opacity(); if (opacity < 1.0f) { paintInfo.context->clip(enclosingIntRect(strokeBBox)); paintInfo.context->beginTransparencyLayer(opacity); } #if ENABLE(SVG_EXPERIMENTAL_FEATURES) if (filter) filter->prepareFilter(paintInfo.context, strokeBBox); else if (!filterId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(filterId, styledElement); #endif if (!viewBox().isEmpty()) paintInfo.context->concatCTM(viewportTransform()); RenderContainer::paint(paintInfo, 0, 0); #if ENABLE(SVG_EXPERIMENTAL_FEATURES) if (filter) filter->applyFilter(paintInfo.context, strokeBBox); #endif if (opacity < 1.0f) paintInfo.context->endTransparencyLayer(); paintInfo.context->restore(); }
const AffineTransform& RenderSVGForeignObject::localToParentTransform() const { m_localToParentTransform = localTransform(); m_localToParentTransform.translate(m_viewport.x(), m_viewport.y()); return m_localToParentTransform; }
std::shared_ptr<raytracer::Primitive> Surface::applyTransform(std::shared_ptr<raytracer::Primitive> primitive) const { auto result = std::make_shared<raytracer::Instance>(primitive); result->setMatrix(localTransform()); return result; }
void StaticRayGroup::writeBegin(int indent,FILE* fp){ int i; for(i=0;i<indent;i++){fprintf(fp," ");} fprintf(fp,"#group_begin\n"); for(i=0;i<indent;i++){fprintf(fp," ");} fprintf(fp," %lg %lg %lg %lg\n", localTransform(0,0),localTransform(1,0), localTransform(2,0),localTransform(3,0)); for(i=0;i<indent;i++){fprintf(fp," ");} fprintf(fp," %lg %lg %lg %lg\n", localTransform(0,1),localTransform(1,1), localTransform(2,1),localTransform(3,1)); for(i=0;i<indent;i++){fprintf(fp," ");} fprintf(fp," %lg %lg %lg %lg\n", localTransform(0,2),localTransform(1,2), localTransform(2,2),localTransform(3,2)); for(i=0;i<indent;i++){fprintf(fp," ");} fprintf(fp," %lg %lg %lg %lg\n", localTransform(0,3),localTransform(1,3), localTransform(2,3),localTransform(3,3)); }
void RenderPath::paint(PaintInfo& paintInfo, int, int) { if (paintInfo.context->paintingDisabled() || (paintInfo.phase != PaintPhaseForeground) || style()->visibility() == HIDDEN || m_path.isEmpty()) return; paintInfo.context->save(); paintInfo.context->concatCTM(localTransform()); FloatRect strokeBBox = relativeBBox(true); SVGElement* svgElement = static_cast<SVGElement*>(element()); ASSERT(svgElement && svgElement->document() && svgElement->isStyled()); SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(svgElement); const SVGRenderStyle* svgStyle = style()->svgStyle(); AtomicString filterId(SVGURIReference::getTarget(svgStyle->filter())); AtomicString clipperId(SVGURIReference::getTarget(svgStyle->clipPath())); AtomicString maskerId(SVGURIReference::getTarget(svgStyle->maskElement())); #if ENABLE(SVG_EXPERIMENTAL_FEATURES) SVGResourceFilter* filter = getFilterById(document(), filterId); #endif SVGResourceClipper* clipper = getClipperById(document(), clipperId); SVGResourceMasker* masker = getMaskerById(document(), maskerId); #if ENABLE(SVG_EXPERIMENTAL_FEATURES) if (filter) filter->prepareFilter(paintInfo.context, strokeBBox); else if (!filterId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(filterId, styledElement); #endif if (clipper) { clipper->addClient(styledElement); clipper->applyClip(paintInfo.context, strokeBBox); } else if (!clipperId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(clipperId, styledElement); if (masker) { masker->addClient(styledElement); masker->applyMask(paintInfo.context, strokeBBox); } else if (!maskerId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(maskerId, styledElement); paintInfo.context->beginPath(); SVGPaintServer* fillPaintServer = KSVGPainterFactory::fillPaintServer(style(), this); if (fillPaintServer) { paintInfo.context->addPath(m_path); fillPaintServer->draw(paintInfo.context, this, ApplyToFillTargetType); } SVGPaintServer* strokePaintServer = KSVGPainterFactory::strokePaintServer(style(), this); if (strokePaintServer) { paintInfo.context->addPath(m_path); // path is cleared when filled. strokePaintServer->draw(paintInfo.context, this, ApplyToStrokeTargetType); } if (styledElement->supportsMarkers()) m_markerBounds = drawMarkersIfNeeded(paintInfo.context, paintInfo.rect, m_path); #if ENABLE(SVG_EXPERIMENTAL_FEATURES) // actually apply the filter if (filter) filter->applyFilter(paintInfo.context, strokeBBox); #endif paintInfo.context->restore(); }
hkDemo::Result PlanetGravityDemo::stepDemo() { // Update lighting { // Update the light source to be at the camera float position[3]; m_cameraPosition.store3( position ); m_flashLight->setPosition( position ); // Update the light direction to be pointing toward the character controller rigid body hkVector4 directionVector; directionVector.setSub4( m_cameraPosition, m_characterRigidBody->getPosition() ); directionVector.mul4( -1.0f ); directionVector.normalize3(); float direction[3]; directionVector.store3( direction ); m_flashLight->setDirection( direction ); } // Detach the camera from the character when P is pressed. if( m_env->m_window->getKeyboard().wasKeyPressed('P') ) { m_detachedCamera = !m_detachedCamera; } // Update turrets for( int i = 0; i < m_turrets.getSize(); i++ ) { Turret& turret = m_turrets[i]; turret.cooldown -= m_timestep; // Make the turret spin turret.hinge->setMotorTargetAngle( turret.hinge->getMotorTargetAngle() + ( m_timestep / 5.f ) ); // Bail out if the turret is "hot" if( turret.cooldown > 0.0f ) { continue; } // Generate a curved raycast and shoot the ray // This has to be done every time-step as it's in world-space { const hkReal radius = 14.8f; hkRotation rot; hkVector4 offset; hkVector4 turretDown; rot.set( turret.turretRigidBody->getRotation() ); offset = turret.turretRigidBody->getPosition(); turretDown.setMul4( -1.0f, rot.getColumn(2) ); hkpLinearParametricCurve myCurve; // Move the ray's source a little up so it's coming from the center of the barrel hkTransform localTransform( hkQuaternion::getIdentity(), hkVector4( 0.0f, 0.0f, 0.7f ) ); // Create a curve of 20 points for( int j = 0; j < 20; j++ ) { hkReal angle = HK_REAL_PI * static_cast<hkReal>(j) / 15.0f; hkVector4 newPoint( radius * 2.0f * sin( angle ), 0.0f, radius * 2.0f * cos( angle ) ); newPoint.setTransformedPos( localTransform, newPoint ); newPoint.setTransformedPos( turret.turretRigidBody->getTransform(), newPoint ); newPoint.addMul4( radius * 2.0f, turretDown ); myCurve.addPoint( newPoint ); } // We only need the closest hit (as our lasers can't pass through objects) // so hkpClosestRayHitCollector is used. hkpClosestRayHitCollector raycastOutput; hkReal t = castCurvedRay( raycastOutput, myCurve, 20 ); // Apply a large force to the closest rb we hit, along the tangent at the colliding point if( raycastOutput.hasHit() ) { hkpRigidBody* hitRb = hkGetRigidBody( raycastOutput.getHit().m_rootCollidable ); if( hitRb->getMotionType() != hkpMotion::MOTION_FIXED ) { hkVector4 tangent; myCurve.getTangent( t, tangent ); tangent.mul4( 15000.0f ); applyScaledLinearImpulse( hitRb, tangent ); turret.cooldown = 3.0f; } } } } m_world->markForWrite(); // Update the character context m_characterRigidBody->m_up = m_worldUp; hkReal posX = 0.0f; hkReal posY = 0.0f; if( !m_detachedCamera ) { float deltaAngle; CharacterUtils::getUserInputForCharacter( m_env, deltaAngle, posX, posY ); if( ( ( hkMath::fabs( posX ) < HK_REAL_MAX ) && ( hkMath::fabs( posY ) < HK_REAL_MAX ) ) && ( posX || posY ) ) { // find new orientation in local space hkVector4 newForward( -posY, 0.0f, -posX ); hkVector4 absoluteForward( 1.0f, 0.0f, 0.0f ); hkReal characterAngle = hkMath::acos( absoluteForward.dot3( newForward ) ); // Calculate cross product to get sign of rotation. hkVector4 crossProduct; crossProduct.setCross( absoluteForward, newForward ); if( crossProduct(1) < 0.0f ) { characterAngle *= -1.0f; } // Rotate the character's rigid body to face in the direction it's moving hkRotation newRotation; newRotation.setAxisAngle( m_worldUp, characterAngle ); m_characterForward.setRotatedDir( newRotation, m_cameraForward ); m_characterForward.normalize3(); } // Rotate the camera's forward vector based on world up vector and mouse movement if( deltaAngle != 0.0f && m_characterRigidBody->getRigidBody()->getRotation().hasValidAxis() ) { hkRotation newRotation; newRotation.setAxisAngle( m_worldUp, deltaAngle ); m_cameraForward.setRotatedDir( newRotation, m_cameraForward ); m_cameraForward.normalize3(); } } HK_TIMER_BEGIN( "set character state", HK_NULL ); hkpCharacterInput input; hkpCharacterOutput output; { input.m_atLadder = false; input.m_inputLR = posX; input.m_inputUD = posY; if( m_detachedCamera ) { input.m_wantJump = false; } else { input.m_wantJump = m_env->m_window->getMouse().wasButtonPressed( HKG_MOUSE_LEFT_BUTTON ) || m_env->m_gamePad->wasButtonPressed( HKG_PAD_BUTTON_1 ); } // Check that we have a valid rotation. Probably won't for the first couple of frames. if( !( m_characterRigidBody->getRigidBody()->getRotation().hasValidAxis() ) ) { input.m_up = hkVector4( 0.0f, 0.0f, 1.0f ); input.m_forward = m_cameraForward; } else { input.m_up = m_worldUp; // Recalculate m_forward so it's perpendicular to m_worldUp hkVector4 newRot; newRot.setCross( m_cameraForward, m_worldUp ); m_cameraForward.setCross( m_worldUp, newRot ); // Display character's current heading hkRotation characterRotation; characterRotation.set( m_characterRigidBody->getRigidBody()->getRotation() ); HK_DISPLAY_ARROW( m_characterRigidBody->getPosition(), characterRotation.getColumn(0), hkColor::LIMEGREEN ); input.m_forward = m_cameraForward; } hkStepInfo stepInfo; stepInfo.m_deltaTime = m_timestep; stepInfo.m_invDeltaTime = 1.0f / m_timestep; input.m_stepInfo = stepInfo; input.m_characterGravity.setMul4( -20.0f, m_worldUp ); input.m_velocity = m_characterRigidBody->getRigidBody()->getLinearVelocity(); input.m_position = m_characterRigidBody->getRigidBody()->getPosition(); { hkpSurfaceInfo ground; m_characterRigidBody->checkSupport( stepInfo, ground ); // Avoid accidental state changes (Smooth movement on stairs) // During transition supported->unsupported continue to return N-frames hkpSurfaceInfo data from previous supported state { // Number of frames to skip (continue with previous hkpSurfaceInfo data) const int skipFramesInAir = 6; if( input.m_wantJump ) { m_framesInAir = skipFramesInAir; } hkpSurfaceInfo* currInfo; if( ground.m_supportedState != hkpSurfaceInfo::SUPPORTED ) { if( m_framesInAir < skipFramesInAir ) { input.m_isSupported = true; currInfo = m_previousGround; } else { input.m_isSupported = false; currInfo = &ground; } m_framesInAir++; } else { input.m_isSupported = true; currInfo = &ground; m_previousGround->set( ground ); // reset old number of frames if( m_framesInAir > skipFramesInAir ) { m_framesInAir = 0; } } input.m_surfaceNormal = currInfo->m_surfaceNormal; input.m_surfaceVelocity = currInfo->m_surfaceVelocity; input.m_surfaceMotionType = currInfo->m_surfaceMotionType; } } HK_TIMER_END(); } // Apply the character state machine { HK_TIMER_BEGIN( "update character state", HK_NULL ); m_characterContext->update( input, output ); HK_TIMER_END(); } //Apply the player character controller { HK_TIMER_BEGIN( "simulate character", HK_NULL ); // Set output velocity from state machine into character rigid body m_characterRigidBody->setLinearVelocity( output.m_velocity, m_timestep ); HK_TIMER_END(); m_world->unmarkForWrite(); } // Rotate the character { hkRotation newOrientation; newOrientation.getColumn(0) = m_characterForward; newOrientation.getColumn(1) = m_worldUp; newOrientation.getColumn(2).setCross( newOrientation.getColumn(0), newOrientation.getColumn(1) ); newOrientation.renormalize(); reorientCharacter( newOrientation ); } // Step the world hkDefaultPhysicsDemo::stepDemo(); // Display state { hkpCharacterStateType state = m_characterContext->getState(); char* stateStr; switch( state ) { case HK_CHARACTER_ON_GROUND: { stateStr = "On Ground"; break; } case HK_CHARACTER_JUMPING: { stateStr = "Jumping"; break; } case HK_CHARACTER_IN_AIR: { stateStr = "In Air"; break; } default: { stateStr = "Other"; break; } } char buffer[255]; hkString::snprintf( buffer, 255, "State : %s", stateStr ); m_env->m_textDisplay->outputText( buffer, 20.f, 270.f, 0xffffffff ); } // // Handle crouching (only for capsule) // if( !m_detachedCamera ) { m_world->markForWrite(); hkBool wantCrouch = ( m_env->m_window->getMouse().getButtonState() & HKG_MOUSE_RIGHT_BUTTON ) || ( m_env->m_gamePad->getButtonState() & HKG_PAD_BUTTON_2 ); hkBool isCrouching = ( m_characterRigidBody->getRigidBody()->getCollidable()->getShape() == m_crouchShape ); // We want to stand if( isCrouching && !wantCrouch ) { m_characterRigidBody->getRigidBody()->setShape( m_standShape ); } // We want to crouch else if( !isCrouching && wantCrouch ) { m_characterRigidBody->getRigidBody()->setShape( m_crouchShape ); } m_world->unmarkForWrite(); } // Transparent camera handling if( !m_detachedCamera ) { m_world->markForWrite(); handleCamera(); m_world->unmarkForWrite(); } return hkDemo::DEMO_OK; }
int StaticRayGroup::read(FILE* fp){ if(fscanf(fp," %lg %lg %lg %lg %lg %lg %lg %lg %lg %lg %lg %lg %lg %lg %lg %lg", &(localTransform(0,0)),&(localTransform(1,0)), &(localTransform(2,0)),&(localTransform(3,0)), &(localTransform(0,1)),&(localTransform(1,1)), &(localTransform(2,1)),&(localTransform(3,1)), &(localTransform(0,2)),&(localTransform(1,2)), &(localTransform(2,2)),&(localTransform(3,2)), &(localTransform(0,3)),&(localTransform(1,3)), &(localTransform(2,3)),&(localTransform(3,3))) != 16){ fprintf(stderr, "Failed to parse group_begin for StaticGroup\n"); return 0; } return set(); }
Car::Car(const ion::base::String& identifier,NewtonWorld *pWorld,const ion::video::Mesh& srcmesh,const float mass, const float Ixx,const float Iyy,const float Izz):Node(identifier),m_pNewtonChassisCollision(0),m_pBody(0), m_pNewtonworld(pWorld),m_pNewtonJoint(0) { if (pWorld==0) { ion::base::log("Car::Car()",ion::base::Error) << "No NewtonWorld pointer given\n"; return; } if (!srcmesh.isValid()) { ion::base::log("Car::Car()",ion::base::Error) << "Source mesh is invalid\n"; return; } if (!srcmesh.vertexstream().isMapped()) { ion::base::log("Car::Car()",ion::base::Error) << "source mesh \"" << srcmesh.objIdentifier() << " is not mapped!\n"; return; } if ((m_pNewtonChassisCollision!=0) && (m_pNewtonworld!=0)) NewtonReleaseCollision(m_pNewtonworld,m_pNewtonChassisCollision); float *pPoints; { pPoints=new float[3*srcmesh.vertexstream().capacity()]; for (ion_uint32 v=0;v<srcmesh.vertexstream().capacity();++v) { const ion::math::Vector3f &rV=srcmesh.vertexstream().position(v); pPoints[v*3+0]=rV.x(); pPoints[v*3+1]=rV.y(); pPoints[v*3+2]=rV.z(); } } ion::math::Matrix4f c; m_pNewtonworld=pWorld; m_pNewtonChassisCollision=NewtonCreateConvexHull(m_pNewtonworld,srcmesh.vertexstream().capacity(),pPoints,12,c); m_pBody=NewtonCreateBody(m_pNewtonworld,m_pNewtonChassisCollision); NewtonBodySetUserData(m_pBody,this); ion::math::Vector3f origin,inertia; // calculate the moment of inertia and the relative center of mass of the solid NewtonConvexCollisionCalculateInertialMatrix (m_pNewtonChassisCollision, &inertia[0], &origin[0]); float ixx = mass * inertia[0]; float iyy = mass * inertia[1]; float izz = mass * inertia[2]; // set the mass matrix NewtonBodySetMassMatrix (m_pBody, mass, ixx, iyy, izz); origin.y()=-1; NewtonBodySetCentreOfMass (m_pBody, &origin[0]); NewtonBodySetMatrix(m_pBody,localTransform().matrix()); NewtonReleaseCollision(m_pNewtonworld,m_pNewtonChassisCollision); NewtonBodySetTransformCallback (m_pBody, physicsSetTransform); NewtonBodySetForceAndTorqueCallback (m_pBody, physicsApplyForceAndTorque); float updir[3]={0,1,0}; m_pNewtonJoint=NewtonConstraintCreateVehicle(m_pNewtonworld,&updir[0],m_pBody); NewtonVehicleSetTireCallback(m_pNewtonJoint,tireUpdate); delete [] pPoints; }
void Car::rotation(const ion::math::Quaternion& newrotation) { Node::rotation(newrotation); NewtonBodySetMatrix(m_pBody,localTransform().matrix()); }
void Car::position(const float x,const float y,const float z) { Node::position(x,y,z); NewtonBodySetMatrix(m_pBody,localTransform().matrix()); }
void hkFlattenShapeHierarchyUtil::getLeafShapesFromShape(const hkpShape* shape, const hkTransform& transform, const hkBool isFixedBody, hkArray<hkpExtendedMeshShape::TrianglesSubpart>& trianglePartsOut, hkArray<hkpConvexShape*>& convexShapesOut, hkArray<hkpShape*>& otherShapesOut) { const hkpShapeType type = shape->getType(); hkTransform newTransform; const hkpShape* childShape = HK_NULL; hkUlong userData = HK_NULL; switch(type) { case HK_SHAPE_LIST: case HK_SHAPE_CONVEX_LIST: { const hkpShapeContainer* container = shape->getContainer(); hkpShapeContainer::ShapeBuffer buffer; HK_ASSERT2(0xad67da22, 0 == (0xffff0000 & hkUlong(shape->getUserData())), "We're dropping a non-zero lookupIndex from user data."); hkUint16 materialId = hkUint16(0xffff & hkUlong(shape->getUserData())); for (hkpShapeKey key = container->getFirstKey(); key != HK_INVALID_SHAPE_KEY; key = container->getNextKey(key)) { const hkpShape* child = container->getChildShape(key, buffer); if (materialId && 0 == (0xffff & hkUlong(child->getUserData())) ) { // no material id for the child -- copy it hkUlong childData = hkUlong(child->getUserData()) | materialId; // Warning: modifying the const input hkpShape* const_cast<hkpShape*>(child)->setUserData(childData); } //HK_ASSERT2(0xad6777dd, isFixedBody || !isLeafShape(child), "A child of a list shape cannot be a terminal node. You must use a transform shape in between." ); getLeafShapesFromShape(child, transform, isFixedBody, trianglePartsOut, convexShapesOut, otherShapesOut); } } break; case HK_SHAPE_TRANSFORM: { const hkpTransformShape* transformShape = static_cast<const hkpTransformShape*>(shape); newTransform.setMul(transform, transformShape->getTransform()); childShape = transformShape->getChildShape(); userData = hkUlong(transformShape->getUserData()); } break; case HK_SHAPE_CONVEX_TRANSFORM: { const hkpConvexTransformShape* convexTransformShape = static_cast<const hkpConvexTransformShape*>(shape); newTransform.setMul(transform, convexTransformShape->getTransform()); childShape = convexTransformShape->getChildShape(); userData = hkUlong(convexTransformShape->getUserData()); } break; case HK_SHAPE_CONVEX_TRANSLATE: { const hkpConvexTranslateShape* convexTranslateShape = static_cast<const hkpConvexTranslateShape*>(shape); hkTransform localTransform( static_cast<const hkRotation&>(hkRotation::getIdentity()), convexTranslateShape->getTranslation() ); newTransform.setMul(transform, localTransform); childShape = convexTranslateShape->getChildShape(); userData = hkUlong(convexTranslateShape->getUserData()); } break; case HK_SHAPE_BV_TREE: { const hkpBvTreeShape* bvTreeshape = static_cast<const hkpBvTreeShape*>(shape); HK_ASSERT2(0xad67da22, 0 == (0xffff0000 & hkUlong(bvTreeshape->getUserData())), "We're dropping a non-zero lookupIndex from user data."); const hkpShapeContainer* container = bvTreeshape->getContainer(); for (hkpShapeKey key = container->getFirstKey(); key!= HK_INVALID_SHAPE_KEY; key = container->getNextKey(key)) { hkpShapeContainer::ShapeBuffer buffer; const hkpShape* child = container->getChildShape(key, buffer); const hkpShapeType childType = child->getType(); if ((childType == HK_SHAPE_LIST) || (childType == HK_SHAPE_CONVEX_LIST)) { getLeafShapesFromShape(child, transform, isFixedBody, trianglePartsOut, convexShapesOut, otherShapesOut); } } break; } case HK_SHAPE_MOPP: { const hkpMoppBvTreeShape* bvTreeshape = static_cast<const hkpMoppBvTreeShape*>(shape); // HK_ASSERT2(0xad67da22, 0 == (0xffff0000 & hkUlong(bvTreeshape->getUserData())), "We're dropping a non-zero lookupIndex from user data."); getLeafShapesFromShape(bvTreeshape->getShapeCollection(), transform, isFixedBody, trianglePartsOut, convexShapesOut, otherShapesOut); break; } default: { //HK_ASSERT2(0xad67ddaa, isFixedBody, "A child of a list was attached without an intermediate transform shape. This is not handled."); // We can get simple shapes without transforms when processing fixed bodies. We do add a hkpConvexTransformShape as usual then ... childShape = shape; newTransform = transform; userData = hkUlong(shape->getUserData()); //HK_ASSERT2(0XAD678D8D, 0 == (userData & 0xffff0000), "Userdata of a fixed body (other than the one fixed uber body) has a non-zero destructible info index."); } break; } if (HK_NULL != childShape) { hkBool leafDone = false; if (hkOneFixedMoppUtil::isTerminalConvexShape(childShape)) { // Create new transform shape to wrap the child terminal shape hkpConvexTransformShape* newConvexTransformShape = new hkpConvexTransformShape(static_cast<const hkpConvexShape*>(childShape), newTransform); newConvexTransformShape->setUserData( userData ); HK_ASSERT2(0xad67da23, 0 == (0xffff0000 & hkUlong(childShape->getUserData())) || (0xffff0000 & userData) == (0xffff0000 & hkUlong(childShape->getUserData())), "We're dropping a non-zero user data."); HK_ASSERT2(0xad67da24, 0 == (0xffff & hkUlong(childShape->getUserData())) || (0xffff & userData) == (0xffff & hkUlong(childShape->getUserData())), "Materials differ in the terminal shape and its wrapping hkpTransformShape."); // put this transform on the shapesOut list convexShapesOut.pushBack(newConvexTransformShape); leafDone = true; } else if (isLeafShape(childShape)) { // It's not a terminal(leaf?) convex shape, but it might be a mesh, or indeed a simplemesh. // It's most likely to be a storagemesh, but we can't assume that, so check vtable: const hkClass* childShapeClass = hkBuiltinTypeRegistry::getInstance().getVtableClassRegistry()->getClassFromVirtualInstance(childShape); if( hkpMeshShapeClass.isSuperClass(*childShapeClass) ) { const hkpMeshShape* mesh = static_cast<const hkpMeshShape*>(childShape); // Confirm vertex data not shared, see below #if defined(HK_DEBUG) { for(int i = 0; i < mesh->getNumSubparts(); i++) { const hkpMeshShape::Subpart& meshSubPartI = mesh->getSubpartAt(i); for(int j = i+1; j < mesh->getNumSubparts(); j++) { const hkpMeshShape::Subpart& meshSubPartJ = mesh->getSubpartAt(j); HK_ASSERT2(0x0, meshSubPartI.m_vertexBase != meshSubPartJ.m_vertexBase, "This method can't (currently) collapse chared meshs data as it collpases the transform into the verts\n"); } } } #endif for(int i = 0; i < mesh->getNumSubparts(); i++) { const hkpMeshShape::Subpart& meshSubPart = mesh->getSubpartAt(i); // Now we have the subpart. We can't know if the data pointed to is 'owned' by the mesh (eg. subclass hkpStorageMeshShape) // or 'pointed to' (base class hkpMeshShape) // // We'll just assume here we can 'share' the data by grabbing the pointers... hkpExtendedMeshShape::TrianglesSubpart extendedMeshSubPart; extendedMeshSubPart.m_vertexBase = meshSubPart.m_vertexBase; extendedMeshSubPart.m_vertexStriding = meshSubPart.m_vertexStriding; extendedMeshSubPart.m_numVertices = meshSubPart.m_numVertices; extendedMeshSubPart.m_triangleOffset = meshSubPart.m_triangleOffset; // .. but we'll have to multiply in the transform! This assumes the vertex data is not shared! { for(int j = 0; j < extendedMeshSubPart.m_numVertices ; j++) { hkVector4 v; v(0) = extendedMeshSubPart.m_vertexBase[0 + extendedMeshSubPart.m_vertexStriding/sizeof(float) * j]; v(1) = extendedMeshSubPart.m_vertexBase[1 + extendedMeshSubPart.m_vertexStriding/sizeof(float) * j]; v(2) = extendedMeshSubPart.m_vertexBase[2 + extendedMeshSubPart.m_vertexStriding/sizeof(float) * j]; v.setTransformedPos(transform, v); const_cast<float*>(extendedMeshSubPart.m_vertexBase)[0 + extendedMeshSubPart.m_vertexStriding/sizeof(float) * j] = v(0); const_cast<float*>(extendedMeshSubPart.m_vertexBase)[1 + extendedMeshSubPart.m_vertexStriding/sizeof(float) * j] = v(1); const_cast<float*>(extendedMeshSubPart.m_vertexBase)[2 + extendedMeshSubPart.m_vertexStriding/sizeof(float) * j] = v(2); } } extendedMeshSubPart.m_indexBase = meshSubPart.m_indexBase; extendedMeshSubPart.m_indexStriding = meshSubPart.m_indexStriding; extendedMeshSubPart.m_numTriangleShapes = meshSubPart.m_numTriangles; extendedMeshSubPart.m_stridingType = (meshSubPart.m_stridingType == hkpMeshShape::INDICES_INT16) ? hkpExtendedMeshShape::INDICES_INT16 : hkpExtendedMeshShape::INDICES_INT32; trianglePartsOut.pushBack(extendedMeshSubPart); leafDone = true; } } } if(!leafDone) { HK_WARN(0xad678dda, "An extra hkTransform shape has been inserted into the hierarchy. This might be suboptimal."); // Create new transform shape to wrap the child terminal shape hkpTransformShape* newTransformShape = new hkpTransformShape(childShape, newTransform); newTransformShape->setUserData( userData ); HK_ASSERT2(0xad67da23, 0 == (0xffff0000 & hkUlong(childShape->getUserData())) || (0xffff0000 & userData) == (0xffff0000 & hkUlong(childShape->getUserData())), "We're dropping a non-zero user data."); HK_ASSERT2(0xad67da24, 0 == (0xffff & hkUlong(childShape->getUserData())) || (0xffff & userData) == (0xffff & hkUlong(childShape->getUserData())), "Materials differ in the terminal shape and its wrapping hkpTransformShape."); // put this transform on the shapesOut list otherShapesOut.pushBack(newTransformShape); leafDone = true; } if(!leafDone) { //HK_ASSERT2(0xad67da23, 0 == (0xffff0000 & shape->getUserData()), "We're dropping a non-zero user data."); if ( 0xffff0000 & hkUlong(shape->getUserData()) ) { // copy the destruction info index downwards.. HK_ASSERT2(0xad67da23, 0 == (0xffff0000 & hkUlong(childShape->getUserData())) || (0xffff0000 & userData) == (0xffff0000 & hkUlong(childShape->getUserData())), "We're dropping a non-zero user data."); HK_ASSERT2(0xad67da24, 0 == (0xffff & hkUlong(childShape->getUserData())) || (0xffff & hkUlong(shape->getUserData())) == (0xffff & hkUlong(childShape->getUserData())), "Materials differ in the terminal shape and its wrapping hkpTransformShape."); //HK_WORLD_ACCESS_CHECK(parentBody->getWorld(), HK_ACCESS_RW ); // Warning: we're actually modifying the const hkpShape* passed as an input parameter const_cast<hkpShape*>(childShape)->setUserData( shape->getUserData() ); } getLeafShapesFromShape(childShape, newTransform, isFixedBody, trianglePartsOut, convexShapesOut, otherShapesOut); } } }
void Car::position(const ion::math::Vector3f& newposition) { Node::position(newposition); NewtonBodySetMatrix(m_pBody,localTransform().matrix()); }