//---------------------------------------------------------------------------- Vector2f Renderer::PointWorldToViewPort (const APoint &point, bool *isInBack) { HMatrix matProjView = GetProjectionMatrix() * GetViewMatrix(); HPoint hPoint(point.X(), point.Y(), point.Z(), point.W()); HPoint tempPoint = matProjView * hPoint; if (isInBack) { if (tempPoint.Z() <= 0) *isInBack = true; else *isInBack = false; } float wInv = 1.0f / tempPoint.W(); //投影坐标范围为[-1,1]要变成[0,1] Vector2f screenPoint; screenPoint.X() = (1.0f + tempPoint.X()*wInv)/2.0f; screenPoint.Y() = (1.0f + tempPoint.Y()*wInv)/2.0f; //投影坐标范围为[0,1]要变成视口内坐标 int viewX, viewY, viewW, viewH; GetViewport(viewX, viewY, viewW, viewH); screenPoint.X() = viewX + screenPoint.X()*viewW; screenPoint.Y() = viewY + screenPoint.Y()*viewH; return screenPoint; }
//---------------------------------------------------------------------------- Vector2f RenderStep::PointWorldToViewPort(const APoint &point, bool *isInBack) { Rectf viewPort = mViewPort; if (viewPort.IsEmpty()) viewPort = Rectf(0.0f, 0.0f, mSize.Width, mSize.Height); HMatrix matProjView = mCamera->GetProjectionMatrix() * mCamera->GetViewMatrix(); HPoint hPoint(point.X(), point.Y(), point.Z(), point.W()); HPoint tempPoint = matProjView * hPoint; if (isInBack) { if (tempPoint.Z() <= 0) *isInBack = true; else *isInBack = false; } float wInv = 1.0f / tempPoint.W(); //投影坐标范围为[-1,1]要变成[0,1] Vector2f screenPoint; screenPoint.X() = (1.0f + tempPoint.X()*wInv) / 2.0f; screenPoint.Y() = (1.0f + tempPoint.Y()*wInv) / 2.0f; //投影坐标范围为[0,1]要变成视口内坐标 screenPoint.X() = viewPort.Left + screenPoint.X()*viewPort.Width(); screenPoint.Y() = viewPort.Bottom + screenPoint.Y()*viewPort.Height(); return screenPoint; }
//---------------------------------------------------------------------------- void EditRenderView_TimeLine::OnLeftDClick(const APoint &pos) { EditRenderView::OnLeftDClick(pos); Rectf rect(0, 0, mLeftWidth, mSize.Height); bool leftContain = rect.IsInsize(Float2(pos.X(), pos.Z())); bool isCtrlDown = PX2_EDIT.IsCtrlDown; if (!leftContain && isCtrlDown) { UICurveGroup *uiCurveGroup = PX2_EDIT.GetTimeLineEdit()->GetSelectedUICurveGroup(); if (!uiCurveGroup) return; Camera *camera = PX2_EDIT.GetTimeLineEdit()->GetTimeLineRenderStep_Grid()->GetCamera(); APoint camPos = camera->GetPosition(); Vector2f camScreenPos = mUIViewGrid->PointWorldToViewPort(camPos); float xDissCam = pos.X() - camScreenPos.X(); float zDissCam = pos.Z() - camScreenPos.Y(); float xDissCamReal = xDissCam / mPixelOverCamIn; float zDissCamReal = zDissCam / mPixelOverCamOut; APoint pointPos = camPos + AVector(xDissCamReal, 0.0f, zDissCamReal); CurveGroup *curveGroup = uiCurveGroup->GetCurveGroup(); curveGroup->AddPoint(pointPos); } }
//---------------------------------------------------------------------------- void Smoke2D::ComputeVortexOverlay () { unsigned char* data = (unsigned char*)mVortexTexture->GetData(0); memset(data, 0, 4*mNumPixels); if (mUseVortexOverlay) { // Draw the vortex centers, magenta for counterclockwise and cyan for // clockwise. float invXRange = 1.0f/(mX1 - mX0); float invYRange = 1.0f/(mY1 - mY0); for (int v = 0; v < mNumActive; ++v) { Vector2f center = mVortexCenter[v]; float x = (center.X() - mX0)*invXRange; float y = (center.Y() - mY0)*invYRange; int ix = (int)((mIMax-1)*x); int iy = (int)((mJMax-1)*y); unsigned char r, g, b, a; if (mVortexAmplitude[v] > 0.0f) { r = 255; g = 0; b = 255; a = 255; } else { r = 0; g = 255; b = 255; a = 255; } for (int dy = -1; dy <= 1; ++dy) { for (int dx = -1; dx <= 1; ++dx) { int index; if (PixelShader::GetProfile() == PixelShader::PP_ARBFP1) { index = 4*((ix+dx) + mIMaxP1*(iy+dy)); } else { index = 4*((ix+dx) + mIMaxP1*(mJMax-(iy+dy))); } data[index++] = b; data[index++] = g; data[index++] = r; data[index++] = a; } } } } mRenderer->Update(mVortexTexture, 0); }
//---------------------------------------------------------------------------- void QuadraticFreeForm2D::OnDisplay () { ClearScreen(); int dim0 = mTexture->GetDimension(0, 0); int dim1 = mTexture->GetDimension(1, 0); unsigned char* data = (unsigned char*)mTexture->GetData(0); const int numSamples = 2*mSize; const float invNumSamples = 1.0f/(float)numSamples; Vector2f param; for (int s = 0; s < numSamples; ++s) { int u = s*dim0/numSamples; param.X() = invNumSamples*s; for (int t = 0; t < numSamples; ++t) { int v = t*dim1/numSamples; param.Y() = invNumSamples*t; Vector2f result = Evaluate(param); int x = ControlToScreen(result.X()); int y = ControlToScreen(result.Y()); int index = 4*(u + dim0*v); unsigned char b = data[index++]; unsigned char g = data[index++]; unsigned char r = data[index++]; ++index; SetPixel(x, y, ColorRGB(r, g, b)); } } // Draw the control points. ColorRGB green(0, 255, 0); for (int row = 0; row <= 2; ++row) { for (int col = 0; col <= 2; ++col) { SetThickPixel(mCtrlX[row][col], mCtrlY[row][col], 2, green); } } WindowApplication2::OnDisplay(); }
//---------------------------------------------------------------------------- void PolygonDistance::DrawPoints (int thick, ColorRGB color, const Vector2f& point) { int x = (int)(point.X() + 0.5f); int y = mSize - 1 - (int)(point.Y() + 0.5f); for (int dy = -thick; dy <= thick; ++dy) { for (int dx = -thick; dx <= thick; ++dx) { SetPixel(x + dx, y + dy, color); } } }
//---------------------------------------------------------------------------- void BSplineCurveExamples::OnDisplay () { ClearScreen(); ColorRGB lightGray(224, 224, 224); ColorRGB mediumGray(192, 192, 192); ColorRGB darkGray(128, 128, 128); ColorRGB black(0, 0, 0); // draw axes int i; for (i = mSize/16; i < mSize; ++i) { SetPixel(mSize/16, mSize - 1 - i, lightGray); SetPixel(i, mSize - 1 - mSize/16, lightGray); } // draw control points int imax = mSpline->GetNumCtrlPoints(); int x, y; for (i = 0; i < imax; ++i) { const Vector2f& ctrl = mSpline->GetControlPoint(i); x = (int)(ctrl.X() + 0.5f); y = mSize - 1 - (int)(ctrl.Y() + 0.5f); SetThickPixel(x, y, 2, darkGray); } // draw spline imax = 2048; for (i = 0; i <= imax; ++i) { // draw point float u = i/(float)imax; Vector2f pos = mSpline->GetPosition(u); x = (int)(pos.X() + 0.5f); y = mSize - 1 - (int)(pos.Y() + 0.5f); if (mModified && mLocCtrlMin[mCurveType] <= u && u <= mLocCtrlMax[mCurveType]) { SetPixel(x, y, mediumGray); } else { SetPixel(x, y, black); } } WindowApplication2::OnDisplay(); }
//---------------------------------------------------------------------------- void PolygonDistance::DrawLineSegment (int thick, ColorRGB color, const Vector2f& end0, const Vector2f& end1) { const int imax = 2048; for (int i = 0; i <= imax; ++i) { float t = i/(float)imax; Vector2f position = t*end0 + (1.0f - t)*end1; int x = (int)(position.X() + 0.5f); int y = mSize - 1 - (int)(position.Y() + 0.5f); for (int dy = -thick; dy <= thick; ++dy) { for (int dx = -thick; dx <= thick; ++dx) { SetPixel(x + dx, y + dy, color); } } } }
//---------------------------------------------------------------------------- Vector2f QuadraticFreeForm2D::Evaluate (const Vector2f& param) const { float s = param.X(); float t = param.Y(); float omS = 1.0f - s; float omT = 1.0f - t; float b0s = omS*omS; float b0t = omT*omT; float b1s = 2.0f*omS*s; float b1t = 2.0f*omT*t; float b2s = s*s; float b2t = t*t; Vector2f result = b0s*(b0t*mCtrl[0][0] + b1t*mCtrl[0][1] + b2t*mCtrl[0][2]) + b1s*(b0t*mCtrl[1][0] + b1t*mCtrl[1][1] + b2t*mCtrl[1][2]) + b2s*(b0t*mCtrl[2][0] + b1t*mCtrl[2][1] + b2t*mCtrl[2][2]); return result; }
//---------------------------------------------------------------------------- BspNode* BspNodes::CreateNode (const Vector2f& v0, const Vector2f& v1, VertexColor3Effect* effect, const Float3& color) { // Create the model-space separating plane. Vector2f dir = v1 - v0; AVector normal(dir[1], -dir[0], 0.0f); normal.Normalize(); float constant = normal[0]*v0[0] + normal[1]*v0[1]; HPlane modelPlane(normal, constant); // Create the BSP node. BspNode* bsp = new0 BspNode(modelPlane); VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0); // Create the rectangle representation of the model plane and set the // vertex colors to the specified color. float xExtent = 0.5f*dir.Length(); float yExtent = 0.125f; TriMesh* rect = StandardMesh(vformat).Rectangle(2, 2, xExtent, yExtent); VertexBufferAccessor vba(rect); for (int i = 0; i < 4; ++i) { vba.Color<Float3>(0, i) = color; } rect->SetEffectInstance(effect->CreateInstance()); // Set the position and orientation for the world-space plane. APoint trn(0.5f*(v0[0] + v1[0]), 0.5f*(v0[1] + v1[1]), yExtent + 0.001f); HMatrix zRotate(AVector::UNIT_Z, Mathf::ATan2(dir.Y(),dir.X())); HMatrix xRotate(AVector::UNIT_X, Mathf::HALF_PI); HMatrix rotate = zRotate*xRotate; rect->LocalTransform.SetTranslate(trn); rect->LocalTransform.SetRotate(rotate); bsp->AttachCoplanarChild(rect); return bsp; }
//---------------------------------------------------------------------------- void RevolutionSurface::UpdateSurface () { // Parameters for evaluating curve. float tMin = mCurve->GetMinTime(); float tRange = mCurve->GetMaxTime() - tMin; // Sampling by arc length requires the total length of the curve. float totalLength; if (mSampleByArcLength) { totalLength = mCurve->GetTotalLength(); } else { totalLength = 0.0f; } // Sample the curve of revolution. float invNumCurveSamplesM1 = 1.0f/(float)(mNumCurveSamples - 1); for (int i = 0; i < mNumCurveSamples; ++i) { float t; if (mSampleByArcLength) { t = mCurve->GetTime(i*totalLength*invNumCurveSamplesM1); } else { t = tMin + i*tRange*invNumCurveSamplesM1; } Vector2f position = mCurve->GetPosition(t); mSamples[i][0] = position.X(); mSamples[i][1] = 0.0f; mSamples[i][2] = position.Y(); } // Store the samples and their rotated equivalents. The storage layout // is dependent on the topology of the mesh. switch (mTopology) { case REV_DISK_TOPOLOGY: UpdateDisk(); break; case REV_CYLINDER_TOPOLOGY: UpdateCylinder(); break; case REV_SPHERE_TOPOLOGY: UpdateSphere(); break; case REV_TORUS_TOPOLOGY: UpdateTorus(); break; default: assertion(false, "Unexpected condition\n"); break; } UpdateModelSpace(Visual::GU_NORMALS); // See the comments in the constructor about mIBuffer and the vertex // buffer update. if (mIBuffer) { Renderer::UpdateAll(mVBuffer); } }
//---------------------------------------------------------------------------- void EditRenderView_TimeLine::_RefreshGrid(bool doScale) { Polysegment *gird = PX2_EDIT.GetTimeLineEdit()->GetGridPoly(); PX2_UNUSED(doScale); int width = (int)mSize.Width; int height = (int)mSize.Height; if (width <= 0 && height <= 0) return; Camera *camera = mUIViewGrid->GetCamera(); APoint pos = camera->GetPosition(); float dMin = 0.0f; float dMax = 0.0f; float uMin = 0.0f; float uMax = 0.0f; float rMin = 0.0f; float rMax = 0.0f; camera->GetFrustum(dMin, dMax, uMin, uMax, rMin, rMax); if (0.0f == rMax || 0.0f == uMax || 0.0f == dMax) return; float inLength = rMax - rMin; float outLength = uMax - uMin; inLength = Mathf::FAbs(inLength); outLength = Mathf::FAbs(outLength); mPixelOverCamIn = width / inLength; mPixelOverCamOut = height / outLength; int minPixelsPerInGrid = 35; int minPixelsPerOutGrid = 25; float minGridSpacing = 0.001f; int gridNum = 0; float inGridSpacing = minGridSpacing; while (inGridSpacing*mPixelOverCamIn < minPixelsPerInGrid) { inGridSpacing = minGridSpacing * _GetGridSpacing(gridNum); gridNum++; } mUPerGrid = inGridSpacing; gridNum = 0; float outGridSpacing = minGridSpacing; while (outGridSpacing*mPixelOverCamOut < minPixelsPerOutGrid) { outGridSpacing = minGridSpacing * _GetGridSpacing(gridNum); gridNum++; } mVPerGrid = outGridSpacing; mXStart = pos.X() + rMin; mXEnd = pos.X() + rMax; mZStart = pos.Z() + uMin; mZEnd = pos.Z() + uMax; Float3 gray(0.62f, 0.62f, 0.62f); int segNum = 0; mFontStrs.clear(); int iTemp = 4; int zTemp = 4; VertexBufferAccessor vba(gird); float zPosTemp = 0.0f; while (zPosTemp < mZEnd) { zPosTemp += mVPerGrid; vba.Position<Float3>(2 * segNum) = Float3(mXStart, 1.0f, zPosTemp); vba.Color<Float3>(0, 2 * segNum) = gray; vba.Position<Float3>(2 * segNum + 1) = Float3(mXEnd, 1.0f, zPosTemp); vba.Color<Float3>(0, 2 * segNum + 1) = gray; mRenderer->SetCamera(mUIViewGrid->GetCamera()); Vector2f scrv = mUIViewGrid->PointWorldToViewPort(APoint(0.0f, 0.0f, zPosTemp)); FontStr fs; fs.x = iTemp + (int)mLeftWidth; fs.y = height - (int)scrv.Y(); fs.str = StringHelp::FloatToString(zPosTemp); mFontStrs.push_back(fs); segNum++; } zPosTemp = 0.0f; while (zPosTemp > mZStart) { zPosTemp -= mVPerGrid; vba.Position<Float3>(2 * segNum) = Float3(mXStart, 1.0f, zPosTemp); vba.Color<Float3>(0, 2 * segNum) = gray; vba.Position<Float3>(2 * segNum + 1) = Float3(mXEnd, 1.0f, zPosTemp); vba.Color<Float3>(0, 2 * segNum + 1) = gray; Vector2f scrv = mUIViewGrid->PointWorldToViewPort(APoint(0.0f, 0.0f, zPosTemp)); FontStr fs; fs.x = iTemp + (int)mLeftWidth; fs.y = height - (int)scrv.Y(); fs.str = StringHelp::FloatToString(zPosTemp); mFontStrs.push_back(fs); segNum++; } float xPosTemp = 0.0f; while (xPosTemp < mXEnd) { xPosTemp += mUPerGrid; vba.Position<Float3>(2 * segNum) = Float3(xPosTemp, 1.0f, mZStart); vba.Color<Float3>(0, 2 * segNum) = gray; vba.Position<Float3>(2 * segNum + 1) = Float3(xPosTemp, 1.0f, mZEnd); vba.Color<Float3>(0, 2 * segNum + 1) = gray; Vector2f scrv = mUIViewGrid->PointWorldToViewPort(APoint(xPosTemp, 0.0f, 0.0f)); FontStr fs; fs.x = (int)scrv.X() + iTemp; fs.y = height - zTemp; fs.str = StringHelp::FloatToString(xPosTemp); mFontStrs.push_back(fs); segNum++; } xPosTemp = 0.0f; while (xPosTemp > mXStart) { xPosTemp -= mUPerGrid; vba.Position<Float3>(2 * segNum) = Float3(xPosTemp, 1.0f, mZStart); vba.Color<Float3>(0, 2 * segNum) = gray; vba.Position<Float3>(2 * segNum + 1) = Float3(xPosTemp, 1.0f, mZEnd); vba.Color<Float3>(0, 2 * segNum + 1) = gray; Vector2f scrv = mUIViewGrid->PointWorldToViewPort(APoint(xPosTemp, 0.0f, 0.0f)); FontStr fs; fs.x = (int)scrv.X() + iTemp; fs.y = height - zTemp; fs.str = StringHelp::FloatToString(xPosTemp); mFontStrs.push_back(fs); segNum++; } Float3 zeroLineColorRed = Float3::MakeColor(150, 28, 36); Float3 zeroLineColorBlue = Float3::MakeColor(63, 72, 175); vba.Position<Float3>(2 * segNum) = Float3(mXStart, 1.0f, 0.0f); vba.Color<Float3>(0, 2 * segNum) = zeroLineColorRed; vba.Position<Float3>(2 * segNum + 1) = Float3(mXEnd, 1.0f, 0.0f); vba.Color<Float3>(0, 2 * segNum + 1) = zeroLineColorRed; segNum++; vba.Position<Float3>(2 * segNum) = Float3(0.0f, 1.0f, mZStart); vba.Color<Float3>(0, 2 * segNum) = zeroLineColorBlue; vba.Position<Float3>(2 * segNum + 1) = Float3(0.0f, 1.0f, mZEnd); vba.Color<Float3>(0, 2 * segNum + 1) = zeroLineColorBlue; segNum++; Vector2f scrv = mUIViewGrid->PointWorldToViewPort(APoint::ORIGIN); FontStr fs; fs.x = iTemp + (int)mLeftWidth; fs.y = height - (int)scrv.Y(); fs.str = "0.0"; mFontStrs.push_back(fs); FontStr fs1; fs1.x = (int)scrv.X() + iTemp; fs1.y = height - zTemp; fs1.str = "0.0"; mFontStrs.push_back(fs1); gird->SetNumSegments(segNum); gird->UpdateModelSpace(Renderable::GU_MODEL_BOUND_ONLY); if (mRenderer) mRenderer->Update(gird->GetVertexBuffer()); if (doScale) { float rWidth = 2.0f * rMax; float scaleX = rWidth / 22.5f; float uHeight = 2.0f * uMax; float scaleZ = uHeight / (((float)mSize.Height / (float)mSize.Width)*22.5f); PX2_EDIT.GetTimeLineEdit()->SetCtrlsScale(Float2(scaleX, scaleZ)); } }
//---------------------------------------------------------------------------- void NURBSCurveExample::OnDisplay () { ClearScreen(); const int iCurveThick = 0; Color kCurveColor(0,0,0); const int iControlThick = 2; Color kControlColor(128,128,128); int iMax = 2048; int i, iX, iY, iDX, iDY; float fT; Vector2f kPos; // draw spline for (i = 0; i <= iMax; i++) { fT = i/(float)iMax; kPos = m_pkSpline->GetPosition(fT); iX = int(kPos.X()+0.5f); iY = g_iSize-1-int(kPos.Y()+0.5f); for (iDY = -iCurveThick; iDY <= iCurveThick; iDY++) { for (iDX = -iCurveThick; iDX <= iCurveThick; iDX++) SetPixel(iX+iDX,iY+iDY,kCurveColor); } } // draw circle if ( m_pkCircle ) { for (i = 0; i <= iMax; i++) { // draw point fT = i/(float)iMax; kPos = m_pkCircle->GetPosition(fT); iX = int(kPos.X()+0.5f); iY = g_iSize-1-int(kPos.Y()+0.5f); for (iDY = -iCurveThick; iDY <= iCurveThick; iDY++) { for (iDX = -iCurveThick; iDX <= iCurveThick; iDX++) SetPixel(iX+iDX,iY+iDY,kCurveColor); } } } // draw control points if ( m_bDrawControlPoints ) { iMax = m_pkSpline->GetNumCtrlPoints(); for (i = 0; i < iMax; i++) { const Vector2f& rkCtrl = m_pkSpline->GetControlPoint(i); iX = int(rkCtrl.X()+0.5f); iY = g_iSize-1-int(rkCtrl.Y()+0.5f); for (iDY = -iControlThick; iDY <= iControlThick; iDY++) { for (iDX = -iControlThick; iDX <= iControlThick; iDX++) SetPixel(iX+iDX,iY+iDY,kControlColor); } } if ( m_pkCircle ) { iMax = m_pkCircle->GetNumCtrlPoints(); for (i = 0; i < iMax; i++) { const Vector2f& rkCtrl = m_pkCircle->GetControlPoint(i); iX = int(rkCtrl.X()+0.5f); iY = g_iSize-1-int(rkCtrl.Y()+0.5f); for (iDY = -iControlThick; iDY <= iControlThick; iDY++) { for (iDX = -iControlThick; iDX <= iControlThick; iDX++) SetPixel(iX+iDX,iY+iDY,kControlColor); } } } } Application2::OnDisplay(); }
//---------------------------------------------------------------------------- bool GeodesicHeightField::OnMouseClick (int button, int state, int x, int y, unsigned int modifiers) { if ((modifiers & MODIFIER_SHIFT) == 0) { return WindowApplication3::OnMouseClick(button, state, x, y, modifiers); } if (state != MOUSE_DOWN || button != MOUSE_LEFT_BUTTON) { return false; } // Convert to right-handed coordinates. y = GetHeight() - 1 - y; // Do a picking operation. APoint origin; AVector direction; mRenderer->GetPickRay(x, y, origin, direction); mPicker.Execute(mScene, origin, direction, 0.0f, Mathf::MAX_REAL); if (mPicker.Records.size() > 0) { const PickRecord& record = mPicker.GetClosestNonnegative(); // Get the vertex indices for the picked triangle. int triangle = record.Triangle; int i0 = 3*triangle, i1 = i0 + 1, i2 = i0 + 2; int* indices = (int*)mMesh->GetIndexBuffer()->GetData(); int v0 = indices[i0]; int v1 = indices[i1]; int v2 = indices[i2]; // Get the texture coordinates for the point of intersection. VertexBufferAccessor vba(mMesh); Vector2f intr = vba.TCoord<Vector2f>(0, v0)*record.Bary[0] + vba.TCoord<Vector2f>(0, v1)*record.Bary[1] + vba.TCoord<Vector2f>(0, v2)*record.Bary[2]; // Save the point. mPoint[mSelected][0] = (double)intr.X(); mPoint[mSelected][1] = (double)intr.Y(); // Clear the texture image to white. unsigned char* data = (unsigned char*)mTexture->GetData(0); memset(data, 0xFF, mTexture->GetNumLevelBytes(0)); // Get an endpoint. int bound0 = mTexture->GetDimension(0, 0); int bound1 = mTexture->GetDimension(1, 0); int x = (int)(bound0*intr.X() + 0.5); int y = (int)(bound1*intr.Y() + 0.5); mXIntr[mSelected] = x; mYIntr[mSelected] = y; ++mSelected; // Mark the endpoints in black. for (int i = 0; i < mSelected; ++i) { int index = 4*(mXIntr[i] + bound0*mYIntr[i]); data[index++] = 0; data[index++] = 0; data[index++] = 0; data[index++] = 255; } mTexture->GenerateMipmaps(); if (mSelected == 2) { delete1(mPath); mPath = 0; mGeodesic->ComputeGeodesic(mPoint[0], mPoint[1], mPQuantity, mPath); mSelected = 0; } } return true; }
//---------------------------------------------------------------------------- void EditRenderView_TimeLine::OnMotion(const APoint &pos) { AVector diff = pos - mLastMousePoint; if (AVector::ZERO == diff) return; float movedX = -diff.X() / mPixelOverCamIn; float movedZ = -diff.Z() / mPixelOverCamOut; Rectf rect(0, 0, mLeftWidth, mSize.Height); bool leftContain = rect.IsInsize(Float2(pos.X(), pos.Z())); bool isCtrlDown = PX2_EDIT.IsCtrlDown; CurveCtrl *selectedCtrl = PX2_EDIT.GetTimeLineEdit()->GetSelectedCurveCtrl(); if (isCtrlDown && !leftContain && selectedCtrl && mIsLeftDown) { Camera *camera = mRenderStep->GetCamera(); const APoint &outVal = selectedCtrl->GetOutVal(); Vector2f posInViewPort = mUIViewGrid->PointWorldToViewPort(outVal); float xDiss = pos.X() - posInViewPort.X(); float zDiss = pos.Z() - posInViewPort.Y(); float xDissReal = xDiss / mPixelOverCamIn; float zDissReal = zDiss / mPixelOverCamOut; AVector arrive = AVector(-xDissReal, 0.0f, -zDissReal); arrive.Normalize(); AVector leave = AVector(xDissReal, 0.0f, zDissReal); leave.Normalize(); if (CurveCtrl::SM_ARRIVE == selectedCtrl->GetSelectMode()) { if (xDiss < 0.0f) { selectedCtrl->SetArriveTangent(arrive); InterpCurveMode mode = selectedCtrl->GetInterpCurveMode(); if (ICM_CURVE_AUTO == mode || ICM_CURVE_AUTOCLAMPED == mode) { selectedCtrl->SetInterpCurveMode(ICM_CURVE_USER); //UnToggleAllInterps(); //ToggleInterp(ICM_CURVE_USER); } } } else if (CurveCtrl::SM_LEAVE == selectedCtrl->GetSelectMode()) { if (xDiss > 0.0f) { selectedCtrl->SetLeaveTangent(leave); InterpCurveMode mode = selectedCtrl->GetInterpCurveMode(); if (ICM_CURVE_AUTO == mode || ICM_CURVE_AUTOCLAMPED == mode) { selectedCtrl->SetInterpCurveMode(ICM_CURVE_USER); //UnToggleAllInterps(); //ToggleInterp(ICM_CURVE_USER); } } } else if (CurveCtrl::SM_CENTER == selectedCtrl->GetSelectMode()) { APoint camPos = camera->GetPosition(); Vector2f camScreenPos = mUIViewGrid->PointWorldToViewPort(camPos); float xDissCam = pos.X() - camScreenPos.X(); float zDissCam = pos.Z() - camScreenPos.Y(); float xDissCamReal = xDissCam / mPixelOverCamIn; float zDissCamReal = zDissCam / mPixelOverCamOut; APoint pointPos = camPos + AVector(xDissCamReal, 0.0f, zDissCamReal); pointPos.Y() = 0.0f; selectedCtrl->SetInVal(pointPos.X()); // ctrl may changed selectedCtrl = PX2_EDIT.GetTimeLineEdit()->GetSelectedCurveCtrl(); // ctrl may changed, can it again if (selectedCtrl) selectedCtrl->SetOutVal(pointPos); } } bool doMovCal = false; if (mIsMiddleDown && !leftContain) doMovCal = true; if (mIsRightDown && !leftContain) doMovCal = true; if (doMovCal) { if (MM_PAN == mMoveMode) { APoint pos = mUIViewGrid->GetCameraNode()->LocalTransform.GetTranslate(); pos += AVector(movedX, 0.0f, movedZ); mUIViewGrid->GetCameraNode()->LocalTransform.SetTranslate(pos); mUIViewGrid->GetCameraNode()->Update(GetTimeInSeconds(), 0.0f); _RefreshGrid(false); } else if (MM_ZOOM == mMoveMode) { } } mLastMousePoint = pos; }
//---------------------------------------------------------------------------- void NURBSCurveExample::OnDisplay () { ClearScreen(); ColorRGB curveColor(0,0,0); ColorRGB controlColor(128, 128, 128); int imax = 2048; int i, x, y; float t; Vector2f position; // Draw the spline. for (i = 0; i <= imax; ++i) { t = i/(float)imax; position = mSpline->GetPosition(t); x = (int)(position.X() + 0.5f); y = mSize - 1 - (int)(position.Y() + 0.5f); SetPixel(x, y, curveColor); } // Draw the circle. if (mCircle) { for (i = 0; i <= imax; ++i) { t = i/(float)imax; position = mCircle->GetPosition(t); x = (int)(position.X() + 0.5f); y = mSize - 1 - (int)(position.Y() + 0.5f); SetPixel(x, y, curveColor); } } // Draw the control points. if (mDrawControlPoints) { // Draw the spline control points. imax = mSpline->GetNumCtrlPoints(); for (i = 0; i < imax; ++i) { const Vector2f& ctrl = mSpline->GetControlPoint(i); x = (int)(ctrl.X() + 0.5f); y = mSize - 1 -(int)(ctrl.Y() + 0.5f); SetThickPixel(x, y, 2, controlColor); } // Draw the circle control points. if (mCircle) { imax = mCircle->GetNumCtrlPoints(); for (i = 0; i < imax; ++i) { const Vector2f& ctrl = mCircle->GetControlPoint(i); x = (int)(ctrl.X() + 0.5f); y = mSize - 1 - (int)(ctrl.Y() + 0.5f); SetThickPixel(x, y, 2, controlColor); } } } WindowApplication2::OnDisplay(); }
//---------------------------------------------------------------------------- void MapTextureToQuad::CreateMapping () { // Create the new perspective mapping from the *target* quadrilateral to // the *source* square bitmap. The mapping is in this direction to avoid // holes in the drawn quadrilateral. delete0(mMapping); #ifdef USE_HM_QUAD_TO_SQR mMapping = new0 HmQuadToSqrf(mVertex[0], mVertex[1], mVertex[2], mVertex[3]); #else mMapping = new0 BiQuadToSqrf(mVertex[0], mVertex[1], mVertex[2], mVertex[3]); #endif // Compute axis-aligned bounding box. int xmin = GetWidth(), xmax = 0, ymin = GetWidth(), ymax = 0; for (int i = 0; i < 4; ++i) { if (xmin > (int)mVertex[i].X()) { xmin = (int)mVertex[i].X(); } if (xmax < (int)mVertex[i].X()) { xmax = (int)mVertex[i].X(); } if (ymin > (int)mVertex[i].Y()) { ymin = (int)mVertex[i].Y(); } if (ymax < (int)mVertex[i].Y()) { ymax = (int)mVertex[i].Y(); } } // Draw perspective mapping of image (...inefficient drawing...). ClearScreen(); int xSize = mTexture->GetDimension(0, 0); int ySize = mTexture->GetDimension(1, 0); unsigned char* data = (unsigned char*)mTexture->GetData(0); for (int trgY = ymin; trgY <= ymax; ++trgY) { Vector2f quad; quad.Y() = (float)trgY; int xStart = xmin; while (xStart <= xmax) { quad.X() = (float)xStart; if (PointInPolygon2f(4, mVertex).ContainsQuadrilateral(quad)) { break; } ++xStart; } int xFinal = xmax; while (xFinal >= xmin) { quad.X() = (float)xFinal; if (PointInPolygon2f(4, mVertex).ContainsQuadrilateral(quad)) { break; } --xFinal; } for (int trgX = xStart; trgX <= xFinal; ++trgX) { // Transform point to unit square. quad.X() = (float)trgX; Vector2f square = mMapping->Transform(quad); // Convert to bitmap coordinates (using clamping). int srcX = (int)((xSize - 1)*square.X()); if (srcX < 0) { srcX = 0; } else if (srcX >= xSize) { srcX = xSize - 1; } int srcY = (int)((ySize - 1)*square.Y()); if (srcY < 0) { srcY = 0; } else if (srcY >= ySize) { srcY = ySize - 1; } int srcIndex = 4*(srcX + xSize*srcY); unsigned char* srcRGBA = data + srcIndex; int trgIndex = trgX + GetWidth()*trgY; unsigned char* trgRGB = (unsigned char*)(mScreen + trgIndex); for (int i = 0; i < 3; ++i) { trgRGB[i] = srcRGBA[i]; } } } OnDisplay(); }
//---------------------------------------------------------------------------- void MapTextureToQuad::CreateMapping () { // Create the new perspective mapping from the *target* quadrilateral to // the *source* square bitmap. The mapping is in this direction to avoid // holes in the drawn quadrilateral. delete m_pkMap; m_pkMap = new HmQuadToSqrf(m_akVertex[0],m_akVertex[1],m_akVertex[2], m_akVertex[3]); // compute axis-aligned bounding box int iXMin = GetWidth(), iXMax = 0, iYMin = GetWidth(), iYMax = 0; for (int i = 0; i < 4; i++) { if ( iXMin > (int)m_akVertex[i].X() ) iXMin = (int)m_akVertex[i].X(); if ( iXMax < (int)m_akVertex[i].X() ) iXMax = (int)m_akVertex[i].X(); if ( iYMin > (int)m_akVertex[i].Y() ) iYMin = (int)m_akVertex[i].Y(); if ( iYMax < (int)m_akVertex[i].Y() ) iYMax = (int)m_akVertex[i].Y(); } // draw perspective mapping of image (...inefficient drawing...) ClearScreen(); int iXSize = m_pkImage->GetWidth(); int iYSize = m_pkImage->GetHeight(); unsigned char* aucData = m_pkImage->GetData(); for (int iTrgY = iYMin; iTrgY <= iYMax; iTrgY++) { Vector2f kQuad; kQuad.Y() = (float)iTrgY; int iXStart = iXMin; while ( iXStart <= iXMax ) { kQuad.X() = (float)iXStart; if ( PointInConvex4(m_akVertex,kQuad) ) break; iXStart++; } int iXFinal = iXMax; while ( iXFinal >= iXMin ) { kQuad.X() = (float)iXFinal; if ( PointInConvex4(m_akVertex,kQuad) ) break; iXFinal--; } for (int iTrgX = iXStart; iTrgX <= iXFinal; iTrgX++) { // transform point to unit square kQuad.X() = (float)iTrgX; Vector2f kSquare = m_pkMap->Transform(kQuad); // convert to bitmap coordinates (using clamping) int iSrcX = (int)((iXSize-1)*kSquare.X()); if ( iSrcX < 0 ) iSrcX = 0; else if ( iSrcX >= iXSize ) iSrcX = iXSize-1; int iSrcY = (int)((iYSize-1)*kSquare.Y()); if ( iSrcY < 0 ) iSrcY = 0; else if ( iSrcY >= iYSize ) iSrcY = iYSize-1; int iSrcIndex = 3*(iSrcX+iXSize*iSrcY); unsigned char* aucSrcRGB = aucData + iSrcIndex; int iTrgIndex = iTrgX + GetWidth()*iTrgY; unsigned char* aucTrgRGB = (unsigned char*)(m_akScreen + iTrgIndex); for (int i = 0; i < 3; i++) aucTrgRGB[i] = aucSrcRGB[2-i]; } } OnDisplay(); }