LOD地形设计

Windows 11 安装 uv:手动下载、配置国内源 本教程详细介绍了在 Windows 11 系统下安装并配置 Python 包管理器 uv 的完整流程,包括配置环境变量 PATH、设置清华 PyPI 镜像源,以及创建收据文件以支持未来更新。适用于因网络限制无法通过官方脚本自动安装的用户,操作步骤清晰,配有图文指引,帮助读者高效完成本地部署。 阅读详情

在大规模的三维场景中,不可能一次渲染所有的三角形,而且即使能做到这点,全部渲染也是不可取的。常用的做法就是采用LOD,即层次细节模型。距离视点较远的三角形可以大一些,粗糙一些,而距离视点较近的三角形则应有较为细腻地表现。常用的LOD地形的实现算法是四叉树算法,即对二维地平面进行分割时,每次把正方形分成4个等分的小正方形,直到分割的正方形尺寸达到某个阈值为止,然后对不能再分的正方形进行三角形剖分渲染。

由于正方形的右下角位于视截体内部(图1),需要把正方形进行分割,图2为第一次分割的后的状态。由于右下角正方形位于视截体内部,所以进行第二次分割,见图3。直到第3次分割(图4),才有小正方形不在视截体内,既不要细致渲染的正方形。如此不断分割,地平面会出现若干大小不等的正方形。为了记录正方形哪些是要分割的,哪些是不要分割的,需要设置一个标志,为此封装一个类来管理标志,该类记为Bit。

 

 

    为了判断一个节点区域是否在视截体内部,应该有一个管理视截体数据的类CFrustum。该类应该有视截体的六个平面方程,以及检测物体是否落在视截体内的函数。由于LOD地形是和视点相关的,距离视点进的三角形需要细腻渲染,而较远的则则可以稍微粗糙一些。因此一个正方形距离视点的距离d和自身的边长e应该是一个指标来决定改正方形是否需要细分,d/e < C1时,需要进一步细分,否则不需要进一步细分。当C1的值越大,e的值越小,节点细节较为细致;相反,C1越小,e值越大,节点细节与粗糙。正方形是否需要进一步分割,还和地形的起伏有关系,当地势平坦时,节点细节可以较少,反之节点细节应该较为丰富。r=MAX(正方形四个定点和中心)-MIN(正方形四个定点和中心)。r/e < C2时,e较大,需要分割。C2越大,e越小,层次越细腻,反之,C2越小,e越大,可以少一些细节。称C1为距离分辨率, C2为高度分辨率。

既然LOD和视点相关,就必须有一个类来记录视点,把该类记为Camera,该类应该包含视点相关数据,如视点位置,视线目标,视点如何移动,旋转等

 

自从LOD地形第一节推出以来,受到不少朋友的关注,本人真是受宠若惊,无奈自己水平有限,怕写不好让大家对自己失望,我只能勉为其难,努力去写,同时欢迎高人能手给于指正,大家共同学习,共同提高!
LOD地形的四叉树算法原理就是对地形进行四叉树分割,同时检查该节点是否位于视截体内部,如果在视截体内部且满足视距,周围点高程误差等条件时,则对该节点继续分割,否则不予分割。其中重点是视截体的计算,以及地形的分割及渲染。下面介绍几个系统中用到的类。
首先介绍标志节点是否分割的类Bit
类定义:

//该类根据节点的位置,为每个节点在标志段里相应位设一个标识。
/***********************************************************************
*    Copyrights Reserved by QinGeSoftware
*    Author : Qinge
*    Filename : Bit.h 1.0
*    Date: 2008-1-10
************************************************************************/
#pragma once

class Bit
{
public:
    void SetScale(int nScale);                        //伸缩系数
    void Set(int x, int y, BOOL bFlog=TRUE);          //设置标志位
    void Reset();                                     //标志清零
    BOOL CreateBits(int nXBites, int nRows);          //创建标志数组
    BOOL IsTrue(int x, int y);                        //查询该位标志
public:
    Bit();
    virtual ~Bit(void);
private:
    unsigned char *m_pBits;   //存储位标志的指针
    int m_nXBytes;            //X方向的字节数
    int m_nZRows;             //Z方向的行数
    int m_nScale;             //伸缩系数
};



