設想
我正在使用 unity c# 重新發明一個類似谷歌地球的體驗作為一個專案。當用戶在全球范圍內平移相機時,會從 Web 異步加載新圖塊。到目前為止,我能夠根據它們的 x & y 坐標和縮放級別加載所有
** 編輯 **
我已經想出了如何讓瓷磚位置正確。現在我被困在瓷磚的正確旋轉上。
對我幫助最大的代碼是在一個關于
** 編輯 2 **
添加@Ruzihm 的答案來計演算法線后

uj5u.com熱心網友回復:
對于平面的定位和旋轉,您可以在 c# 中執行此操作:
float x,y,z;
// ...
plane.transform.position = new Vector3(x,y,z);
// negative needed according to comments
Vector3 planeUp = new Vector3(x,y,-z);
Vector3 planeRight = Vector3.Cross(planeUp, Vector3.up);
Vector3 planeForward = Vector3.Cross(planeRight, planeUp);
plane.transform.rotation = Quaternion.LookRotation(planeForward, planeUp);
使它們彎曲到位要困難得多,因為它帶來了如何將每個正方形投影到曲面上的問題......你如何管理重疊?差距?每個平面的邊緣如何對齊?
無論如何,直到那個決定,這里的東西來幫助可視化的問題。您可以從四邊形的每個頂點到球體的中間追蹤一條線,然后沿著這條線找到與中心距離與平面中心距離相同的點。幸運的是,這在可以附加到平面的著色器中是可行的。為簡潔起見,這里假設球體的中心位于世界原點 (0,0,0):
Shader "Custom/SquareBender" {
Properties{
_MainTex("Tex", 2D) = "" {}
}
SubShader {
Pass {
Tags {"LightMode" = "Always"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata {
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
};
v2f vert(appdata v)
{
v2f o;
// everything in obj space
float4 worldOrigin = mul(unity_WorldToObject,
float4(0,0,0,1));
float4 fromOriginToObj = float4(0,0,0,1) - worldOrigin;
float4 fromOriginToPos = v.vertex - worldOrigin;
float4 dirPos = normalize(fromOriginToPos);
float r = distance(fromOriginToObj);
o.pos = UnityObjectToClipPos(r*dirPos worldOrigin);
o.uv = v.uv
return o;
}
sampler2D _MainTex;
float4 frag(v2f IN) : COLOR
{
fixed4 col = tex2D(_MainTex, IN.uv);
}
ENDCG
}
}
FallBack "VertexLit"
}
uj5u.com熱心網友回復:
如果您將緯度和經度分配給每個頂點,并且還分配球體中心和半徑,則可以讓著色器指定它們的位置和方向,而不是在 C# 中定位和定向平面:
Shader "Custom/SquareBender" {
Properties{
_MainTex("Tex", 2D) = "" {}
_SphereCenter("SphereCenter", Vector) = (0, 0, 0, 1)
_SphereRadius("SphereRadius", Float) = 5
}
SubShader {
Pass {
Tags {"LightMode" = "Always"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata {
float2 uv : TEXCOORD0;
float2 latLon : TEXCOORD1;
};
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
};
float4 _SphereCenter;
float4 _SphereRadius;
v2f vert(appdata v)
{
v2f o;
float lat = v.latLon.x
float lon = v.latLon.y
float4 posOffsetWorld = float4(
_SphereRadius*cos(lat)*cos(lon),
_SphereRadius*cos(lat)*sin(lon),
_SphereRadius*sin(lat), 0);
float4 posObj = mul(unity_WorldToObject,
posOffsetWorld _SphereCenter);
o.pos = UnityObjectToClipPos(posObj);
o.uv = v.uv;
return o;
}
sampler2D _MainTex;
float4 frag(v2f IN) : COLOR
{
fixed4 col = tex2D(_MainTex, IN.uv);
}
ENDCG
}
}
FallBack "VertexLit"
}
您可以像這樣將資料分配給頂點:
// tileIndex is column/row/zoom of current tile
// uv is relative postion within tile
// (0,0) for bottom left, (1,1) top right
Vector2 GetLatLonOfVertex(Vector3Int tileIndex, Vector2 uv)
{
float lat, lon;
// Use tileIndex and uv to calculate lat, lon
// Exactly how you could do this depends on your tiling API...
return new Vector2(lat, lon);
}
// Call after plane mesh is created, and any additional vertices/uvs are set
// tileIndex is column/row/zoom of current tile
void SetUpTileLatLons(Mesh mesh, Vector3Int tileIndex)
{
Vector2[] uvs = mesh.uv;
Vector2[] latLons= new Vector2[uvs.Length];
for (int i = 0; i < latLons.Length; i )
{
latLons[i] = GetLatLonOfVertex(tileIndex, uvs[i]);
}
mesh.uv2 = latLons;
}
平面的頂點越多,球體就會顯得越圓,盡管它會導致瓷磚上的紋理失真更多。權衡取決于你。請確保如果您按程式添加更多頂點/三角形,則為它們分配適當的 uv。
請注意,頂點的位置是在著色器中根據緯度/經度分配的,與物件的變換無關。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/372148.html
