用線段繪制球體(three.js webgl_lines_spere例子)

用線段繪制球體(three.js webgl_lines_spere例子)

Three.js中的webgl_lines_sphere例子使用線段渲染出3D球體滚局,效果十分有趣。

實現(xiàn)過程

渲染過程比較簡單,先構(gòu)造出單位球體上(unit sphere)的點羡洛,隨后將點再對應(yīng)半徑上隨機伸縮坐標柑司,每個半徑上相鄰的這兩個點構(gòu)成線段,為線段指定色彩后即可渲染出基本的lines sphere(線段球體)拷呆。

這里闲坎,我們模仿webgl_lines_sphere例子,使用C++和OpenGL ES 3.0獲得了如下的渲染效果茬斧,iOS版本實現(xiàn)源碼可以從github上獲取腰懂。

lines_sphere_anim.gif

用線段繪制一個基本的3D球體

這一過程的關(guān)鍵在于使用線段代替頂點形成球形幾何體數(shù)據(jù)。首先啥供,我們使用隨機數(shù)分別產(chǎn)生范圍為[-1..1]的[x,y,z]^t各個坐標部件的數(shù)值,然后把這些坐標看作矢量悯恍,并進行標準化。隨后伙狐,我們再將這些矢量的坐標看作點的坐標涮毫,那么這些點將位于中心為原點的單位球體之上。如此贷屎,我們就擁有了一個球體的頂點數(shù)據(jù)罢防,之后,再針對這個頂點沿著半徑方向(也是這個點的法線法線方向)向外在一定范圍內(nèi)隨機伸縮這個點形成單位球體外圍的點唉侄,將這個點和單位球體上同半徑的點連接為線段咒吐。這樣,我們就擁有了近似繪制球體的線段頂點數(shù)據(jù)属划。在渲染時恬叹,針對線段指定代表色彩和透明度的uniform變量即可渲染出一個線段球體。生成頂點數(shù)據(jù)的代碼如下:

vector<Cvec3f> createLinesSphereGeometry(float r){
    vector<Cvec3f> vertices;
    
    for(int i = 0; i < 1500; i++) {
        //生成范圍為[-1..1]的隨機坐標部件值
        float x = rand()/(RAND_MAX/2.0) - 1;
        float y = rand()/(RAND_MAX/2.0) - 1;
        float z = rand()/(RAND_MAX/2.0) - 1;
        
        Cvec3f vertex(x,y,z);
        
        //標準化后同眯,這些隨機點就變成了單位球體上的點绽昼,經(jīng)過縮放后,可以變成了不同尺寸球面上的點
        vertex.normalize();
        //縮放為半徑為r的球體
        vertex *= r;
        
        vertices.push_back(vertex);
        
        //在當前半徑為r的球體上的點须蜗,被乘以固定方位的隨機因子
        Cvec3f vertexOuter = vertex * ((rand()/(float)RAND_MAX) * 0.09 + 1 );
        
        vertices.push_back(vertexOuter);
        
    }
    
    return vertices;
}

球體的多重繪制和移動

webgl_lines_sphere例子中進行了多重(9層)球體繪制硅确,并且讓內(nèi)層的球體隨時間縮放變換,同時進行逆時針旋轉(zhuǎn)明肮,外側(cè)的球體則只進行順時針旋轉(zhuǎn)菱农。還有,內(nèi)外側(cè)球體的色彩和透明度也進行對應(yīng)的設(shè)置柿估。整體的展示效果比較有趣循未。部分代碼如下:


struct RenderingParameter{
    float scale;
    string color;
    float opacity;
};
//球體的初始大小,色彩和透明度信息
vector<RenderingParameter> parameters = {{0.25,"0xff7700", 1}, {0.5, "0xff9900", 1}, {0.75, "0xffaa00", 0.75}, {1, "0xffaa00", 0.5}, {1.25, "0x000833", 0.8},
    {3.0, "0xaaaaaa", 0.75}, {3.5,"0xffffff",0.5}, {4.5, "0xffffff", 0.25}, {5.5, "0xffffff", 0.125}};

