//-----------------------------------------------------------------------
	OpcodeCollisionBoundingBoxShape::~OpcodeCollisionBoundingBoxShape()
	{
		// ½â¾öÄÚ´æй©
		OGRE_DELETE(mMeshInterface);
		OGRE_DELETE(mCollisionModel);
		if(mAutoDeleteIndexList)
		{
			OGRE_DELETE_ARRAY(mIndexList);
		}
		if(mAutoDeleteVertexList)
		{
			OGRE_DELETE_ARRAY(mVertexList);
		}
	}
Beispiel #2
0
	//-----------------------------------------------------------------------
	bool ConvexBody::operator == ( const ConvexBody& rhs ) const
	{
		if ( getPolygonCount() != rhs.getPolygonCount() )
			return false;

		// Compare the polygons. They may not be in correct order.
		// A correct convex body does not have identical polygons in its body.
		bool *bChecked = new bool[ getPolygonCount() ];
		for ( size_t i=0; i<getPolygonCount(); ++i )
		{
			bChecked[ i ] = false;
		}

		for ( size_t i=0; i<getPolygonCount(); ++i )
		{
			bool bFound = false;

			for ( size_t j=0; j<getPolygonCount(); ++j )
			{
				const Polygon& pA = getPolygon( i );
				const Polygon& pB = rhs.getPolygon( j );

				if ( pA == pB )
				{
					bFound = true;
					bChecked[ i ] = true;
					break;
				}
			}

			if ( bFound == false )
			{
				OGRE_DELETE_ARRAY( bChecked );
				return false;
			}
		}

		for ( size_t i=0; i<getPolygonCount(); ++i )
		{
			if ( bChecked[ i ] != true )
			{
				OGRE_DELETE_ARRAY( bChecked );
				return false;
			}
		}

		OGRE_DELETE_ARRAY( bChecked );
		return true;
	}
	GridDecal::~GridDecal()
	{
		OGRE_DELETE_ARRAY(m_gridPositions);
		if(m_decal)
		{
			m_sceneMgr->destroyManualObject(m_decal);
			m_decal = 0;
		}
	}
	// 当属性改变了,需要重构贴花的时候
	void GridDecal::updateDecal()
	{
#define WIDTH_POS_COUNT (m_widthGridCount + 1)
#define HEIGHT_POS_COUNT (m_heightGridCount + 1)
		// 显示整个节点
		m_node->setVisible(m_visible);
		// 不可视就不更新了
		if(!m_visible)
		{
			return;
		}
		// 错误数据检查
		if(m_heightGridCount == 0 || m_widthGridCount == 0)
			return;
		// 如果网格大小改变了,就重构
		if((m_dirty & (GRID_DECAL_DIRTY_WIDTH_GRID_COUNT
			| GRID_DECAL_DIRTY_HEIGHT_GRID_COUNT))
			|| m_gridPositions == 0
			)
		{
			OGRE_DELETE_ARRAY(m_gridPositions);
			m_gridPositions = new Vector3[WIDTH_POS_COUNT * HEIGHT_POS_COUNT];
			memset(m_gridPositions , 0 , sizeof(Vector3) * WIDTH_POS_COUNT * HEIGHT_POS_COUNT);
		}

		// 位置、深度、大小会导致平面重新定义
		if(m_dirty & (DIRTY_POSITION
			| DIRTY_DEPTH
			| DIRTY_SIZE
			| GRID_DECAL_DIRTY_WIDTH_GRID_COUNT
			| GRID_DECAL_DIRTY_HEIGHT_GRID_COUNT)
			)
		{
			for(uint y = 0 ; y < WIDTH_POS_COUNT ; y ++)
			{
				for(uint x = 0 ; x < HEIGHT_POS_COUNT ; x ++)
				{
					// 找到与地形相交的点
					if(!IDecalSystem::getSingleton().worldRayQuery(m_gridPositions[y * WIDTH_POS_COUNT + x]
						, m_position + Vector3(m_size.x * ((float)x / (float)WIDTH_POS_COUNT) - m_size.x / 2.0f , m_depth , m_size.y * ((float)y / (float)HEIGHT_POS_COUNT) - m_size.y / 2.0f)
						, m_position + Vector3(m_size.x * ((float)x / (float)WIDTH_POS_COUNT) - m_size.x / 2.0f , -m_depth , m_size.y * ((float)y / (float)HEIGHT_POS_COUNT) - m_size.y / 2.0f)
						)
						)
					{
						return;
					}
					// 移动到相对位置
					m_gridPositions[y * WIDTH_POS_COUNT + x] -= m_position;
				}
			}
			// 从三点定义贴花平面
			m_decalPlane.redefine(m_gridPositions[WIDTH_POS_COUNT / 2]
								, m_gridPositions[WIDTH_POS_COUNT * (HEIGHT_POS_COUNT - 1)]
								, m_gridPositions[WIDTH_POS_COUNT * HEIGHT_POS_COUNT - 1]
								);
		}

		// 改变节点位置
		if(m_dirty & DIRTY_POSITION)
		{
			m_node->setPosition(m_position);
		}

		// 材质名和大小会影响贴花对象的重构
		if(m_dirty & (DIRTY_POSITION
			| DIRTY_DEPTH
			| DIRTY_MATERIAL_NAME
			| DIRTY_SIZE
			| GRID_DECAL_DIRTY_WIDTH_GRID_COUNT
			| GRID_DECAL_DIRTY_HEIGHT_GRID_COUNT)
			)
		{
			// 材质贴花
			if(!m_materialName.empty())
			{
				// 创建贴花对象
				if(m_decal == 0)
				{
					m_decal = m_sceneMgr->createManualObject(m_name + "_GridDecal");
					m_decal->setDynamic(true);
					m_decal->begin(m_materialName);
					m_decal->position(Vector3::ZERO);
					m_decal->textureCoord(0,0);
					m_decal->index(0);
					m_decal->end();
					// 贴花在地形之后,物件之前
					m_decal->setRenderQueueGroup(RENDER_QUEUE_DECAL);
					attachObject(m_decal);
				}

				// 设置材质
				if(m_dirty & DIRTY_MATERIAL_NAME)
				{
					m_decal->getSection(0)->setMaterialName(m_materialName);
				}
				// 更新顶点
				if(m_dirty & (DIRTY_POSITION
					| DIRTY_DEPTH
					| DIRTY_SIZE
					| GRID_DECAL_DIRTY_WIDTH_GRID_COUNT
					| GRID_DECAL_DIRTY_HEIGHT_GRID_COUNT)
					)
				{
					m_decal->beginUpdate(0);
					// 生成所有顶点
					for(uint y = 0 ; y < HEIGHT_POS_COUNT ; y ++)
					{
						for(uint x = 0 ; x < WIDTH_POS_COUNT ; x ++)
						{
							m_decal->position(m_gridPositions[y * WIDTH_POS_COUNT + x]);
							m_decal->textureCoord((float)x / (float)WIDTH_POS_COUNT
								, (float)y / (float)HEIGHT_POS_COUNT);
						}
					}
					// 根据顶点生成索引缓冲区
					for(uint y = 0 ; y < m_heightGridCount ; y ++)
					{
						for(uint x = 0 ; x < m_widthGridCount ; x ++)
						{
							uint tl = y * WIDTH_POS_COUNT + x;
							uint tr = y * WIDTH_POS_COUNT + x + 1;
							uint bl = (y + 1) * WIDTH_POS_COUNT + x;
							uint br = (y + 1) * WIDTH_POS_COUNT + x + 1;
							m_decal->quad(tl
								, bl
								, br
								, tr
								);
						}
					}
					
					m_decal->end();
				}
			}
			else
			{
				if(m_decal)
				{
					m_sceneMgr->destroyManualObject(m_decal);
					m_decal = 0;
				}
			}
		}

		// 改变附加对象的节点旋转
		if(m_nodeAttachObject)
		{
			// 位置信息改变才需要重新设置
			if(m_dirty & (DIRTY_POSITION
				| DIRTY_DEPTH
				| DIRTY_SIZE
				| DIRTY_OFFSET)
				)
			{
				m_nodeAttachObject->setPosition(m_offsetPosition);
			}
		}
	}
