Skip to content

Commit a3592f1

Browse files
committed
[up] README 水族馆和人体
1 parent db274ad commit a3592f1

File tree

127 files changed

+11025
-2
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

127 files changed

+11025
-2
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@
1313
-|-|-|
1414
光线追踪 | [源代码位置](./tinyraytracerYD) | <div align=center><img src="./result/tinyraytracer.jpg" width=200 ></div> |
1515
光栅渲染器 | [源代码位置](./tinyrendererYD) | <div align=center><img src="./result/africanhead.png" width=200 ></div> |
16-
OpenGL 拖尾、刀光、剑光、尾焰效果| [源代码位置](./streak) | <div align=center><img src="./result/streak.gif" width=150 ></div> |
16+
医疗人体3D展示系统 | [源代码位置](./moving-light-strip) | <div align=center><img src="./result/moving-light-strip.gif" width=150 ></div> |
17+
3D海洋馆(带鱼群骨骼动画)| [源代码位置](./streak) | <div align=center><img src="./result/wallpaper.gif" width=150 ></div> |
18+
OpenGL 拖尾、刀光、剑光、尾焰效果| [源代码位置](./wallpaper) | <div align=center><img src="./result/streak.gif" width=150 ></div> |
1719
3D-PLY文件读取曲率计算| [源代码位置](./3D-PLY) | <img src="./result/curvature.png" width=300> |
1820
3D-骨架提取| [源代码位置](./3D-skeleton) | <div align=center><img src="./result/skeleton.png" width=200></div> |
19-
虚化模糊场景(类似摄像机的人像效果)| [源代码位置](./blur-scene-gaussian--3d) | <img src="./result/blur-scene-gaussian--3d.jpg" width=300> |
21+
虚化模糊场景Blur(类似景深效果)| [源代码位置](./blur-scene-gaussian--3d) | <img src="./result/blur-scene-gaussian--3d.jpg" width=300> |
2022
人物透视X光效果| [源代码位置](./x-ray-scene_3d) | <img src="./result/x-ray-scene_3d.png" width=300> |
2123
OpenGL ES Uniform缓冲| [源代码位置](./opengles-uniform-buffer) | <div align=center><img src="./result/opengles-uniform-buffer.jfif" width=150></div> | |
2224
3D摄像机漫游| [源代码位置](./CameraRoam) | <img src="./result/CameraRoam.jfif" width=300> |