//球體的初始化過程代碼
shared_ptr<Geometry> geometry;
vector<Cvec3f> lineSphereVertices = createLinesSphereGeometry(300.0);
geometry.reset(new Geometry(&lineSphereVertices[0],(int)lineSphereVertices.size()));
   
mainCamera.reset(new PerspectiveCamera());
mainCamera->updatePorjectonMatrix();
    
Cvec3 translationVec = Cvec3(0,0,-550);
    
for(size_t i=0;i<parameters.size();i++){
    shared_ptr<LinesSphereModel> ls = make_shared<LinesSphereModel>(LinesSphereModel(geometry,simpleShaderState));
        
    RenderingParameter para=parameters[i];
    //每個球體的初始大小
    ls->scale = Cvec3(para.scale,para.scale,para.scale);
    originalScale[i]=para.scale;
    ls->position = translationVec;
        
    //每個球體的色彩    
    Cvec3 lColor = hexStringToRGB(para.color);
    ls->lineColor = lColor;
        
    //每個球體的初始選擇角度(圍繞y軸)    
    float angleY = rand()/(RAND_MAX/180.0);
    ls->rotation = Cvec3(0,angleY,0);
        
    lsModels.push_back(ls);
}

//每次繪制時球體的運動設(shè)置

//全局變量秫舌,在每幀繪制時增加固定數(shù)量
delta+=0.1;

for(int i=0;i<lsModels.size();i++){
//        time_t timeInMill = time(NULL);
//        double time = (double)timeInMill/10;

    shared_ptr<LinesSphereModel> lsModel = lsModels[i];

    //設(shè)置內(nèi)外圈球體的旋轉(zhuǎn)角度
    int factor = i<4?(i+1):-(i+1);
    long rotationY = delta*(factor);
    lsModel->rotation = Cvec3(0,rotationY,0);

      //對內(nèi)圈球體在特定范圍內(nèi)以正弦方式循環(huán)縮放
    if (i < 5){
        float scale = originalScale[i] * (i/5.0 + 1) * (1 + 0.5 * sin(7 * delta * 0.05));
        lsModel->scale = Cvec3(scale,scale,scale);
    }

    lsModel->setPerspectiveCamera(mainCamera);
    lsModel->UpdateMatrixWorld();
    lsModel->Render();
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末的妖,一起剝皮案震驚了整個濱河市烙丛,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌羔味,老刑警劉巖河咽,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異赋元,居然都是意外死亡忘蟹,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門搁凸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來媚值,“玉大人,你說我怎么就攤上這事护糖∪烀ⅲ” “怎么了?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵嫡良,是天一觀的道長锰扶。 經(jīng)常有香客問我,道長寝受,這世上最難降的妖魔是什么坷牛? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮很澄,結(jié)果婚禮上京闰,老公的妹妹穿的比我還像新娘。我一直安慰自己甩苛,他們只是感情好蹂楣,可當我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著讯蒲,像睡著了一般痊土。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上爱葵,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天施戴,我揣著相機與錄音反浓,去河邊找鬼萌丈。 笑死,一個胖子當著我的面吹牛雷则,可吹牛的內(nèi)容都是我干的辆雾。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼月劈,長吁一口氣:“原來是場噩夢啊……” “哼度迂!你這毒婦竟也來了藤乙?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤惭墓,失蹤者是張志新(化名)和其女友劉穎坛梁,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體腊凶,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡划咐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了钧萍。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片褐缠。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖风瘦,靈堂內(nèi)的尸體忽然破棺而出队魏,到底是詐尸還是另有隱情,我是刑警寧澤万搔,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布胡桨,位于F島的核電站,受9級特大地震影響瞬雹,放射性物質(zhì)發(fā)生泄漏登失。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一挖炬、第九天 我趴在偏房一處隱蔽的房頂上張望揽浙。 院中可真熱鬧,春花似錦意敛、人聲如沸馅巷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽钓猬。三九已至,卻和暖如春撩独,著一層夾襖步出監(jiān)牢的瞬間敞曹,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工综膀, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留澳迫,地道東北人。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓剧劝,卻偏偏與公主長得像橄登,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容