int GetCellIndex(const Vec3f &aPoint) const
    {
        const Vec3f distMin = aPoint - mBBoxMin;

        const Vec3f coordF(
            std::floor(mInvCellSize * distMin.x),
            std::floor(mInvCellSize * distMin.y),
            std::floor(mInvCellSize * distMin.z));

        const Vec3i coordI  = Vec3i(int(coordF.x), int(coordF.y), int(coordF.z));

        return GetCellIndex(coordI);
    }
void GridModel::UpdateGrid()
{
	unsigned int i, j;
	unsigned int index = 0;
	unsigned int x,y,z;

	bool not_dirty;
	for( i = 0; i < _modified_chunks.size(); i++ )//bad
	{
		not_dirty = true;
		for( j = 0; j < _dirty_chunks.size(); j++ )
		{
			if ( _dirty_chunks[j] == _modified_chunks[i] )
			{
				not_dirty = false;
				break;
			}
		}

		if (not_dirty)
			_modified_chunks[i]->RecalcColor( _cells, dimm );
	
	}

	_modified_chunks.clear();

	for( i = 0; i < _dirty_chunks.size(); i++ )
	{
		index = GetCellIndex( (_dirty_chunks[i]->GetCenter() ), x, y, z);
				
		_dirty_chunks[i]->CreateMesh( _cells, _interacted, dimm );
		if ( _dirty_chunks[i]->GetVAO() != NULL )// If mesh creating was successfull.
		{
			_renderable_chunks[index] = _dirty_chunks[i]->GetVAO();			
			_modified_chunks.push_back(_dirty_chunks[i]);
		}
		else
			_renderable_chunks.erase( index );
	}

	_dirty_chunks.clear();
}
Exemple #3
0
void CUniformGrid::AddBody(CGameNode * node)
{
	const int CurrentIndex = node->GetGridIndex();
	const int NewIndex = GetCellIndex(node->GetPosition());

	if (-1 != CurrentIndex)
	{
		if (NewIndex == CurrentIndex)
		{
			// Nothing to do, already in right place
			return;
		}
		else
		{
			// Got this unit but in wrong cell, so remove first
			RemoveBody(node);
		}
	}

	m_GridArray[NewIndex].push_back(node);
	node->SetGridIndex(NewIndex);
}
GridModel::GridModel( int power )
{
	dimm = 1<<power; //grid dimension
	size = dimm*dimm*dimm;//total size
	half_dimm = dimm>>1;
	_cells = new UINT8[size];//cells - voxels.
	_interacted = new bool[size];//array to store bool - if voxel was changed during this frame.
	memset( _interacted, 0, size*sizeof(bool) );

	power_for_chunk = max( unsigned(power-4), unsigned(4) );//chunk_size
	unsigned int _chunk_power = power - power_for_chunk;
	chunk_dimm = 1<<_chunk_power;//dimension for array of chunk
	chunk_size = chunk_dimm*chunk_dimm*chunk_dimm;
	_chunks = new VoxelChunk*[chunk_size];

	internal_chunk_size = 1<<power_for_chunk;//internal chunk size, dimm == chunk_dimm*internal_chunk_size

	Point center;//center of voxel is always (+-xx.5, +-yy.5, +-zz.5)

	int iter = 0;
	unsigned int tmp1, tmp2, tmp3;
	float radius = 0.0f;
	for (  int i = 0; i < dimm; i++ )
	{
		center.coord[0] = float(i - half_dimm);//well, but not here =)
		for (  int j = 0; j < dimm; j++ )
		{
			center.coord[1] = float(j - half_dimm);
			for (  int k = 0; k < dimm; k++ )
			{
				center.coord[2] = float(k - half_dimm);
				iter = i*dimm*dimm+ j*dimm+ k;

				_cells[iter] = 0;
				radius = sqrtf(  center.coord[0]*center.coord[0] + center.coord[1]*center.coord[1] + center.coord[2]*center.coord[2]);
				if ( radius < dimm/2 - 1 )
					_cells[iter] = 255;
				//floating_rock(i, j, k, _cells, dimm);
				if ( iter != GetCellIndex(center, tmp1, tmp2, tmp3) )
				{
					std::cout<<"Error!";
				}
			}
		}
	}

	int tmp_lbl[3];
	int tmp_ufr[3];
	float _h_s = float(internal_chunk_size>>1);
	for (  int i = 0; i < chunk_dimm; i++ )
	{
		tmp_lbl[0] = int(i<<power_for_chunk) - int(dimm/2);
		center.coord[0] = float(tmp_lbl[0]) + _h_s;//but here it is
		tmp_ufr[0] = tmp_lbl[0] + internal_chunk_size;
		for (  int j = 0; j < chunk_dimm; j++ )
		{
			tmp_lbl[1] = int(j<<power_for_chunk) - int(dimm/2);
			center.coord[1] = float(tmp_lbl[1]) + _h_s;
			tmp_ufr[1] = tmp_lbl[1] + internal_chunk_size;
			for (  int k = 0; k < chunk_dimm; k++ )
			{
				tmp_lbl[2] = int(k<<power_for_chunk) - int(dimm/2);
				center.coord[2] = float(tmp_lbl[2]) + _h_s;
				tmp_ufr[2] = tmp_lbl[2] + internal_chunk_size;

				iter = i*chunk_dimm*chunk_dimm+ j*chunk_dimm+ k;
				
				_chunks[ iter ] = new VoxelChunk( center, tmp_lbl, tmp_ufr );
				_chunks[ iter ]->MarkDirty();
				_dirty_chunks.push_back( _chunks[ iter ] );
			}
		}
	}

	/* init mutex*/
#ifdef USE_SPINLOCK
	pthread_spin_init(&spinlock, 0);
#else
	pthread_mutex_init(&mutex, NULL);
#endif
	
}
    void build(
        const tParticle* aParticles,
        uint32_t count,
        float aRadius)
    {
        mRadius      = aRadius;
        mRadiusSqr   = sqr(mRadius);
        mCellSize    = mRadius * 2.f;
        mInvCellSize = 1.f / mCellSize;

        mBBoxMin = Vec3f( 1e36f);
        mBBoxMax = Vec3f(-1e36f);
        // Build bounding box of the particiles
        for(size_t i=0; i<count; i++)
        {
            if(isValid(aParticles[i])) {
                const Vec3f &pos = getPosition(aParticles[i]);
                for(int j=0; j<3; j++)
                {
                    mBBoxMax[j] = std::max(mBBoxMax[j], pos[j]);
                    mBBoxMin[j] = std::min(mBBoxMin[j], pos[j]);
                }
            }
        }
        auto center = (mBBoxMin + mBBoxMax) / 2.f;
        // For numerical stability at the border of the scene:
        mBBoxMin = center + 1.1f * (mBBoxMin - center);
        mBBoxMax = center + 1.1f * (mBBoxMax - center);

        mIndices.resize(count);
        memset(&mCellEnds[0], 0, mCellEnds.size() * sizeof(int));

        // set mCellEnds[x] to number of particles within x
        for(size_t i=0; i<count; i++)
        {
            if(isValid(aParticles[i])) {
                const Vec3f &pos = getPosition(aParticles[i]);
                mCellEnds[GetCellIndex(pos)]++;
            }
        }

        // run exclusive prefix sum to really get the cell starts
        // mCellEnds[x] is now where the cell starts
        int sum = 0;
        for(size_t i=0; i<mCellEnds.size(); i++)
        {
            int temp = mCellEnds[i];
            mCellEnds[i] = sum;
            sum += temp;
        }

        for(size_t i=0; i<count; i++)
        {
            if(isValid(aParticles[i])) {
                const Vec3f &pos = getPosition(aParticles[i]);
                const int targetIdx = mCellEnds[GetCellIndex(pos)]++;
                mIndices[targetIdx] = int(i);
            }
        }

        // now mCellEnds[x] points to the index right after the last
        // element of cell x

        //// DEBUG
        //for(size_t i=0; i<aParticles.size(); i++)
        //{
        //    const Vec3f &pos  = aParticles[i].GetPosition();
        //    Vec2i range = GetCellRange(GetCellIndex(pos));
        //    bool found = false;
        //    for(;range.x < range.y; range.x++)
        //    {
        //        if(mIndices[range.x] == i)
        //            found = true;
        //    }
        //    if(!found)
        //        printf("Error at particle %d\n", i);
        //}
    }
    int process(
        const tParticle* aParticles,
        const Vec3f& queryPos,
        const tFunc& aFunc) const
    {
        const Vec3f distMin = queryPos - mBBoxMin;
        const Vec3f distMax = mBBoxMax - queryPos;
        for(int i=0; i<3; i++)
        {
            if(distMin[i] < 0.f || distMax[i] < 0.f) {
                return -1;
            }
        }

        const Vec3f cellPt = mInvCellSize * distMin;
        const Vec3f coordF(
            std::floor(cellPt.x),
            std::floor(cellPt.y),
            std::floor(cellPt.z));

        const int  px = int(coordF.x);
        const int  py = int(coordF.y);
        const int  pz = int(coordF.z);

        const Vec3f fractCoord = cellPt - coordF;

        const int  pxo = px + (fractCoord.x < 0.5f ? -1 : +1);
        const int  pyo = py + (fractCoord.y < 0.5f ? -1 : +1);
        const int  pzo = pz + (fractCoord.z < 0.5f ? -1 : +1);

        int found = 0;

        for(int j=0; j<8; j++)
        {
            Vec2i activeRange;
            switch(j)
            {
            case 0: activeRange = GetCellRange(GetCellIndex(Vec3i(px , py , pz ))); break;
            case 1: activeRange = GetCellRange(GetCellIndex(Vec3i(px , py , pzo))); break;
            case 2: activeRange = GetCellRange(GetCellIndex(Vec3i(px , pyo, pz ))); break;
            case 3: activeRange = GetCellRange(GetCellIndex(Vec3i(px , pyo, pzo))); break;
            case 4: activeRange = GetCellRange(GetCellIndex(Vec3i(pxo, py , pz ))); break;
            case 5: activeRange = GetCellRange(GetCellIndex(Vec3i(pxo, py , pzo))); break;
            case 6: activeRange = GetCellRange(GetCellIndex(Vec3i(pxo, pyo, pz ))); break;
            case 7: activeRange = GetCellRange(GetCellIndex(Vec3i(pxo, pyo, pzo))); break;
            }

            for(; activeRange.x < activeRange.y; activeRange.x++)
            {
                const int particleIndex   = mIndices[activeRange.x];
                const tParticle &particle = aParticles[particleIndex];

                const float distSqr =
                    sqr_length(queryPos - getPosition(particle));

                if(distSqr <= mRadiusSqr) {
                    aFunc(particle);
                    ++found;
                }
            }
        }
        return found;
    }