//类实现文件
/***********************************************************************
*    Copyrights Reserved by QinGeSoftware
*    Author : Qinge
*    Filename : Bit.cpp 1.0
*    Date: 2008-1-10
************************************************************************/
#include "StdAfx.h"
#include "Bit.h"

Bit::Bit(void)
{
    m_pBits = NULL;                                 //指针初始化为NULL    
    m_nXBytes = 0;
    m_nZRows = 0;
    m_nScale = 1;                                        //不能初始化为0,因为是除数

}

Bit::~Bit(void)
{
    if(m_pBits != NULL)
    {
        delete [] m_pBits;                              //释放指针
        m_pBits = NULL;                                 //置为空,否则会成为野指针
    }
}

BOOL Bit::CreateBits(int nXBites, int nRows)
{
    //nXBits 必须是8的倍数
    m_nXBytes = nXBites/8+1;                            //想想为什么加1
    m_nZRows   = nRows;
    m_pBits = new unsigned char[m_nXBytes * m_nZRows]; //分配空间
    memset(m_pBits, 0, m_nZRows * m_nXBytes);         //标志段全部初始化0
    return 0;
}

void Bit::SetScale(int nScale)
{
    m_nScale = nScale;                                 //提供操作私有变量的接口
}

void Bit::Set(int x, int y, BOOL bFlog )
{
    x = x / m_nScale;                                 //每隔m_nScale采样
    y = y / m_nScale;
    unsigned char &c = m_pBits[y * m_nXBytes + x/8]; //获得某字符的引用,注意赋值方式,否则
    unsigned char d = 0x80;                           //后面改了白该。
    d = d >>(x%8);                                    //根据X值得不同,首位右移相应位数。移位
                                                       // 使得每个节点对应一位。 
    if(bFlog)
    {
        c|=d;                                         //把字符C与X相应的位置为1

    }
    else
    {
        d = ~d;                                       //和某节点对应的位为0,其余位为1
        c &= d;                                     //把字符C与X相应的位置为0

    }

}

void Bit::Reset()
{
    memset(m_pBits, 0, m_nXBytes * m_nZRows);

}

BOOL Bit::IsTrue(int x, int y)
{
   x = x/m_nScale;
   y = y/m_nScale;
   unsigned char c = m_pBits[y*m_nXBytes+x/8];                     //这次不是引用,想想为什么
   unsigned char d = 0x80;                                           
   c = c << (x%8);                                                   //为什么不是d移位?
   return c&d;            //把与X对应的位返回,其余位为0


}
//该函数得到字符包含包含8个节点的标志,必须根据X的值进行移位方能找到对应的节点,这次是取得标识而不是设置标识,故不用引用。c移位而不是d移位,是为了把标识移到首位。然后和0x80进行位与操作得到BOOL值。d移位操作效果是一样的,但不是左移而是右移。

LOD地形根据视点的变化决定是否进行网格分割,因此系统应设计一个视点类,来管理视点相关的数据。这节介绍的视点类是通用的,在很多网站都可下到这个类的代码,它可以用在OPENGL编程的各个场合,当然朋友也可根据需要自己增加相应功能!
/***********************************************************************
*    Copyrights Reserved by QinGeSoftware
*    Author : Qinge
*    Filename : Camera.h 1.0
*    Date: 2008-1-10
************************************************************************/
#pragma once
#include "Vector3.h"
class Camera
{
public:
    Camera(void);
    virtual ~Camera(void);
public:
    CVector3 GetPosition(){return m_vPosition;}                        //获得摄像机位置
    CVector3    GetView(){return m_vView;}                             //获得视线目标点
    CVector3 GetUpVector() {return m_vUpVector;}                       //获得向上方向
    CVector3 GetStrafe() {return m_vStrafe;}                           //获得平移方向的单位向量

