void PhysicsBallJoint::changed(ConstFieldMaskArg whichField, 
                            UInt32            origin,
                            BitVector         details)
{
    //Do not respond to changes that have a Sync origin
    if(origin & ChangedOrigin::Sync)
    {
        return;
    }

    if(whichField & WorldFieldMask)
    {
        if(_JointID)
        {
            dJointDestroy(_JointID);
        }
        _JointID = dJointCreateBall(getWorld()->getWorldID(), 0);
    }

    Inherited::changed(whichField, origin, details);

    if((whichField & AnchorFieldMask) || (whichField & WorldFieldMask))
    {
	    dJointSetBallAnchor(_JointID, getAnchor().x(), getAnchor().y(), getAnchor().z());
    }
}
Esempio n. 2
0
MarkToBaseLookup1::MarkToBaseLookup1 (MemoryPen pen, OpenTypeFont &font, bool aMarkToMark)
: markToMark (aMarkToMark) {
	MemoryPen start = pen;
	// format = 1
	pen.readUShort();
	markCoverage = getCoverageTable (start + pen.readOffset(), font);
	baseCoverage = getCoverageTable (start + pen.readOffset(), font);

	UShort markClassNum = pen.readUShort();
	
	markArray = getMarkArray (start + pen.readOffset());
	if (markArray.size() != markCoverage->getGlyphNum())
		throw Exception (
			"Number of glyphs in mark array does not equal number of glyphs in coverage table");

	MemoryPen baseArrayPen = start + pen.readOffset();
	MemoryPen baseArrayStart = baseArrayPen;
	UShort baseNum = baseArrayPen.readUShort();
	if (baseNum != baseCoverage->getGlyphNum())
		throw Exception (
			"Number of glyphs in base array does not equal number of glyphs in coverage table");

	for (UShort i = 0; i < baseNum; i ++) {
		BaseRecord r;
		for (UShort j = 0; j < markClassNum; j ++)
			r.push_back (getAnchor (baseArrayStart + baseArrayPen.readOffset()));
		baseArray.push_back (r);
	}
}
Esempio n. 3
0
void
Gui::appendTabToDefaultViewerPane(PanelWidget* tab,
                                  ScriptObject* obj)
{
    TabWidget* viewerAnchor = getAnchor();

    assert(viewerAnchor);
    viewerAnchor->appendTab(tab, obj);
}
Esempio n. 4
0
void dJointGetScrewAnchor2( dJointID j, dVector3 result )
{
    dxJointScrew* joint = ( dxJointScrew* )j;
    dUASSERT( joint, "bad joint argument" );
    dUASSERT( result, "bad result argument" );
    checktype( joint, Screw );
    if ( joint->flags & dJOINT_REVERSE )
        getAnchor( joint, result, joint->anchor1 );
    else
        getAnchor2( joint, result, joint->anchor2 );
}
Esempio n. 5
0
// Return -1 on error (a square no longer has possibilities)
int process(int row, int col, char grid[9][9], Candidates gridC[9][9],
             std::list<std::pair<int, int>> & pointsOfInterest) {
    if (!isSudokuDigit(grid[row][col])) { return 0; }
    auto c = grid[row][col] - '1' + 1;
    // Remove possibility from the row, col, and current box
    for (int i = 0; i < 9; ++i) {
        if (i == col) { continue; }
        auto r = gridC[row][i].setFalse(c);
        if (r > 0 && !isSudokuDigit(grid[row][i])) {
            grid[row][i] = (r - 1) + '1';
            pointsOfInterest.push_back(std::pair<int, int>(row, i));
        } else if (r == -1) {
            return -1;
        }
    }
    for (int i = 0; i < 9; ++i) {
        if (i == row) { continue; }
        auto r = gridC[i][col].setFalse(c);
        if (r > 0 && !isSudokuDigit(grid[i][col])) {
            grid[i][col] = (r - 1) + '1';
            pointsOfInterest.push_back(std::pair<int, int>(i, col));
        } else if (r == -1) {
            return -1;
        }
    }
    int m = getAnchor(row);
    int n = getAnchor(col);
    for (int k = 0; k < 3; ++k) {
        for (int l = 0; l < 3; ++l) {
            if (m + k == row && n + l == col) { continue; }
            auto r = gridC[m + k][n + l].setFalse(c);
            if (r > 0 && !isSudokuDigit(grid[m + k][n + l])) {
                grid[m + k][n + l] = (r - 1) + '1';
                pointsOfInterest.push_back(std::pair<int, int>(m + k, n + l));
            } else if (r == -1) {
                return -1;
            }
        }
    }
    return 0;
}
Esempio n. 6
0
void BoundingBox2D::set(cv::Point minPoint,
                        cv::Point maxPoint,
                        float minDepth,
                        float maxDepth)
{
    m_minPoint = minPoint;
    m_maxPoint = maxPoint;
    m_minDepth = minDepth;
    m_maxDepth = maxDepth;

    assert(m_minPoint.x <= m_maxPoint.x);
    assert(m_minPoint.y <= m_maxPoint.y);
    assert(m_minDepth <= m_maxDepth);

    // update inferred data
    m_width = m_maxPoint.x - m_minPoint.x;
    m_height = m_maxPoint.y - m_minPoint.y;
    m_center = cv::Point(m_minPoint.x + (m_width / 2), m_minPoint.y + (m_height / 2));
    m_area = (getAnchor(AT_RIGHT) - getAnchor(AT_LEFT)) *
            (getAnchor(AT_BOTTOM) - getAnchor(AT_TOP));
    m_avgDepth = m_minDepth + ((m_maxDepth - m_minDepth) / 2.0f);
}
Esempio n. 7
0
Meta* Meta::clone() {
    Meta* ret = new Meta();

    MetInf* retMetInf = new MetInf(getFormat(), getType(), getMark(), getSize(), getAnchor(), getVersion(),
                   getNextNonce(), getMaxMsgSize(), getMaxObjSize(), getEMI(), getMem());
    ret->setMetInf(retMetInf);

    if (retMetInf) {
        delete retMetInf; retMetInf = NULL;
    }

    return ret;

}
Esempio n. 8
0
MarkArray getMarkArray (MemoryPen pen) {
	MemoryPen start = pen;
	MarkArray markArray;

	UShort markRecordNum = pen.readUShort();
	markArray.reserve (markRecordNum);
	for (UShort i = 0; i < markRecordNum; i++) {
		MarkRecord r;
		r.markClass = pen.readUShort();
		r.markAnchor = getAnchor (start + pen.readOffset());
		markArray.push_back (r);
	}

	return markArray;
}
__int64 CHexViewView::getBestTopLine(__int64 addr) const {
  const __int64 line1  = GETLINENO(addr);
  const __int64 addr2  = hasAnchor() ? getAnchor() : addr;
  const __int64 line2  = GETLINENO(addr2);

  if(ISVISIBLELINE(line1) && ISVISIBLELINE(line2)) {
    return m_topLine; // no need to do vertical scroll
  }
  const __int64 selectedLineCount = (addr == addr2) ? 0 : (abs(line1 - line2) + 1);
  if(selectedLineCount <= m_pageSize.cy) {
    return min(line1, line2) - (m_pageSize.cy - selectedLineCount)/2;
  } else {
    return min(line1, line2);
  }
}
Esempio n. 10
0
void RectShape::DrawSelf(Renderer *r)
{
    auto sh = static_cast<PrimitiveShader_PC*>(getShader());
    r->Use(sh);
    auto const &an = getAnchor();
    auto const &pos = getPosition();
    auto const &sz = getSize();
    Vec2 arrs[4];
    arrs[0] = Vec2(pos.x - sz.x*an.x, pos.y - sz.y*an.y);
    arrs[1] = Vec2(arrs[0].x+sz.x, arrs[0].y);
    arrs[2] = Vec2(arrs[0].x, arrs[0].y+sz.y);
    arrs[3] = Vec2(arrs[0].x+sz.x, arrs[0].y+sz.y);
    sh->pushColor(getColor());
    sh->drawTriangleStrip(getWorldTransform(), &arrs[0], 4);
    sh->popColor();
}
Esempio n. 11
0
void
Gui::activateViewerTab(ViewerInstance* viewer)
{
    OpenGLViewerI* viewport = viewer->getUiContext();

    {
        QMutexLocker l(&_imp->_viewerTabsMutex);
        for (std::list<ViewerTab*>::iterator it = _imp->_viewerTabs.begin(); it != _imp->_viewerTabs.end(); ++it) {
            if ( (*it)->getViewer() == viewport ) {
                TabWidget* viewerAnchor = getAnchor();
                assert(viewerAnchor);
                viewerAnchor->appendTab(*it, *it);
                (*it)->show();
            }
        }
    }
    Q_EMIT viewersChanged();
}
Esempio n. 12
0
bool Node::addAnchor( int index, bptni::Anchor *anchor ) {
	// anchor position must be in the correct range and anchor must exist
	if ((index < 0 || index > (int) anchorList->size()) || anchor == NULL) {
		return false;
	}

	// anchor id must be unique - conflicts with referredNode anchor ids
	// can only be solved at runtime, since anchors can be inserted after
	if (getAnchor( anchor->getId() ) != NULL) {
		return false;
	}

	if (index == (int) anchorList->size()) {
		anchorList->push_back( anchor );
	} else {
		anchorList->insert( anchorList->begin() + index, anchor );
	}

	return true;
}
Esempio n. 13
0
MarkToLigatureLookup1::MarkToLigatureLookup1 (MemoryPen pen, OpenTypeFont &font)
{
	MemoryPen start = pen;
	// format = 1
	pen.readUShort();
	markCoverage = getCoverageTable (start + pen.readOffset(), font);
	ligatureCoverage = getCoverageTable (start + pen.readOffset(), font);

	UShort markClassNum = pen.readUShort();
	
	markArray = getMarkArray (start + pen.readOffset());
	if (markArray.size() != markCoverage->getGlyphNum())
		throw Exception (
			"Number of glyphs in mark array does not equal number of glyphs in coverage table");

	MemoryPen ligatureArrayPen = start + pen.readOffset();
	MemoryPen ligatureArrayStart = ligatureArrayPen;
	UShort ligatureNum = ligatureArrayPen.readUShort();
	if (ligatureNum != ligatureCoverage->getGlyphNum())
		throw Exception (
			"Number of glyphs in ligature array does not equal number of glyphs in coverage table");

	for (UShort i = 0; i < ligatureNum; i ++) {
		LigatureMarkAnchors ligatureMarkAnchors;
		MemoryPen ligatureAttachPen = ligatureArrayStart + ligatureArrayPen.readOffset();
		MemoryPen ligatureAttachStart = ligatureAttachPen;
		for (UShort componentNum = ligatureAttachPen.readUShort(); componentNum; componentNum --) {
			ComponentAnchors componentAnchors;
			for (UShort j = 0; j < markClassNum; j ++) {
				Offset anchorOffset = ligatureAttachPen.readOffset();
				if (anchorOffset)
					componentAnchors.push_back (getAnchor (ligatureAttachStart +
						anchorOffset));
				else
					componentAnchors.push_back (NULL);
			}
			ligatureMarkAnchors.push_back (componentAnchors);
		}
		ligatureAnchors.push_back (ligatureMarkAnchors);
	}
}
Esempio n. 14
0
int CHexViewView::getBestLineOffset(__int64 addr) const {
  const __int64 offset1 = GETLINEOFFSET(addr);
  const __int64 addr2   = hasAnchor() ? getAnchor() : addr;
  const __int64 offset2 = GETLINEOFFSET(addr2);

  if(ISVISIBLEOFFSET(offset1) && ISVISIBLEOFFSET(offset2)) {
    return m_lineOffset; // no need to do horizontal scroll
  }
  const __int64 line1 = GETLINENO(addr );
  const __int64 line2 = GETLINENO(addr2);
  if(line1 == line2) {
    const int length = (int)abs(addr - addr2);
    if(length <= m_pageSize.cx) {
      return (int)(min(offset1, offset2) - (m_pageSize.cx - length)/2);
    } else {
      return (int)min(offset1, offset2);
    }
  } else {
    return (int)min(offset1, offset2);
  }
}
Esempio n. 15
0
void Cell::destroyCell ()
{
  if (getFlagStr() != INVALID_STR)
  {
    if (_rhs != NULL)
    {
      if (getRhsDim() > 1)
        delete[] _rhs;

      else
        delete _rhs;

      _rhs = NULL;
    }

    if (_detwindow != NULL)
    {
      delete[] _detwindow;
      _detwindow = NULL;
    }

    if (getFlagStr() == STR_ANCHOR)
    {
      if (_anchor != NULL)
      {
        for (int i = 0; i < getAnchorDim(); i++)
        {
          if (getAnchor()[i].array != NULL)
          {
            delete[] getAnchor()[i].array;
            getAnchor()[i].array = NULL;
          }
        }

        delete[] _anchor;
        _anchor = NULL;
      } 

      if (_score != NULL)
      {
        for (int i = 0; i < getScoreDim(); i++)
        {
          if (_score[i] != NULL)
          {
            cvReleaseMat (&_score[i]);
            _score[i] = NULL;
          }
        }
      
        delete[] _score;
        _score = NULL;
      }
    }

    if (_Ix != NULL)
    {
      for (int i = 0; i < getIxDim(); i++)
      {
        if (_Ix[i] != NULL)
        {
          cvReleaseMat (&_Ix[i]);
          _Ix[i] = NULL;
        }
      }

      delete[] _Ix;
      _Ix = NULL;
    }

    if (_Iy != NULL)
    {
      for (int i = 0; i < getIyDim(); i++)
      {
        if (_Iy[i] != NULL)
        {
          cvReleaseMat (&_Iy[i]);
          _Iy[i] = NULL;
        }
      }

      delete[]_Iy;
      _Iy = NULL;
    }
  }

  setFlagStr (INVALID_STR);
}
Esempio n. 16
0
int BoundingBox2D::getAnchorDistance(AnchorType anchor,
                                     const BoundingBox2D& other) const
{
    return abs(getAnchor(anchor) - other.getAnchor(anchor));
}
Esempio n. 17
0
void
dxJointPU::getInfo2( dReal worldFPS, dReal worldERP, 
    int rowskip, dReal *J1, dReal *J2,
    int pairskip, dReal *pairRhsCfm, dReal *pairLoHi, 
    int *findex )
{
    const dReal k = worldFPS * worldERP;

    // ======================================================================
    // The angular constraint
    //
    dVector3 ax1, ax2; // Global axes of rotation
    getAxis(this, ax1, axis1);
    getAxis2(this,ax2, axis2);

    dVector3 uniPerp;  // Axis perpendicular to axes of rotation
    dCalcVectorCross3(uniPerp,ax1,ax2);
    dNormalize3( uniPerp );

    dCopyVector3( J1 + GI2__JA_MIN, uniPerp );

    dxBody *body1 = node[1].body;

    if ( body1 ) {
        dCopyNegatedVector3( J2 + GI2__JA_MIN , uniPerp );
    }
    // Corrective velocity attempting to keep uni axes perpendicular
    dReal val = dCalcVectorDot3( ax1, ax2 );
    // Small angle approximation : 
    // theta = asin(val)
    // theta is approximately val when val is near zero.
    pairRhsCfm[GI2_RHS] = -k * val; 
    
    // ==========================================================================
    // Handle axes orthogonal to the prismatic 
    dVector3 an1, an2; // Global anchor positions
    dVector3 axP, sep; // Prismatic axis and separation vector
    getAnchor(this, an1, anchor1);
    getAnchor2(this, an2, anchor2);

    if (flags & dJOINT_REVERSE) {
        getAxis2(this, axP, axisP1);
    } else {
        getAxis(this, axP, axisP1);
    }
    dSubtractVectors3(sep, an2, an1);

    dVector3 p, q;
    dPlaneSpace(axP, p, q);

    dCopyVector3( J1 + rowskip + GI2__JL_MIN, p );
    dCopyVector3( J1 + 2 * rowskip + GI2__JL_MIN, q );
    // Make the anchors be body local
    // Aliasing isn't a problem here.
    dSubtractVectors3(an1, an1, node[0].body->posr.pos);
    dCalcVectorCross3( J1 + rowskip + GI2__JA_MIN, an1, p );
    dCalcVectorCross3( J1 + 2 * rowskip + GI2__JA_MIN, an1, q );

    if (body1) {
        dCopyNegatedVector3( J2 + rowskip + GI2__JL_MIN, p );
        dCopyNegatedVector3( J2 + 2 * rowskip + GI2__JL_MIN, q );
        dSubtractVectors3(an2, an2, body1->posr.pos);
        dCalcVectorCross3( J2 + rowskip + GI2__JA_MIN, p, an2 );
        dCalcVectorCross3( J2 + 2 * rowskip + GI2__JA_MIN, q, an2 );
    }

    pairRhsCfm[pairskip + GI2_RHS] = k * dCalcVectorDot3( p, sep );
    pairRhsCfm[2 * pairskip + GI2_RHS] = k * dCalcVectorDot3( q, sep );
    
    // ==========================================================================
    // Handle the limits/motors
    int currRowSkip = 3 * rowskip, currPairSkip = 3 * pairskip;

    if (limot1.addLimot( this, worldFPS, J1 + currRowSkip, J2 + currRowSkip, pairRhsCfm + currPairSkip, pairLoHi + currPairSkip, ax1, 1 )) {
        currRowSkip += rowskip; currPairSkip += pairskip;
    }

    if (limot2.addLimot( this, worldFPS, J1 + currRowSkip, J2 + currRowSkip, pairRhsCfm + currPairSkip, pairLoHi + currPairSkip, ax2, 1 )) {
        currRowSkip += rowskip; currPairSkip += pairskip;
    }

    if (  body1 || (flags & dJOINT_REVERSE) == 0 ) {
        limotP.addTwoPointLimot( this, worldFPS, J1 + currRowSkip, J2 + currRowSkip, pairRhsCfm + currPairSkip, pairLoHi + currPairSkip, axP, an1, an2 );
    } else {
        dNegateVector3(axP);
        limotP.addTwoPointLimot ( this, worldFPS, J1 + currRowSkip, J2 + currRowSkip, pairRhsCfm + currPairSkip, pairLoHi + currPairSkip, axP, an1, an2  );
    }
}
void PhysicsPistonJoint::changed(ConstFieldMaskArg whichField, 
                            UInt32            origin,
                            BitVector         details)
{
    if(whichField & WorldFieldMask)
    {
        if(_JointID)
        {
            dJointDestroy(_JointID);
            _JointID = dJointCreatePiston(getWorld()->getWorldID(), 0);
        }
        else
        {
            _JointID = dJointCreatePiston(getWorld()->getWorldID(), 0);
            if(!(whichField & HiStopFieldMask))
            {
                setHiStop(dJointGetPistonParam(_JointID,dParamHiStop));
            }
            if(!(whichField & LoStopFieldMask))
            {
                setLoStop(dJointGetPistonParam(_JointID,dParamLoStop));
            }
            if(!(whichField & BounceFieldMask))
            {
                setBounce(dJointGetPistonParam(_JointID,dParamBounce));
            }
            if(!(whichField & CFMFieldMask))
            {
                setCFM(dJointGetPistonParam(_JointID,dParamCFM));
            }
            if(!(whichField & StopCFMFieldMask))
            {
                setStopCFM(dJointGetPistonParam(_JointID,dParamStopCFM));
            }
            if(!(whichField & StopERPFieldMask))
            {
                setStopERP(dJointGetPistonParam(_JointID,dParamStopERP));
            }
            if(!(whichField & HiStop2FieldMask))
            {
                setHiStop2(dJointGetPistonParam(_JointID,dParamHiStop2));
            }
            if(!(whichField & LoStop2FieldMask))
            {
                setLoStop2(dJointGetPistonParam(_JointID,dParamLoStop2));
            }
            if(!(whichField & Bounce2FieldMask))
            {
                setBounce2(dJointGetPistonParam(_JointID,dParamBounce2));
            }
            if(!(whichField & CFM2FieldMask))
            {
                setCFM2(dJointGetPistonParam(_JointID,dParamCFM2));
            }
            if(!(whichField & StopCFM2FieldMask))
            {
                setStopCFM2(dJointGetPistonParam(_JointID,dParamStopCFM2));
            }
            if(!(whichField & StopERP2FieldMask))
            {
                setStopERP2(dJointGetPistonParam(_JointID,dParamStopERP2));
            }
        }
    }

    Inherited::changed(whichField, origin, details);

    if((whichField & AnchorFieldMask) || (whichField & WorldFieldMask))
    {
	    dJointSetPistonAnchor(_JointID, getAnchor().x(), getAnchor().y(), getAnchor().z());
    }
    if((whichField & AxisFieldMask) || (whichField & WorldFieldMask))
    {
	    dJointSetPistonAxis(_JointID, getAxis().x(), getAxis().y(), getAxis().z());
    }
    if((whichField & HiStopFieldMask) || (whichField & WorldFieldMask))
    {
        dJointSetPistonParam(_JointID,  dParamHiStop, getHiStop());
    }
    if((whichField & LoStopFieldMask) || (whichField & WorldFieldMask))
    {
        dJointSetPistonParam(_JointID,  dParamLoStop, getLoStop());
    }
    if((whichField & BounceFieldMask) || (whichField & WorldFieldMask))
    {
        dJointSetPistonParam(_JointID,  dParamBounce, getBounce());
    }
    if((whichField & CFMFieldMask) || (whichField & WorldFieldMask))
    {
        dJointSetPistonParam(_JointID,  dParamCFM, getCFM());
    }
    if((whichField & StopERPFieldMask) || (whichField & WorldFieldMask))
    {
        dJointSetPistonParam(_JointID,  dParamStopERP, getStopERP());
    }
    if((whichField & StopCFMFieldMask) || (whichField & WorldFieldMask))
    {
        dJointSetPistonParam(_JointID,  dParamStopCFM, getStopCFM());
    }
    if((whichField & HiStop2FieldMask) || (whichField & WorldFieldMask))
    {
        dJointSetPistonParam(_JointID,  dParamHiStop2, getHiStop2());
    }
    if((whichField & LoStop2FieldMask) || (whichField & WorldFieldMask))
    {
        dJointSetPistonParam(_JointID,  dParamLoStop2, getLoStop2());
    }
    if((whichField & Bounce2FieldMask) || (whichField & WorldFieldMask))
    {
        dJointSetPistonParam(_JointID,  dParamBounce2, getBounce2());
    }
    if((whichField & CFM2FieldMask) || (whichField & WorldFieldMask))
    {
        dJointSetPistonParam(_JointID,  dParamCFM2, getCFM2());
    }
    if((whichField & StopERP2FieldMask) || (whichField & WorldFieldMask))
    {
        dJointSetPistonParam(_JointID,  dParamStopERP2, getStopERP2());
    }
    if((whichField & StopCFM2FieldMask) || (whichField & WorldFieldMask))
    {
        dJointSetPistonParam(_JointID,  dParamStopCFM2, getStopCFM2());
    }
}
Esempio n. 19
0
File: pu.cpp Progetto: JohnCrash/ode
void
dxJointPU::getInfo2( dReal worldFPS, dReal worldERP, const Info2Descr *info )
{
    const int s1 = info->rowskip;
    const int s2 = 2 * s1;
    const dReal k = worldFPS * worldERP;

    // ======================================================================
    // The angular constraint
    //
    dVector3 ax1, ax2; // Global axes of rotation
    getAxis(this, ax1, axis1);
    getAxis2(this,ax2, axis2);

    dVector3 uniPerp;  // Axis perpendicular to axes of rotation
    dCalcVectorCross3(uniPerp,ax1,ax2);
    dNormalize3( uniPerp );
    dCopyVector3( info->J1a , uniPerp );
    if ( node[1].body )
    {
        dCopyNegatedVector3( info->J2a , uniPerp );
    }
    // Corrective velocity attempting to keep uni axes perpendicular
    dReal val = dCalcVectorDot3( ax1, ax2 );
    // Small angle approximation : 
    // theta = asin(val)
    // theta is approximately val when val is near zero.
    info->c[0] = -k * val; 
    
    // ==========================================================================
    // Handle axes orthogonal to the prismatic 
    dVector3 an1, an2; // Global anchor positions
    dVector3 axP, sep; // Prismatic axis and separation vector
    getAnchor(this,an1,anchor1);
    getAnchor2(this,an2,anchor2);
    if (flags & dJOINT_REVERSE) {
        getAxis2(this, axP, axisP1);
    } else {
        getAxis(this, axP, axisP1);
    }
    dSubtractVectors3(sep,an2,an1);

    dVector3 p,q;
    dPlaneSpace(axP,p,q);

    dCopyVector3(( info->J1l ) + s1, p );
    dCopyVector3(( info->J1l ) + s2, q );
    // Make the anchors be body local
    // Aliasing isn't a problem here.
    dSubtractVectors3(an1,an1,node[0].body->posr.pos);
    dCalcVectorCross3(( info->J1a ) + s1, an1, p );
    dCalcVectorCross3(( info->J1a ) + s2, an1, q );

    if (node[1].body) {
        dCopyNegatedVector3(( info->J2l ) + s1, p );
        dCopyNegatedVector3(( info->J2l ) + s2, q );
        dSubtractVectors3(an2,an2,node[1].body->posr.pos);
        dCalcVectorCross3(( info->J2a ) + s1, p, an2 );
        dCalcVectorCross3(( info->J2a ) + s2, q, an2 );
    }

    info->c[1] = k * dCalcVectorDot3( p, sep );
    info->c[2] = k * dCalcVectorDot3( q, sep );
    
    // ==========================================================================
    // Handle the limits/motors
    int row = 3 + limot1.addLimot( this, worldFPS, info, 3, ax1, 1 );
    row += limot2.addLimot( this, worldFPS, info, row, ax2, 1 );

    if (  node[1].body || !(flags & dJOINT_REVERSE) )
        limotP.addTwoPointLimot( this, worldFPS, info, row, axP, an1, an2 );
    else
    {
        axP[0] = -axP[0];
        axP[1] = -axP[1];
        axP[2] = -axP[2];
        limotP.addTwoPointLimot ( this, worldFPS, info, row, axP, an1, an2  );
    }
}
void PhysicsHingeJoint::changed(ConstFieldMaskArg whichField, 
                            UInt32            origin,
                            BitVector         details)
{
    //Do not respond to changes that have a Sync origin
    if(origin & ChangedOrigin::Sync)
    {
        return;
    }

    if(whichField & WorldFieldMask)
    {
        if(_JointID)
        {
            dJointDestroy(_JointID);
            _JointID = dJointCreateHinge(getWorld()->getWorldID(), 0);
        }
        else
        {
            _JointID = dJointCreateHinge(getWorld()->getWorldID(), 0);
            if(!(whichField & HiStopFieldMask))
            {
                setHiStop(dJointGetHingeParam(_JointID,dParamHiStop));
            }
            if(!(whichField & LoStopFieldMask))
            {
                setLoStop(dJointGetHingeParam(_JointID,dParamLoStop));
            }
            if(!(whichField & BounceFieldMask))
            {
                setBounce(dJointGetHingeParam(_JointID,dParamBounce));
            }
            if(!(whichField & CFMFieldMask))
            {
                setCFM(dJointGetHingeParam(_JointID,dParamCFM));
            }
            if(!(whichField & StopCFMFieldMask))
            {
                setStopCFM(dJointGetHingeParam(_JointID,dParamStopCFM));
            }
            if(!(whichField & StopERPFieldMask))
            {
                setStopERP(dJointGetHingeParam(_JointID,dParamStopERP));
            }
        }
    }

    Inherited::changed(whichField, origin, details);

    if((whichField & AnchorFieldMask) || (whichField & WorldFieldMask))
    {
	    dJointSetHingeAnchor(_JointID, getAnchor().x(), getAnchor().y(), getAnchor().z());
    }
    if((whichField & AxisFieldMask) || (whichField & WorldFieldMask))
    {
	    dJointSetHingeAxis(_JointID, getAxis().x(), getAxis().y(), getAxis().z());
    }
    if((whichField & HiStopFieldMask) || (whichField & WorldFieldMask))
    {
        dJointSetHingeParam(_JointID,  dParamHiStop, getHiStop());
    }
    if((whichField & LoStopFieldMask) || (whichField & WorldFieldMask))
    {
        dJointSetHingeParam(_JointID,  dParamLoStop, getLoStop());
    }
    if((whichField & BounceFieldMask) || (whichField & WorldFieldMask))
    {
        dJointSetHingeParam(_JointID,  dParamBounce, getBounce());
    }
    if((whichField & CFMFieldMask) || (whichField & WorldFieldMask))
    {
        dJointSetHingeParam(_JointID,  dParamCFM, getCFM());
    }
    if((whichField & StopERPFieldMask) || (whichField & WorldFieldMask))
    {
        dJointSetHingeParam(_JointID,  dParamStopERP, getStopERP());
    }
    if((whichField & StopCFMFieldMask) || (whichField & WorldFieldMask))
    {
        dJointSetHingeParam(_JointID,  dParamStopCFM, getStopCFM());
    }
}