void CEmotionButton::DoEvent(TEventUI& event)
{
     switch( event.Type)
	 {
		 case UIEVENT_MOUSEMOVE:
		 {
				RECT rc1, rc2, invalidRect;
				int lastCol = -1, curCol = -1;

				unsigned char changetype = _PosChangeType::NoChange; //预览矩形是否需要改变

				POINT pt = event.ptMouse;
				int tmpSel = GetCellIndex(pt.x, pt.y);

				//是否超出了图片数量
				if((tmpSel + curPage * CELLCOUNT_PAGE) >= m_ImageCount)
					tmpSel = -1;

				if(tmpSel != curSel)
				{
					//两个cell 索引行进
					lastSel = curSel;
					curSel = tmpSel;
					curFrame = 0;

					//预览矩形需要移动吗?
					lastCol = (lastSel % 15);
					curCol = (curSel % 15); //每行15个

					GetBlueRect(lastSel, &rc1);
					GetBlueRect(curSel, &rc2);
					UnionRect(&invalidRect, &rc1, &rc2);
					invalidRect.right++;
					invalidRect.bottom++;

					//判断缩略矩形是否发生位置改变?
					if(pvstatus == _PVStatus::Hide)
					{
						if(curSel >= 0)
						{
							if((curSel%15) > 7)
							{
								pvstatus = _PVStatus::Left;
								changetype = _PosChangeType::HideToLeft;
							}
							else
							{
								pvstatus = _PVStatus::Right;
								changetype = _PosChangeType::HideToRight;
							}
						}
					}
					else if(pvstatus == _PVStatus::Left)
					{					
						if(curSel < 0)
						{
							pvstatus = _PVStatus::Hide;
							changetype = _PosChangeType::LeftToHide;
						}
						else if(curCol < 4 || (curCol == 4 && lastCol == 4))
						{
							pvstatus = _PVStatus::Right;
							changetype = _PosChangeType::LeftToRight;
						}
					}
					else if(pvstatus == _PVStatus::Right)
					{
						if(curSel < 0)
						{
							pvstatus = _PVStatus::Hide;
							changetype = _PosChangeType::RightToHide;
						}
						else if(curCol > 10 || (curCol == 10 && lastCol == 10))
						{
							pvstatus = _PVStatus::Left;
							changetype = _PosChangeType::RightToLeft;
						}
					}

					//刷新蓝色矩形框
					UpdateSelectedFace(curPage, curSel, curFrame, pvstatus);
					this->Invalidate();
					 
					
					if(changetype == _PosChangeType::NoChange)
					{
						//刷新预览图片
						if(pvstatus == _PVStatus::Left)
						{
							this->Invalidate();
							//InvalidateRect(hDlg, &rcLeft, FALSE);
						}
						else if(pvstatus == _PVStatus::Right)
						{
							this->Invalidate();
							//InvalidateRect(hDlg, &rcRight, FALSE);
						}

					}
					else
					{
						CopyRect(&rc1, &rcLeft);
						CopyRect(&rc2, &rcRight);
						rc1.right++;
						rc1.bottom++;
						rc2.right++;
						rc2.bottom++; 

						//擦除原位置的缩略图
						switch(changetype & 0xf0)
						{
						case 0x00:
							break;
						case 0x10:
							this->Invalidate();
							//InvalidateRect(hDlg, &rc1, FALSE);
							break;
						case 0x20:
							this->Invalidate();
							//InvalidateRect(hDlg, &rc2, FALSE);
							break;
						}
						//显示新位置上的缩略图
						switch(changetype & 0x0f)
						{
						case 0x00:
							pvstatus == _PVStatus::Hide;
							break;
						case 0x01:
							this->Invalidate();
							//InvalidateRect(hDlg, &rc1, FALSE);
							break;
						case 0x02:
							this->Invalidate();
							//InvalidateRect(hDlg, &rc2, FALSE);
							break;
						}
					}

					//安装定时器(显示动画)
					if(curSel >= 0)
					{
						UINT frameDelay = 200;
						CxImage* pImg = GetSelectedImage(curPage, curSel);
						CxImage* pFrame = pImg->GetFrame(curFrame);

						//QQ表情的帧延时通常是10毫秒,显示速度过快,因此增大到50毫秒
						if(pFrame != NULL) frameDelay = max(frameDelay, pFrame->GetFrameDelay());

						frameCount = pImg->GetNumFrames();
 
						this->m_pManager->SetTimer(this, TIMER_SHOWGIF, frameDelay);
					}
					else
					{ 
						this->m_pManager->KillTimer(this, TIMER_SHOWGIF);
					}
				}
				
				//使系统通知我们 WM_MOUSELEAVE ;
				TrackMouseEvent(&m_tme); //注意版本需求:_WIN32_WINNT 0x0510
		 }
		 break;
		 case UIEVENT_MOUSELEAVE:
		 {
				if(curSel >= 0)
				{
					RECT rc;
					GetBlueRect(curSel, &rc);
					lastSel = curSel;
					curSel = -1;
					curFrame = 0;
					pvstatus = _PVStatus::Hide;
					UpdateSelectedFace(curPage, curSel, curFrame, pvstatus);
					this->Invalidate();
					//InvalidateRect(hDlg, &rc, FALSE);
				}
		 }
		 break;
		 case UIEVENT_TIMER:
		 {
			  this->m_pManager->KillTimer(this, TIMER_SHOWGIF);

			if(curSel >= 0 && frameCount > 1)
			{
				CxImage *pImg = GetSelectedImage(curPage, curSel);
				CxImage *pFrame = NULL;
				UINT frameDelay = 200;

				LPRECT lpRect = (pvstatus == _PVStatus::Left)? &rcLeft:&rcRight;
				
				//移动到下一帧!
				curFrame = (curFrame + 1) % frameCount;

				//QQ表情的帧延时通常是10毫秒,显示速度过快,因此增大到100毫秒
				pFrame = pImg->GetFrame(curFrame);
				
				if(pFrame) frameDelay = max(frameDelay, pFrame->GetFrameDelay());
 
				UpdateSelectedFace(curPage, curSel, curFrame, pvstatus);
				this->Invalidate();
				//InvalidateRect(hDlg, lpRect, FALSE);

				//下一帧的定时时间
				this->m_pManager->SetTimer(this, TIMER_SHOWGIF, frameDelay);
			} 
		 }
		 break;
	 }
}
bool CSakiBoard::IsOccupied(int x, int y)
{
	auto index = GetCellIndex(x, y);
	return (m_cells[index] != 0);
}