日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

OpenGL三维小球碰撞实现方法(glm、glfw)

發(fā)布時(shí)間:2024/8/1 编程问答 56 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OpenGL三维小球碰撞实现方法(glm、glfw) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

小萌新剛開(kāi)始學(xué)OpenGL,想做一個(gè)三維小球碰撞模擬。一開(kāi)始試了好多寫法,但都有問(wèn)題,不斷改進(jìn),終于完成了,感覺(jué)有必要記錄一下。

首先,為了能夠無(wú)限添加小球,我采用鏈表結(jié)構(gòu),并定義了小球結(jié)構(gòu)體,其中包含小球的各個(gè)物理屬性。

struct ball {glm::vec3 position; //球心坐標(biāo)glm::vec3 speed; //速度矢量glm::vec3 color;//可有可無(wú)float r; //小球半徑float m; //小球質(zhì)量struct ball* next; };

在渲染循環(huán)里面加上p->position += p->speed * deltaTime;實(shí)現(xiàn)小球移動(dòng)。deltatime為渲染的時(shí)間間隔。

然后就是簡(jiǎn)單的循環(huán),用來(lái)篩選發(fā)生碰撞的小球。

struct ball* p = head; struct ball* q;while (p != NULL) { q = p->next;while ((q != NULL)) {if ((veclength(p->position - q->position) <= (p->r + q->r))) {}q = q->next;}p = p->next;}

接著最關(guān)鍵的就是發(fā)生碰撞的兩個(gè)小球的代碼了。

一開(kāi)始,我嘗試先在草稿紙上,把碰撞后的速度算出來(lái)。然后if他們之間的距離小于半徑之和,就給他們的速度附上碰撞后的值。

然而,當(dāng)我滿懷期待地運(yùn)行的時(shí)候,發(fā)現(xiàn)只有少數(shù)小球符合要求,大多數(shù)小球剛一碰撞,就直接飛走了。于是我只好回來(lái)再看代碼,發(fā)現(xiàn)可能是因?yàn)橹貜?fù)判定。也就是賦值完速度之后的下一幀,他們可能還沒(méi)有分離,這時(shí)候又會(huì)給速度賦值一次。

于是我添加了一個(gè)開(kāi)關(guān),當(dāng)兩個(gè)球分離之前,只會(huì)執(zhí)行一次碰撞速度賦值。

當(dāng)我運(yùn)行的時(shí)候又發(fā)現(xiàn),當(dāng)兩個(gè)球未分離的時(shí)候,如果有第三個(gè)球撞上來(lái),那第一個(gè)球和第二個(gè)球就會(huì)發(fā)生重合。這也是不對(duì)的。

覺(jué)得這個(gè)問(wèn)題過(guò)于復(fù)雜的我決定另辟蹊徑。想到了一種更接近自然界本質(zhì)的方法,那就是彈力。小球碰撞速度的改變,終究還是因?yàn)樗麄冎g的相互作用力,給了他們加速度。

于是我在小球?qū)傩岳锩嫣砑恿思铀俣萭lm::vec3 a,并且在渲染循環(huán)里面添加了p->speed += p->a * deltaTime;當(dāng)小球發(fā)生碰撞時(shí),根據(jù)質(zhì)量反比,賦給他們分離的加速度99999.0f/m。

if ((veclength(p->position - q->position) <= (p->r + q->r))) {p->a = glm::normalize(p->position - q->position) * 999999.0f / p->m;q->a = glm::normalize(q->position - p->position) * 999999.0f / q->m;}

經(jīng)過(guò)不斷實(shí)驗(yàn),我發(fā)現(xiàn)雖然這樣解決了上述問(wèn)題,但是又出現(xiàn)了新的問(wèn)題:

1、當(dāng)兩個(gè)質(zhì)量較小的球,即使以很慢的速度碰撞,碰撞之后速度會(huì)變得很大。

2、當(dāng)多個(gè)小球豎直疊在一起時(shí),會(huì)發(fā)生嚴(yán)重的彈跳。

3、同一個(gè)小球無(wú)法同時(shí)和多個(gè)小球同時(shí)碰撞

針對(duì)上述問(wèn)題我又進(jìn)行了改進(jìn)。

對(duì)于問(wèn)題1、2,是因?yàn)楫?dāng)兩個(gè)小球分離或者接觸的瞬間,和加速度改變的瞬間有誤差。這是由于小球的移動(dòng)終究是離散的,不是移動(dòng)的。于是我想到了把恒力改為隨小球距離變化的保守力。并且當(dāng)小球剛接觸的時(shí)候,這個(gè)力得趨于0,并且要隨距離減少快速增加(防止球質(zhì)量過(guò)大時(shí)吞球)。于是我選擇了指數(shù)函數(shù),A^x^2-1.具體需要自己調(diào)試。

對(duì)于問(wèn)題三,是因?yàn)橐婚_(kāi)始加速度用的是=,不能疊加,于是我改成了+=。完美(我覺(jué)得)解決了上述問(wèn)題。

此外,由于自然界不存在完全彈性碰撞,因此我加了一個(gè)隨速度阻尼,保證熵增。

最終代碼如下:

void BALLMOVE() {struct ball* p = head;struct ball* q;while (p != NULL) { p->speed += p->a * deltaTime;p->speed += 30.0f * deltaTime * glm::vec3(0, -1, 0);//這是重力加速度p->position += p->speed * deltaTime;q = p->next;p->a = glm::vec3(0, 0, 0);while ((q != NULL)) {if ((veclength(p->position - q->position) <= (p->r + q->r))) {float k = fabs(veclength(p->position - q->position) - (p->r + q->r));float kn = pow(7,k*k)-1;p->a += kn*(glm::normalize(p->position - q->position) * 999999.0f - (p->speed - q->speed) * 100000.0f) / p->m;q->a += kn*(glm::normalize(q->position - p->position) * 999999.0f - (q->speed - p->speed)*100000.0f) / q->m; }q = q->next;}p = p->next;}}

將這個(gè)函數(shù)插入到渲染循環(huán)里面,就可以實(shí)現(xiàn)小球碰撞啦。

?

總結(jié)

以上是生活随笔為你收集整理的OpenGL三维小球碰撞实现方法(glm、glfw)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。