B样条曲线的应用

B样条曲线渲染及生成全景图

采用OpenGL场景中渲染B样条曲线,曲线控制点给生成全景图算法,生成全景图,创建过程:

  1. 场景中B样条曲线,需要渲染的部分:B样条的控制点controlPoint,及由控制点B样条算法生成的曲线上的点linePoint;这些点通过坐标转换,将屏幕坐标转换为世界坐标。曲线外面矩形框点,固定的点,世界坐标。
  2. 全景图中B样条算法中需要的控制点,需要的是像素坐标。因此,曲线actor中传给B样条算法的点需要像素坐标,而曲线需要B样条计算出来的点转换为世界坐标。

传给BSpline算法:

            double dTheta = m_fRotateAngle / 180f * Math.PI;
            float[] fMatrix = { (float)Math.Cos(dTheta), (float)Math.Sin(dTheta),0,
                                                      -(float)Math.Sin(dTheta),(float)Math.Cos(dTheta),0,
                                                      m_fCenterX,m_fCenterY,1};
            visMat3f mvisMat3f = new visMat3f(fMatrix);
            visMat3f mvisMat3fInvert = mvisMat3f.GetInvert();
            float fNewNodeX = (mvisMat3fInvert.f00 * fMouseX + mvisMat3fInvert.f10 * fMouseY + mvisMat3fInvert.f20)
                / m_fScaleX;
            float fNewNodeY = (mvisMat3fInvert.f01 * fMouseX + mvisMat3fInvert.f11 * fMouseY + mvisMat3fInvert.f21)
                / m_fScaleY;
            visVec3f visV3fNewPosition = new visVec3f(fNewNodeX, fNewNodeY);
            m_lv3fNodePoints.Insert(m_nWhichPointIsSelected, visV3fNewPosition);
            m_lv3fNodePoints.RemoveAt(m_nWhichPointIsSelected + 1);

            float fPixelX = 0;
            float fPixelY = 0;
            CoordWorldToPixel(fNewNodeX, fNewNodeY, ref fPixelX, ref fPixelY);
            m_algoBSpline.MoveNodePoint(fPixelX, fPixelY, m_nWhichPointIsSelected);

B样条算法传给actor的linePoint

            List<visVec3f> listV3fLineStrip = new List<visVec3f>();
            m_algoBSpline.GetPanoLineStrip(listV3fLineStrip);

            m_lv3fPanoLine.Clear();
            foreach (visVec3f v3fPixel in listV3fLineStrip)
            {
                float fWolrdX = 0;
                float fWolrdY = 0;
                CoordPixelToWorld(v3fPixel.x, v3fPixel.y, ref fWolrdX, ref fWolrdY);
                m_lv3fPanoLine.Add(new visVec3f(fWolrdX, fWolrdY));
            }
  1. 以上可以看出actor中B样条算法BSpline,与生成全景图需要的B样条算法BSpline所需控制点均为像素坐标。
  2. 另在编辑整个图形时,核心主要以下几点:
    1)移动外面边框时,actor曲线上的点(controlpoint 及linepoint)坐标均不变,在渲染时,已经将框的平移及缩放量计算;
 GL.PushMatrix();
 GL.Translate(m_fCenterX, m_fCenterY, 0);

 GL.Rotate(m_fRotateAngle, 0, 0, 1);
 GL.Scale(m_fScaleX, m_fScaleY, 0f);

2) 移动控制点时,actor本身控制点坐标需改变,全景算法中B样条控制点同样需要改变,见3

 double dTheta = m_fRotateAngle / 180f * Math.PI;
            float[] fMatrix = { (float)Math.Cos(dTheta), (float)Math.Sin(dTheta),0,
                                                      -(float)Math.Sin(dTheta),(float)Math.Cos(dTheta),0,
                                                      m_fCenterX,m_fCenterY,1};
            visMat3f mvisMat3f = new visMat3f(fMatrix);
            visMat3f mvisMat3fInvert = mvisMat3f.GetInvert();
            float fNewNodeX = (mvisMat3fInvert.f00 * fMouseX + mvisMat3fInvert.f10 * fMouseY + mvisMat3fInvert.f20)
                / m_fScaleX;
            float fNewNodeY = (mvisMat3fInvert.f01 * fMouseX + mvisMat3fInvert.f11 * fMouseY + mvisMat3fInvert.f21)
                / m_fScaleY;
            visVec3f visV3fNewPosition = new visVec3f(fNewNodeX, fNewNodeY);
            m_lv3fNodePoints.Insert(m_nWhichPointIsSelected, visV3fNewPosition);
            m_lv3fNodePoints.RemoveAt(m_nWhichPointIsSelected + 1);

            float fPixelX = 0;
            float fPixelY = 0;
            CoordWorldToPixel(fNewNodeX, fNewNodeY, ref fPixelX, ref fPixelY);
            m_algoBSpline.MoveNodePoint(fPixelX, fPixelY, m_nWhichPointIsSelected);

3)结束移动时,无论是移动点还是框,传给生成全景图的B样条算法的控制点需要计算成绝对的坐标:

                   #region 只修改传给全景算法的控制点,actor本身的控制点不修改
                    float fPointX, fPointY;
                    double dTheta = MathHelper.DegreesToRadians(m_fRotateAngle);
                    float fPixelX = 0, fPixelY = 0;

                    m_algoBSplineForP.ClearNodePoint();

                    for (int i = 0; i < m_lv3fNodePoints.Count; i++)
                    {
                        //需要先将目前的点坐标转换为变换后的坐标
                        fPointX = m_lv3fNodePoints[i].x * m_fScaleX * (float)Math.Cos(dTheta)
                                - m_lv3fNodePoints[i].y * m_fScaleX * (float)Math.Sin(dTheta) + m_fCenterX / 2;
                        fPointY = m_lv3fNodePoints[i].x * m_fScaleY * (float)Math.Sin(dTheta)
                                + m_lv3fNodePoints[i].y * m_fScaleY * (float)Math.Cos(dTheta) + m_fCenterY / 2;
                        CoordWorldToPixel(fPointX, fPointY, ref fPixelX, ref fPixelY);
                        m_algoBSplineForP.AddNodePoint(new visVec3f(fPixelX, fPixelY, 0));
                    }

                    UpdateManualPanoramicCurve();
                    #endregion
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值