    void PosotionCamera(float positionX, float positionY, float positionZ,
                         float viewX,     float viewY,     float viewZ,
                        float upVectorX, float upVectorY, float upVectorZ); //初始化摄像机
    void RotateView(float angle, float X, float Y, float Z);    //绕(x,y,z)旋转angle
    void SetViewByMouse();                                         //通过鼠标旋转场景
    void RotateAroundPoint(CVector3 vCenter, float X, float Y, float Z);   //绕点旋转
    void StrafeCamera(float speed);                                        //平移摄像机
    void MoveCamera(float speed);                                        //沿视线方向移动摄像机
    void Look();                                                    //设置视点相当于glLookAt()
    void Update();                                                       //更新视点位置。
    void CheckForMovement();                                           //检查是否有视点变量更新
private:
    CVector3 m_vPosition;       //摄像机视点
    CVector3 m_vView;           //摄像机视线
    CVector3 m_vUpVector;       //摄像机向上方向
    CVector3 m_vStrafe;        //摄像机平移
    const float fSpeed;        //摄像机移动速度
};


/***********************************************************************
*    Copyrights Reserved by QinGeSoftware
*    Author : Qinge
*    Filename : Camera.cpp 1.0
*    Date: 2008-1-10
************************************************************************/
#include "StdAfx.h"
#include "Camera.h"

Camera::Camera(void):fSpeed(5.0f)
{

m_vPosition = CVector3(0,0,0);
m_vView    = CVector3(0.0,1.0,0.5);
m_vUpVector = CVector3(0.0,0.0,1.0);

}

Camera::~Camera(void)
{
}


void Camera::PosotionCamera(float positionX, float positionY, float positionZ, float viewX, float viewY, float viewZ, float upVectorX, float upVectorY, float upVectorZ)
{
   m_vPosition = CVector3(positionX, positionY+200, positionZ);
   m_vView     = CVector3(viewX, viewY, viewZ);
   m_vUpVector = CVector3(upVectorX, upVectorY, upVectorZ);
}

void Camera::SetViewByMouse()
{
    CPoint m_CurPt,m_PrePt;
    HDC hDC = ::GetDC(NULL);
    float angleY, angleZ;
    CVector3 m_uAixs, m_vViewDire;
    unsigned long WIDTH, HEIGHT;

    WIDTH =::GetDeviceCaps(hDC,HORZRES);                //获得屏幕分辨率
    HEIGHT =::GetDeviceCaps(hDC,VERTRES);                //
    
    ::GetCursorPos(&m_CurPt);
    m_PrePt.x = WIDTH >>1;                                //分辨率/2
    m_PrePt.y = HEIGHT >> 1;
    ::SetCursorPos(m_PrePt.x, m_PrePt.y);                //固定光标在屏幕中心

    angleY = (m_CurPt.x - m_PrePt.x    )/1000.0;            //根据鼠标移动距离确定旋转角度
    angleZ = (m_CurPt.y - m_PrePt.y )/1000.0;            //

    m_vViewDire = m_vView - m_vPosition;
    m_uAixs = m_vViewDire.CrossProduct(m_vViewDire,m_vUpVector);   //得到平移向量
    m_uAixs = m_uAixs.Normalize(m_uAixs);

    RotateView(angleZ, m_uAixs.x, m_uAixs.y, m_uAixs.z);           //绕任意轴旋转
    RotateView(angleY,0,1,0);                                       //绕y轴旋转



}

void Camera::RotateView(float angle, float x, float y, float z)
{
    CVector3 vNewView;

    
    CVector3 vView = m_vView - m_vPosition;    //视线方向
    
    float cosTheta = (float)cos(angle);
    float sinTheta = (float)sin(angle);
    //下面就是一个数学公式
    vNewView.x = (cosTheta + (1 - cosTheta) * x * x)        * vView.x;
    vNewView.x += ((1 - cosTheta) * x * y - z * sinTheta)    * vView.y;
    vNewView.x += ((1 - cosTheta) * x * z + y * sinTheta)    * vView.z;

    vNewView.y = ((1 - cosTheta) * x * y + z * sinTheta)    * vView.x;
    vNewView.y += (cosTheta + (1 - cosTheta) * y * y)        * vView.y;
    vNewView.y += ((1 - cosTheta) * y * z - x * sinTheta)    * vView.z;

    vNewView.z = ((1 - cosTheta) * x * z - y * sinTheta)    * vView.x;
    vNewView.z += ((1 - cosTheta) * y * z + x * sinTheta)    * vView.y;
    vNewView.z += (cosTheta + (1 - cosTheta) * z * z)        * vView.z;
        
    m_vView = m_vPosition + vNewView;           //视点+新向量=新视线目标点
}