moving-light-strip/README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# 医疗人体3D展示系统
2+
3+
作者:憨豆酒(YinDou),yindou97@163.com,熟悉图形学,图像处理领域,经常更新的学习总结仓库:<https://github.com/douysu/person-summary> 如果对您有帮助还请帮忙点一个star,如果大家发现错误以及不合理之处,还希望多多指出。
4+
5+
- [我的Github](https://github.com/douysu)
6+
- [我的博客](https://blog.csdn.net/ModestBean)
7+
- [我的知乎](https://zhuanlan.zhihu.com/c_1218472587279433728)
8+
9+
# 介绍
10+
11+
为医疗项目APP接入3D人体展示模块,带移动光带效果
12+
13+
![](../result/moving-light-strip.gif)
14+
15+
# 开发
16+
17+
基于OpenGL ES 3.0 开发
18+
19+
# 运行
20+
21+
将代码,资源复制到Android Studio中,运行。

moving-light-strip/frag_body.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#version 300 es
2+
precision mediump float;
3+
//接收从顶点着色器过来的参数
4+
in vec3 gzqd; //总光照强度
5+
in vec3 vPosition;//传给片元的顶点位置
6+
out vec4 fragColor;//输出到的片元颜色
7+
uniform float lineWidth;//传入线的宽度
8+
uniform float lineBright;//传入线的亮度系数
9+
uniform float obY;//传入线的Y位置
10+
void main()
11+
{
12+
const float ALPHA=0.5f;//颜色的透明通道
13+
const vec3 PFColor=vec3(0.11764705,0.43137254,0.97647058);//皮肤的颜色
14+
const vec3 LineColor=vec3(0.11764705,0.43137254,0.97647058);//光带的颜色
15+
vec3 finalColor=PFColor*gzqd;//得到光照后皮肤颜色
16+
float factor=abs(vPosition.y-obY)/lineWidth;//利用数学公式将人体分为三段 光带,光带以上,光带已下,光带部分的值以线的位置对称
17+
factor=(1.0-smoothstep(0.0,1.0,factor));//利用Hermite差值转换值,光带部分为0~1,1~0光滑的数,光带以上,光带已下部分均为0
18+
fragColor=vec4(finalColor+LineColor*factor*lineBright,ALPHA+(1.0-ALPHA)*factor);//将皮肤颜色线条颜色传给片元,更改透明通道,身体为0部分即没有光带
19+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+
android:versionCode="1"
4+
android:versionName="1.0" package="com.bn.activty">
5+
<application android:icon="@drawable/icon" android:label="@string/app_name">
6+
<activity android:name="com.bn.activty.MainActivity"
7+
android:label="@string/app_name">
8+
<intent-filter>
9+
<action android:name="android.intent.action.MAIN" />
10+
<category android:name="android.intent.category.LAUNCHER" />
11+
</intent-filter>
12+
</activity>
13+
</application>
14+
<uses-sdk android:targetSdkVersion="21" android:minSdkVersion="18"></uses-sdk>
15+
</manifest>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#version 300 es
2+
precision mediump float;
3+
//接收从顶点着色器过来的参数
4+
in vec3 gzqd; //总光照强度
5+
in vec3 vPosition;//传给片元的顶点位置
6+
out vec4 fragColor;//输出到的片元颜色
7+
uniform float lineWidth;//传入线的宽度
8+
uniform float lineBright;//传入线的亮度系数
9+
uniform float obY;//传入线的Y位置
10+
void main()
11+
{
12+
const float ALPHA=0.5f;//颜色的透明通道
13+
const vec3 PFColor=vec3(0.11764705,0.43137254,0.97647058);//皮肤的颜色
14+
const vec3 LineColor=vec3(0.11764705,0.43137254,0.97647058);//光带的颜色
15+
vec3 finalColor=PFColor*gzqd;//得到光照后皮肤颜色
16+
float factor=abs(vPosition.y-obY)/lineWidth;//利用数学公式将人体分为三段 光带,光带以上,光带已下,光带部分的值以线的位置对称
17+
factor=(1.0-smoothstep(0.0,1.0,factor));//利用Hermite差值转换值,光带部分为0~1,1~0光滑的数,光带以上,光带已下部分均为0
18+
fragColor=vec4(finalColor+LineColor*factor*lineBright,ALPHA+(1.0-ALPHA)*factor);//将皮肤颜色线条颜色传给片元,更改透明通道,身体为0部分即没有光带
19+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#version 300 es
2+
precision mediump float;
3+
//接收从顶点着色器过来的参数
4+
in vec4 ambient;//顶点着色器传入的环境光强度
5+
in vec4 diffuse;//顶点着色器传入的散射光强度
6+
in vec4 specular;//顶点着色器传入的镜面光强度
7+
uniform vec4 organColor;//传入的器官颜色
8+
uniform float brightBreath;//传入的呼吸参数
9+
out vec4 fragColor;//输出到的片元颜色
10+
void main()
11+
{
12+
vec4 finalColor=vec4(organColor.r*brightBreath,organColor.g*brightBreath,organColor.b*brightBreath,organColor.a);//计算呼吸颜色
13+
fragColor = finalColor*ambient+finalColor*specular+finalColor*diffuse;//给此片元最终颜色
14+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#version 300 es
2+
uniform mat4 uMVPMatrix; //总变换矩阵
3+
uniform mat4 uMMatrix; //变换矩阵
4+
uniform vec3 uLightLocation; //光源位置
5+
uniform vec3 uCamera; //摄像机位置
6+
in vec3 aPosition; //顶点位置
7+
in vec3 aNormal; //顶点法向量
8+
//用于传递给片元着色器的变量
9+
out vec3 gzqd;//总光照强度
10+
out vec3 vPosition;//物体坐标系位置
11+
//定位光光照计算的方法
12+
vec4 pointLight(
13+
in vec3 normal,
14+
in vec3 lightLocation,
15+
in vec4 lightAmbient,
16+
in vec4 lightDiffuse,
17+
in vec4 lightSpecular
18+
){
19+
vec4 result=vec4(0.0);
20+
result=result+lightAmbient;
21+
vec3 normalTarget=aPosition+normal;
22+
vec3 newNormal=(uMMatrix*vec4(normalTarget,1)).xyz-(uMMatrix*vec4(aPosition,1)).xyz;
23+
newNormal=normalize(newNormal);
24+
vec3 eye= normalize(uCamera-(uMMatrix*vec4(aPosition,1)).xyz);
25+
vec3 vp= normalize(lightLocation-(uMMatrix*vec4(aPosition,1)).xyz);
26+
vp=normalize(vp);
27+
vec3 halfVector=normalize(vp+eye);
28+
float shininess=50.0;
29+
float nDotViewPosition=max(0.0,dot(newNormal,vp));
30+
result=result+lightDiffuse*nDotViewPosition;
31+
float nDotViewHalfVector=dot(newNormal,halfVector);
32+
float powerFactor=max(0.0,pow(nDotViewHalfVector,shininess));
33+
result=result+lightSpecular*powerFactor;
34+
return result;
35+
}
36+
void main()
37+
{
38+
gl_Position = uMVPMatrix * vec4(aPosition,1); //根据总变换矩阵计算此次绘制此顶点位置
39+
//得到最终的光照强度
40+
gzqd=pointLight(normalize(aNormal),uLightLocation,vec4(0.2,0.2,0.2,1.0),vec4(0.9,0.9,0.9,1.0),vec4(0.4,0.4,0.4,1.0)).rgb;
41+
//将物体位置传给片元着色器
42+
vPosition=aPosition;
43+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#version 300 es
2+
uniform mat4 uMVPMatrix; //总变换矩阵
3+
uniform mat4 uMMatrix; //变换矩阵
4+
uniform vec3 uLightLocation; //光源位置
5+
uniform vec3 uCamera; //摄像机位置
6+
in vec3 aPosition; //顶点位置
7+
in vec3 aNormal; //顶点法向量
8+
//用于传递给片元着色器的变量
9+
out vec4 ambient;//最终环境光
10+
out vec4 diffuse;//最终散射光
11+
out vec4 specular;//最终镜面光
12+
out vec3 vPosition;//物体坐标系位置
13+
//定位光光照计算的方法
14+
void pointLight(
15+
in vec3 normal,
16+
inout vec4 ambient,
17+
inout vec4 diffuse,
18+
inout vec4 specular,
19+
in vec3 lightLocation,
20+
in vec4 lightAmbient,
21+
in vec4 lightDiffuse,
22+
in vec4 lightSpecular
23+
){
24+
ambient=lightAmbient;
25+
vec3 normalTarget=aPosition+normal;
26+
vec3 newNormal=(uMMatrix*vec4(normalTarget,1)).xyz-(uMMatrix*vec4(aPosition,1)).xyz;
27+
newNormal=normalize(newNormal);
28+
vec3 eye= normalize(uCamera-(uMMatrix*vec4(aPosition,1)).xyz);
29+
vec3 vp= normalize(lightLocation-(uMMatrix*vec4(aPosition,1)).xyz);
30+
vp=normalize(vp);
31+
vec3 halfVector=normalize(vp+eye);
32+
float shininess=50.0;
33+
float nDotViewPosition=max(0.0,dot(newNormal,vp));
34+
diffuse=lightDiffuse*nDotViewPosition;
35+
float nDotViewHalfVector=dot(newNormal,halfVector);
36+
float powerFactor=max(0.0,pow(nDotViewHalfVector,shininess));
37+
specular=lightSpecular*powerFactor;
38+
}
39+
void main()
40+
{
41+
gl_Position = uMVPMatrix * vec4(aPosition,1); //根据总变换矩阵计算此次绘制此顶点位置
42+
vec4 ambientTemp, diffuseTemp, specularTemp; //存放环境光、散射光、镜面反射光的临时变量
43+
//得到最终的环境光散射光和镜面光
44+
pointLight(normalize(aNormal),ambientTemp,diffuseTemp,specularTemp,uLightLocation,vec4(0.1,0.1,0.1,1.0),vec4(0.7,0.7,0.7,1.0),vec4(0.3,0.3,0.3,1.0));
45+
ambient=ambientTemp;//传递给片元最终环境光
46+
diffuse=diffuseTemp;//传递给片元最终散射光
47+
specular=specularTemp;//传给片元最终镜面光
48+
vPosition=aPosition;//将物体位置传给片元
49+
}
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
package com.bn.activty;
2+
import android.app.Activity;
3+
import android.os.Bundle;
4+
import android.view.Gravity;
5+
import android.view.View;
6+
import android.view.ViewGroup;
7+
import android.view.Window;
8+
import android.view.WindowManager;
9+
import android.widget.AdapterView;
10+
import android.widget.BaseAdapter;
11+
import android.widget.LinearLayout;
12+
import android.widget.ListView;
13+
import android.widget.RadioButton;
14+
import android.widget.RadioGroup;
15+
import android.widget.TextView;
16+
17+
import com.bn.util.Constant;
18+
import com.bn.util.MyFunction;
19+
20+
21+
public class MainActivity extends Activity {
22+
private MySurfaceView mGLSurfaceView;//自己SurfaceView
23+
String organStr[]=new String[]{"骨骼","大脑","食道","肺","心脏","肝脏","胰脏","胆囊","胃","脾","肠","肾","膀胱"};//男生器官字符串
24+
String womanorganStr[]=new String[]{"骨骼","大脑","食道","肺","心脏","肝脏","胰脏","胆囊","胃","子宫","肠","肾","膀胱"};//女生器官字符串
25+
int oldSelect=14;//记录上次点击的值
26+
float colorRed[]=new float[]{1.0f,0.0f,0.0f,1.0f};//红色
27+
ListView ls;//器官的listView
28+
BaseAdapter ba;//男的Adapter
29+
BaseAdapter baWoman;//女的Adapter
30+
@Override
31+
protected void onCreate(Bundle savedInstanceState)
32+
{
33+
super.onCreate(savedInstanceState);
34+
//设置为全屏
35+
requestWindowFeature(Window.FEATURE_NO_TITLE);
36+
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN ,
37+
WindowManager.LayoutParams.FLAG_FULLSCREEN);
38+
//设置为横屏模式
39+
//setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
40+
setContentView(R.layout.main);
41+
mGLSurfaceView = new MySurfaceView(this);
42+
43+
//将自定义的SurfaceView添加到外层LinearLayout中
44+
LinearLayout ll=(LinearLayout)findViewById(R.id.main_liner);
45+
ll.addView(mGLSurfaceView);
46+
mGLSurfaceView.requestFocus();//获取焦点
47+
mGLSurfaceView.setFocusableInTouchMode(true);//设置为可触控
48+
//获得单选按钮
49+
RadioButton RadioMan=(RadioButton)this.findViewById(R.id.RadioMan);
50+
RadioButton RadioWoman=(RadioButton)this.findViewById(R.id.RadioWoman);
51+
//获得ListView
52+
ls=(ListView)this.findViewById(R.id.listOrgan);
53+
//男Adapter
54+
ba=new BaseAdapter()
55+
{
56+
@Override
57+
public int getCount() {
58+
return organStr.length;
59+
}
60+
61+
@Override
62+
public Object getItem(int arg0) { return null; }
63+
64+
@Override
65+
public long getItemId(int arg0) { return 0; }
66+
67+
@Override
68+
public View getView(int arg0, View arg1, ViewGroup arg2) {
69+
LinearLayout ll=new LinearLayout(MainActivity.this);
70+
ll.setOrientation(LinearLayout.VERTICAL);//设置朝向
71+
//初始化TextView
72+
TextView tv=new TextView(MainActivity.this);
73+
tv.setText(organStr[arg0]);
74+
tv.setTextSize(24);//设置字体大小
75+
tv.setTextColor(MainActivity.this.getResources().getColor(R.color.white));//设置字体颜色
76+
tv.setGravity(Gravity.LEFT);//靠左
77+
ll.addView(tv);
78+
return ll;
79+
}
80+
};
81+
//女Adapter
82+
baWoman=new BaseAdapter()
83+
{
84+
@Override
85+
public int getCount() {
86+
return womanorganStr.length;
87+
}
88+
89+
@Override
90+
public Object getItem(int arg0) { return null; }
91+
92+
@Override
93+
public long getItemId(int arg0) { return 0; }
94+
95+
@Override
96+
public View getView(int arg0, View arg1, ViewGroup arg2) {
97+
LinearLayout ll=new LinearLayout(MainActivity.this);
98+
ll.setOrientation(LinearLayout.VERTICAL);//设置朝向
99+
//初始化TextView
100+
TextView tv=new TextView(MainActivity.this);
101+
tv.setText(womanorganStr[arg0]);
102+
tv.setTextSize(24);//设置字体大小
103+
tv.setTextColor(MainActivity.this.getResources().getColor(R.color.white));//设置字体颜色
104+
tv.setGravity(Gravity.LEFT);//靠左
105+
ll.addView(tv);
106+
return ll;
107+
}
108+
};
109+
//男单选按钮
110+
RadioMan.setOnClickListener(new View.OnClickListener() {
111+
@Override
112+
public void onClick(View v) {
113+
ls.setAdapter(ba);//设置男Adapter
114+
mGLSurfaceView.manOrWoman=true;//更改性别标志位
115+
mGLSurfaceView.womanorganColor= MyFunction.initWomanColor();//初始化女生颜色
116+
oldSelect=14;//初始化选择器官
117+
mGLSurfaceView.selectOrgan=14;//初始化选择器官
118+
}
119+
});
120+
//女单选按钮
121+
RadioWoman.setOnClickListener(new View.OnClickListener() {
122+
@Override
123+
public void onClick(View v) {
124+
ls.setAdapter(baWoman);//设置女Adapter
125+
mGLSurfaceView.manOrWoman=false;//更改性别标志位
126+
mGLSurfaceView.tempmanOrganColor= MyFunction.initManColor();//初始化男生颜色
127+
oldSelect=14;//初始化选择器官
128+
mGLSurfaceView.selectOrgan=14;//初始化选择器官
129+
}
130+
});
131+
//更改菜单界面的方法
132+
ls.setAdapter(ba);
133+
//设置选项被单击的监听器
134+
ls.setOnItemClickListener(
135+
new AdapterView.OnItemClickListener()
136+
{
137+
@Override
138+
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
139+
long arg3) {//重写选项被单击事件的处理方法
140+
mGLSurfaceView.addOrDec=true;//设置循环标志位
141+
if(oldSelect>=0&&oldSelect<=13)
142+
{
143+
mGLSurfaceView.tempbrightBreath[oldSelect]=1.0f;//将上一器官的呼吸系数初始化为1
144+
mGLSurfaceView.tempmanOrganColor[oldSelect]=Constant.organColor[oldSelect];//将原颜色给男器官
145+
mGLSurfaceView.womanorganColor[oldSelect]=Constant.womanorganColor[oldSelect];//将原颜色给女器官
146+
}
147+
setColor(arg2);//上红色
148+
setSelectOrgan(arg2);//更改选中器官
149+
oldSelect=arg2;//记录上一次选择的值
150+
}
151+
}
152+
);
153+
}
154+
//设置颜色
155+
public void setColor(int select)
156+
{
157+
if(mGLSurfaceView.manOrWoman){
158+
mGLSurfaceView.tempmanOrganColor[select]=colorRed;
159+
}else
160+
{
161+
mGLSurfaceView.womanorganColor[select]=colorRed;
162+
}
163+
164+
}
165+
//设置选中器官
166+
public void setSelectOrgan(int select)
167+
{
168+
mGLSurfaceView.selectOrgan=select;
169+
}
170+
@Override
171+
protected void onResume() {
172+
super.onResume();
173+
mGLSurfaceView.onResume();
174+
}
175+
@Override
176+
protected void onPause() {
177+
super.onPause();
178+
mGLSurfaceView.onPause();
179+
}
180+
}

0 commit comments

Comments
 (0)