Beispiel #5
0
	//-----------------------------------------------------------------------
	void ConvexBody::clip( const Plane& pl, bool keepNegative )
	{
		if ( getPolygonCount() == 0 )
			return;

		// current will be used as the reference body
		ConvexBody current;
		current.moveDataFromBody(*this);
		
		OgreAssert( this->getPolygonCount() == 0, "Body not empty!" );
		OgreAssert( current.getPolygonCount() != 0, "Body empty!" );

		// holds all intersection edges for the different polygons
		Polygon::EdgeMap intersectionEdges;

		// clip all polygons by the intersection plane
		// add only valid or intersected polygons to *this
		for ( size_t iPoly = 0; iPoly < current.getPolygonCount(); ++iPoly )
		{

			// fetch vertex count and ignore polygons with less than three vertices
			// the polygon is not valid and won't be added
			const size_t vertexCount = current.getVertexCount( iPoly );
			if ( vertexCount < 3 )
				continue;

			// current polygon
			const Polygon& p = current.getPolygon( iPoly );

			// the polygon to assemble
			Polygon *pNew = allocatePolygon();

			// the intersection polygon (indeed it's an edge or it's empty)
			Polygon *pIntersect = allocatePolygon();
			
			// check if polygons lie inside or outside (or on the plane)
			// for each vertex check where it is situated in regard to the plane
			// three possibilities appear:
			Plane::Side clipSide = keepNegative ? Plane::POSITIVE_SIDE : Plane::NEGATIVE_SIDE;
			// - side is clipSide: vertex will be clipped
			// - side is !clipSide: vertex will be untouched
			// - side is NOSIDE:   vertex will be untouched
			Plane::Side *side = new Plane::Side[ vertexCount ];
			for ( size_t iVertex = 0; iVertex < vertexCount; ++iVertex )
			{
				side[ iVertex ] = pl.getSide( p.getVertex( iVertex ) );
			}

			// now we check the side combinations for the current and the next vertex
			// four different combinations exist:
			// - both points inside (or on the plane): keep the second (add it to the body)
			// - both points outside: discard both (don't add them to the body)
			// - first vertex is inside, second is outside: add the intersection point
			// - first vertex is outside, second is inside: add the intersection point, then the second
			for ( size_t iVertex = 0; iVertex < vertexCount; ++iVertex )
			{
				// determine the next vertex
				size_t iNextVertex = ( iVertex + 1 ) % vertexCount;

				const Vector3& vCurrent = p.getVertex( iVertex );
				const Vector3& vNext    = p.getVertex( iNextVertex );

				// case 1: both points inside (store next)
				if ( side[ iVertex ]     != clipSide &&		// NEGATIVE or NONE
					 side[ iNextVertex ] != clipSide )		// NEGATIVE or NONE
				{
					// keep the second
					pNew->insertVertex( vNext );
				}

				// case 3: inside -> outside (store intersection)
				else if ( side[ iVertex ]		!= clipSide &&
						  side[ iNextVertex ]	== clipSide )
				{
					// Do an intersection with the plane. We use a ray with a start point and a direction.
					// The ray is forced to hit the plane with any option available (eigher current or next
					// is the starting point)

					// intersect from the outside vertex towards the inside one
					Vector3 vDirection = vCurrent - vNext;
					vDirection.normalise();
					Ray ray( vNext, vDirection );
					std::pair< bool, Real > intersect = ray.intersects( pl );

					// store intersection
					if ( intersect.first )
					{
						// convert distance to vector
						Vector3 vIntersect = ray.getPoint( intersect.second );	

						// store intersection
						pNew->insertVertex( vIntersect );
						pIntersect->insertVertex( vIntersect );
					}
				}

				// case 4: outside -> inside (store intersection, store next)
				else if ( side[ iVertex ]		== clipSide &&
					side[ iNextVertex ]			!= clipSide )
				{
					// Do an intersection with the plane. We use a ray with a start point and a direction.
					// The ray is forced to hit the plane with any option available (eigher current or next
					// is the starting point)

					// intersect from the outside vertex towards the inside one
					Vector3 vDirection = vNext - vCurrent;
					vDirection.normalise();
					Ray ray( vCurrent, vDirection );
					std::pair< bool, Real > intersect = ray.intersects( pl );

					// store intersection
					if ( intersect.first )
					{
						// convert distance to vector
						Vector3 vIntersect = ray.getPoint( intersect.second );

						// store intersection
						pNew->insertVertex( vIntersect );
						pIntersect->insertVertex( vIntersect );
					}

					pNew->insertVertex( vNext );

				}
				// else:
				// case 2: both outside (do nothing)
					
			}

			// insert the polygon only, if at least three vertices are present
			if ( pNew->getVertexCount() >= 3 )
			{
				// in case there are double vertices, remove them
				pNew->removeDuplicates();

				// in case there are still at least three vertices, insert the polygon
				if ( pNew->getVertexCount() >= 3 )
				{
					this->insertPolygon( pNew );
				}
				else
				{
					// delete pNew because it's empty or invalid
					freePolygon(pNew);
					pNew = 0;
				}
			}
			else
			{
				// delete pNew because it's empty or invalid
				freePolygon(pNew);
				pNew = 0;
			}

			// insert intersection polygon only, if there are two vertices present
			if ( pIntersect->getVertexCount() == 2 )
			{
				intersectionEdges.insert( Polygon::Edge( pIntersect->getVertex( 0 ),
														  pIntersect->getVertex( 1 ) ) );
			}

			// delete intersection polygon
			// vertices were copied (if there were any)
			freePolygon(pIntersect);
			pIntersect = 0;

			// delete side info
			OGRE_DELETE_ARRAY( side );
		}

		// if the polygon was partially clipped, close it
		// at least three edges are needed for a polygon
		if ( intersectionEdges.size() >= 3 )
		{
			Polygon *pClosing = allocatePolygon();

			// Analyze the intersection list and insert the intersection points in ccw order
			// Each point is twice in the list because of the fact that we have a convex body
			// with convex polygons. All we have to do is order the edges (an even-odd pair)
			// in a ccw order. The plane normal shows us the direction.
			Polygon::EdgeMap::iterator it = intersectionEdges.begin();

			// check the cross product of the first two edges
			Vector3 vFirst  = it->first;
			Vector3 vSecond = it->second;

			// remove inserted edge
			intersectionEdges.erase( it );

			Vector3 vNext;

			// find mating edge
			if (findAndEraseEdgePair(vSecond, intersectionEdges, vNext))
			{
				// detect the orientation
				// the polygon must have the same normal direction as the plane and then n
				Vector3 vCross = ( vFirst - vSecond ).crossProduct( vNext - vSecond );
				bool frontside = ( pl.normal ).directionEquals( vCross, Degree( 1 ) );

				// first inserted vertex
				Vector3 firstVertex;
				// currently inserted vertex
				Vector3 currentVertex;
				// direction equals -> front side (walk ccw)
				if ( frontside )
				{
					// start with next as first vertex, then second, then first and continue with first to walk ccw
					pClosing->insertVertex( vNext );
					pClosing->insertVertex( vSecond );
					pClosing->insertVertex( vFirst );
					firstVertex		= vNext;
					currentVertex	= vFirst;

				#ifdef _DEBUG_INTERSECTION_LIST
					std::cout << "Plane: n=" << pl.normal << ", d=" << pl.d << std::endl;
					std::cout << "First inserted vertex: " << *next << std::endl;
					std::cout << "Second inserted vertex: " << *vSecond << std::endl;
					std::cout << "Third inserted vertex: " << *vFirst << std::endl;
				#endif
				}
				// direction does not equal -> back side (walk cw)
				else
				{
					// start with first as first vertex, then second, then next and continue with next to walk ccw
					pClosing->insertVertex( vFirst );
					pClosing->insertVertex( vSecond );
					pClosing->insertVertex( vNext );
					firstVertex		= vFirst;
					currentVertex	= vNext;

					#ifdef _DEBUG_INTERSECTION_LIST
						std::cout << "Plane: n=" << pl.normal << ", d=" << pl.d << std::endl;
						std::cout << "First inserted vertex: " << *vFirst << std::endl;
						std::cout << "Second inserted vertex: " << *vSecond << std::endl;
						std::cout << "Third inserted vertex: " << *next << std::endl;
					#endif
				}

				// search mating edges that have a point in common
				// continue this operation as long as edges are present
				while ( !intersectionEdges.empty() )
				{

					if (findAndEraseEdgePair(currentVertex, intersectionEdges, vNext))
					{
						// insert only if it's not the last (which equals the first) vertex
						if ( !intersectionEdges.empty() )
						{
							currentVertex = vNext;
							pClosing->insertVertex( vNext );
						}
					}
					else
					{
						// degenerated...
						break;
					}

				} // while intersectionEdges not empty

				// insert polygon (may be degenerated!)
				this->insertPolygon( pClosing );

			}
			// mating intersection edge NOT found!
			else
			{
				freePolygon(pClosing);
			}

		} // if intersectionEdges contains more than three elements
	}