void Camera::StrafeCamera(float speed)
{
    
                                                //给视线目标点,视点增加一个增量
    m_vPosition.x += m_vStrafe.x * speed;
    m_vPosition.z += m_vStrafe.z * speed;
    
    m_vView.x += m_vStrafe.x * speed;
    m_vView.z += m_vStrafe.z * speed;
}

void Camera::MoveCamera(float speed)
{
    CVector3 vVector = m_vView - m_vPosition;
    vVector = vVector.Normalize(vVector);
    
    m_vPosition.x += vVector.x * speed;        //沿视线方向移动 
    m_vPosition.z += vVector.z * speed;        // 
    m_vView.x += vVector.x * speed;            // 
    m_vView.z += vVector.z * speed;            // 
}

void Camera::Update() 
{
    
    CVector3 vCross =m_vView.CrossProduct(m_vView - m_vPosition, m_vUpVector);
    m_vStrafe = vCross.Normalize(vCross);

    SetViewByMouse();
    CheckForMovement();

}
void Camera::CheckForMovement()                           // 上下左右移动视点
{
    if(GetKeyState(VK_UP) & 0x80 || GetKeyState('W') & 0x80)
    {                

        MoveCamera(fSpeed);                
    }

    if(GetKeyState(VK_DOWN) & 0x80 || GetKeyState('S') & 0x80)
    {            

        MoveCamera(-fSpeed);                
    }

    if(GetKeyState(VK_LEFT) & 0x80 || GetKeyState('A') & 0x80) 
    {            

        StrafeCamera(-fSpeed);
    }

    if(GetKeyState(VK_RIGHT) & 0x80 || GetKeyState('D') & 0x80)
    {            

        StrafeCamera(fSpeed);
    }    
}
void Camera::Look()                            //等于gluLookAt()
{
    gluLookAt(m_vPosition.x, m_vPosition.y, m_vPosition.z,    
            m_vView.x,    m_vView.y,     m_vView.z,    
            m_vUpVector.x, m_vUpVector.y, m_vUpVector.z);
}
世界坐标系向观察坐标系的转换

假如任何形体都放在世界坐标系中,那么计算是相当复杂的,为了简化计算,我们需要把形体从世界坐标系转到观察坐标系中。观察坐标系的原点在是世界坐标系的位置为Eye,Z轴与观察方向一致(从Eye出发到At点的向量)如图4-1所示:

                                                                        image  

 

                                                                            图4-1

 

假设观察坐标系的坐标轴分别以单位向量xaxis,yaxis,zaxis,则:

                                                               xaxis= normal (At-Eye);

                                                               yaxis= normal (cross(Up,zaxis));

                                                               zaxis= normal (zaxis,xaxis);

假设世界坐标系中任意一点P的坐标(x,y,z),在观察坐标系中的坐标(x',y',z')。

x' = (P-Eye)* xaxis = x*xaxis.x + y* xaxis.y + z * xaxis.z - xaxis*Eye

y' = (P- Eye)*yaxis = x*yaxis.x + y* yaxis.y + z * yaxis.z - yaxis*Eye

z'= (P- Eye)*zaxis = x*zaxis.x + y* zaxis.y + z * zaxis.z - zaxis*Eye

 

                                    (x',y',z',1) = (x,y,z,1)*2

所以从世界坐标系向观察坐标系变换的矩阵为2

 

(二)齐次裁剪透视投影变换

真实的物体是三维的,但是计算机屏幕是二维的,必须把三维物体投影到屏幕平面上,而且还要保存深度信息,这个变换过程称为投影变换,如图4-2所示

                                                                 3

                                                                                                    图4-2

假设视截体Y方向的张角fov,近平面Zn,远平面的Zf,近平面的宽高比aspect,现在可以直到近平面的方程z=Zn,远平面 z=Zf。

                                                                    4

                                                                                                      图4-3

由图4-3可以看出,视截体的顶面方程为y=z*tan(fov/2);底面方程=-z*tan(fov/2);视截体的右侧面x=cot(fov/2)*aspect*z.

左侧面方程x=-cot(fov/2)*aspect*z.

首先寻求把顶面y = z*tan(fov/2) 转换为y'=1,y'=k*y ,k=cot(fov/2)*y/z就是满足条件的变换,底面变换也是这个表达式。

右侧面x = cot(fov/2)*aspect*z,转换为x'=1, x'=p*x, 从而p=(tan(fov/2)/aspect)/z(左侧面表达式相同).

最后寻求把近平面Zn转换为z'=0;Zf转换为z'=1.   z'= r*z + s.于是r* Zn + s =0,r*Zf + s =1,由此求出 r= /(Zf-Zn), s= -Zn/(Af-Zn).

透视投影变换矩阵=

5

 

(三)视截体平面的计算

根据模型变换矩阵和投影变换矩阵,可以计算出视截体的6个平面。世界坐标系中的视截体在模型变换和透视投影变换后,成为观察坐标系中的[-1,1]*[-1,1]*[0,1]。设模型变换A,投影变换B,M=A*B,视截体的方程:ax+by+cz+d=0。该平面在观察坐标系中的形式为a'x'+b'y'+c'z'+d'=0.

(x',y',z',1) = (x,y,z,1)M

(x,y,z,1)(a,b,c,d)(转置)=0

(x',y',z',1)(a',b',c',d')(转置) = 0

可得:(x,y,z,1)M(a',b',c',d')(转置) = 0

(a,b,c,d)(转置)= M (a',b',c',d')(转置)

a=M11a'+M12b'+M13c'+M14d'

b=M21a'+M22b'+M23c'+M24d'

c=M31a'+M32b'+M33c'+M34d'

d=M41a'+M42b'+M43c'+M44d'

视截体的6个平面的法向量均指向视截体内部,视截体的左侧面leftplane   观察坐标系中的左侧面x+1=0 ,代入上式可得视截体左侧面的系数

a=M11+M14

b=M21+M24

c=M31+M34

d=M41+M44

右侧面的方程1-x=0;系数

a=M14-M11

b=M24-M21

c=M34-M31

d=M44-M41

同理:顶面系数

a=M14-M12

b=M24-M22

c=M24-M32

d=M44-M42

底面系数

a=M12+M14

b=M22+M24

c=M32+M34

d=M42+M44

近平面系数:

a=M13

b=M23

c=M33

d=M43

远平面系数:

a=M14-M13

b=M24-M23

c=M34-M33

d=M44-M43

 

上述内容是涉及视截体计算的数学基础,下一节实战视截体编程

android 蓝牙通讯demo android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。 立即下载

相关推荐

在带有Intel Arc GPU的Windows上安装IPEX-LLM

本文将介绍在 Intel Arc GPU 环境下安装 IPEX-LLM。

wux_labs的博客 1636

简单快速的地形LOD连续变形

来源:gameres.com 作者:佚名  在地形渲染中为了减轻渲染负担其中一个技术是就LOD,但其带了的一个问题就是会产生地形“跳动”,因为地形的LOD精度发生变化时镶嵌的密度也发生了 变化。要解决这个问题有一个方法就是当高精的模型向底精模型变化时不是突然变化过去的,而是慢慢渐变而来,这样可以极大的减少“跳动”。通过设置适当的渐 变距离可以做到让观察者感觉不到地形的变化。   关于这个问

Only me 2281

WorkVisual传输程序报错_发现一个内部错误

WorkVisual传输程序报错_发现一个内部错误

qq_16401025的博客 2458

lod地形

最近在看OGRE怎样载入地形的内容,因为terrain.cfg中涉及了很多的LOD(细节层次)的问题,看得我一把鼻涕一把眼泪的,所以就想说先看看LOD地形再去研究ogre本身地形实现的具体操作应该会好一些,主要资料参考的是曾凡喜,周炜,潘运亮等的《Direct3D 实时渲染技术》这本书,其对于用四叉树实现的LOD地形有比较详细的描述。 【LOD出现原因】          由于大的地形绘制需

debugconsole的专栏 3638

软件工程大作业——图书管理系统/图书个性化推荐与实现系统

软件工程期末大作业,图书管理系统,包含ER图、程序流程图、属性图、结构图

2401_82857325的博客 3649

MATLAB新手也能懂:用MATPOWER 8.0b搞定电力系统潮流计算(附case9实战代码)

本文详细介绍了如何使用MATPOWER 8.0b在MATLAB中进行电力系统潮流计算,特别适合新手入门。通过case9实战案例,讲解了从安装配置到运行牛顿-拉夫逊法潮流计算的全过程,包括结果分析和常见问题处理,帮助读者快速掌握这一电力系统分析的核心技能。

weixin_26757925的博客 381

LOD地形渲染技术概述

参考文章 http://blog.sina.com.cn/s/blog_5e3213f30100zxet.html LOD技术简述 http://blog.sina.com.cn/s/blog_458f87120100q9eg.html LOD技术概述 http://my.oschina.net/u/997451/blog/122649 LOD裂缝问题解决方法 http://

踏莎行的博客 1万+

别再手动写JSON了!用Node-RED OPC UA节点5分钟搞定楼宇温湿度数据采集

本文介绍了如何利用Node-RED和OPC UA节点快速实现楼宇温湿度数据的自动化采集与JSON格式转换。通过可视化工具Node-RED,开发者无需编写复杂代码,5分钟内即可完成从传感器到数据输出的全流程配置,大幅提升智慧楼宇和工业物联网项目的实施效率。

weixin_30368405的博客 433

LOD层次细节算法-大规模实时地形的绘制

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_33911824的博客 639

NVMe-MI --- Message Servicing Model(消息服务模型)

本文主要介绍NVMe-MI消息服务模型,两个主要类别是请求消息和响应消息。并介绍带外机制消息服务状态机。

智小星的博客 2014

华为OD机试真题 新系统2026-04-08 C语言 实现【直捣黄龙】

小王在玩一款叫做直捣黄龙的小游戏,在该游戏中他需要从入口位置进入敌营,绕过哨兵的层层封锁,达到敌军司令部实施斩首行动。 敌军阵营是一个n*n的矩阵,入口在坐标(0,n/2),敌军司令部在坐标(n-1,n/2),每个哨兵警戒以自己为中心的9宫格,一旦被哨兵发现则行动失败。

MISAYAONE的博客 184

最新-基于四叉树的LOD地形设计

  上次说过要在这里把最新的地形设计写出来,不过一直没时间写,也想画些UML图,但没工具画,呵呵,只能通过手写了。希望大家看得明白吧。        基本设计思想:        主要有以下几个类,        CTerrainBlock,地形一个block,每个对象拥有自己的顶点缓冲和相对应的LOD值。        HeightMap类,读入高度图,并根据策略创建一定数量的CTerrainB...

weixin_34254823的博客 303

【x265编码器】章节6——x265的码率控制

对于CRF模式而言,右边这部分是是固定值m_rateFactorConstant,在初始化的时候确定,跟分辨率,qCompress这个参数是外部可设参数,默认值0.6,因此QP的选择只跟编码复杂度有关,跟码率无关,编码复杂度越高,QP值越高,因此可以一定程度上说CRF模式是恒定质量的编码模式。其中Complex表示当前帧的编码复杂度,x265中用lookahead模块计算的SATD作为衡量当前帧的复杂度,c为模型参数,qscale是率失真优化中的拉格朗日乘子,R为编码当前帧需要的比特数。

vcvdv123的博客 1万+

LOD地形设计(六)

这一节开始把前面介绍的内容放入视图类中,完成地形的显示渲染工作。我们在视图类内设置了渲染设备,摄像机,视截体,以及地形变量。 /**************************************************************************** *    Copyright Reserved by Qinge *    Filename :LODTerrainV

qinmelody的专栏 1452

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

LOD地形设计(二)

  自从LOD地形第一节推出以来,受到不少朋友的关注,本人真是受宠若惊,无奈自己水平有限,怕写不好让大家对自己失望,我只能勉为其难,努力去写,同时欢迎高人能手给于指正,大家共同学习,共同提高!LOD地形的四叉树算法原理就是对地形进行四叉树分割,同时检查该节点是否位于视截体内部,如果在视截体内部且满足视距,周围点高程误差等条件时,则对该节点继续分割,否则不予分割。其中重点是视截体的计算,以及

qinmelody的专栏 1080

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

LOD地形设计(三)

  LOD地形根据视点的变化决定是否进行网格分割,因此系统应设计一个视点类,来管理视点相关的数据。这节介绍的视点类是通用的,在很多网站都可下到这个类的代码,它可以用在OPENGL编程的各个场合,当然朋友也可根据需要自己增加相应功能!/************************************************************************    Copyr

qinmelody的专栏 1322

LOD地形设计(一)

   在大规模的三维场景中,不可能一次渲染所有的三角形,而且即使能做到这点,全部渲染也是不可取的。常用的做法就是采用LOD,即层次细节模型。距离视点较远的三角形可以大一些,粗糙一些,而距离视点较近的三角形则应有较为细腻地表现。常用的LOD地形的实现算法是四叉树算法,即对二维地平面进行分割时,每次把正方形分成4个等分的小正方形,直到分割的正方形尺寸达到某个阈值为止,然后对不能再分的正方形进行三角...

Windows SDK 358

引擎设计跟踪 地形LOD的改进

虽然地形已经有LOD和形变(geomorphing, 这里简称morphing)来进行LOD的渐变,从而避免bump, 但是如果LOD级别过多,远处的高山就会严重丢失细节,比如变成尖尖的凸起,非常丑陋,这是morphing无法解决的。 解决一种方式是使用强制的固定LOD (fixed LOD),如果一个block的高度(maxH)或者高度比率(dH/dX)超过一定阈值,就使用固定的高细节的LOD...

weixin_30362233的博客 274

LOD地形设计(五)

视截体是计算机图形学的关键内容之一,涉及裁剪、投影等内容,视截体分为长方体和平头椎体两种,前者关乎平行投影,后者关乎透视投影。但不论是哪一种,视截体都有六个面,在上节内容中,我介绍了视截体6个面求解的数学推导,这一节实现视截体的实际编程。视截体类应该至少包含计算6个面的函数,判断一个正方体,球体,点是否在视截体内部的函数,平面法线标准化的函数,以及存储视截体各个面的系数的二维矩阵。下面是视

qinmelody的专栏 904

LOD地形设计(四)

(一)世界坐标系向观察坐标系的转换 假如任何形体都放在世界坐标系中,那么计算是相当复杂的,为了简化计算,我们需要把形体从世界坐标系转到观察坐标系中。观察坐标系的原点在是世界坐标系的位置为Eye,Z轴与观察方向一致(从Eye出发到At点的向量)如图4-1所示:                                                                       

qinmelody的专栏 776

毕业设计——阶段性成果展示

    3月中旬开始弄毕业设计,现在弄了一部分了,进度比预计的慢了点点,但是剩余的时间还是很充足的。    都没使用shader,只大概晓得,没仔细研究,估计很费时间。用了RTT(渲染到纹理)。 这是LOD地形的用的简单的Geomipmap,贴图光照什么的还没弄。  天空穹也弄了天空盒的,动态云彩还没加,没纹理。  地形不同块的平滑缝合衔接,2个

HoneyCat的月光浴场 8921
上一篇: BTree,B-Tree,B+Tree,B*Tree都是什么
下一篇: Intel体系MMX指令
b2b160
博客等级 码龄20年 2408粉丝 96原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值