aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/addon-modules
diff options
context:
space:
mode:
Diffstat (limited to 'addon-modules')
-rw-r--r--addon-modules/Gloebit/prebuild.xml41
-rw-r--r--addon-modules/OpenSim.Modules.Warp3DCachedImageModule/.gitignore287
-rw-r--r--addon-modules/OpenSim.Modules.Warp3DCachedImageModule/LICENSE25
-rw-r--r--addon-modules/OpenSim.Modules.Warp3DCachedImageModule/prebuild.xml41
-rw-r--r--addon-modules/OpenSim.Modules.Warp3DCachedImageModule/src/Perlin.cs264
-rw-r--r--addon-modules/OpenSim.Modules.Warp3DCachedImageModule/src/TerrainSplat.cs470
-rw-r--r--addon-modules/OpenSim.Modules.Warp3DCachedImageModule/src/Warp3DImageModule.cs1089
7 files changed, 2176 insertions, 41 deletions
diff --git a/addon-modules/Gloebit/prebuild.xml b/addon-modules/Gloebit/prebuild.xml
deleted file mode 100644
index b891e27..0000000
--- a/addon-modules/Gloebit/prebuild.xml
+++ /dev/null
@@ -1,41 +0,0 @@
1<Project frameworkVersion="v4_0" name="Gloebit" path="addon-modules/Gloebit/GloebitMoneyModule" type="Library">
2 <ReferencePath>../../../bin/</ReferencePath>
3 <Reference name="System"/>
4 <Reference name="System.Web"/>
5 <Reference name="System.Data"/>
6 <Reference name="System.Xml"/>
7 <Reference name="OpenMetaverseTypes" path="../../../bin/"/>
8 <Reference name="OpenMetaverse" path="../../../bin/"/>
9 <Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/>
10 <Reference name="Nini" path="../../../bin/"/>
11 <Reference name="log4net" path="../../../bin/"/>
12 <Reference name="MySql.Data" path="../../../bin/"/>
13 <Reference name="OpenSim.Data"/>
14 <Reference name="OpenSim.Data.MySQL"/>
15 <Reference name="OpenSim.Data.PGSQL"/>
16 <Reference name="OpenSim.Data.SQLite"/>
17 <Reference name="OpenSim.Framework"/>
18 <Reference name="OpenSim.Framework.Servers"/>
19 <Reference name="OpenSim.Framework.Servers.HttpServer"/>
20 <Reference name="OpenSim.Region.Framework"/>
21 <Reference name="OpenSim.Region.CoreModules"/>
22 <Reference name="OpenSim.Region.OptionalModules"/>
23 <Reference name="OpenSim.Framework.Communications"/>
24 <Reference name="OpenSim.Server.Base"/>
25 <Reference name="OpenSim.Services.Interfaces"/>
26 <Reference name="OpenSim.Region.ScriptEngine.Shared"/>
27 <Reference name="OpenSim.Region.ScriptEngine.Shared.Api.Runtime"/>
28 <Reference name="XMLRPC" path="../../../bin/"/>
29 <Reference name="Npgsql" path="../../../bin/"/>
30
31 <!-- To allow regions to have mono addins -->
32 <Reference name="Mono.Addins" path="../../../bin/"/>
33
34 <Files>
35 <Match pattern="*.cs" recurse="true"/>
36 <Match buildAction="EmbeddedResource" path="Resources" pattern="*.sql"/>
37 <Match buildAction="EmbeddedResource" path="Resources" pattern="*.migrations"/>
38 <Match buildAction="Copy" pattern="*.ini.example" destination="../../../bin/"/>
39 </Files>
40
41</Project>
diff --git a/addon-modules/OpenSim.Modules.Warp3DCachedImageModule/.gitignore b/addon-modules/OpenSim.Modules.Warp3DCachedImageModule/.gitignore
new file mode 100644
index 0000000..a752eac
--- /dev/null
+++ b/addon-modules/OpenSim.Modules.Warp3DCachedImageModule/.gitignore
@@ -0,0 +1,287 @@
1## Ignore Visual Studio temporary files, build results, and
2## files generated by popular Visual Studio add-ons.
3##
4## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5
6# User-specific files
7*.suo
8*.user
9*.userosscache
10*.sln.docstates
11
12# User-specific files (MonoDevelop/Xamarin Studio)
13*.userprefs
14
15# Build results
16[Dd]ebug/
17[Dd]ebugPublic/
18[Rr]elease/
19[Rr]eleases/
20x64/
21x86/
22bld/
23[Bb]in/
24[Oo]bj/
25[Ll]og/
26
27# Visual Studio 2015 cache/options directory
28.vs/
29# Uncomment if you have tasks that create the project's static files in wwwroot
30#wwwroot/
31
32# MSTest test Results
33[Tt]est[Rr]esult*/
34[Bb]uild[Ll]og.*
35
36# NUNIT
37*.VisualState.xml
38TestResult.xml
39
40# Build Results of an ATL Project
41[Dd]ebugPS/
42[Rr]eleasePS/
43dlldata.c
44
45# .NET Core
46project.lock.json
47project.fragment.lock.json
48artifacts/
49**/Properties/launchSettings.json
50
51*_i.c
52*_p.c
53*_i.h
54*.ilk
55*.meta
56*.obj
57*.pch
58*.pdb
59*.pgc
60*.pgd
61*.rsp
62*.sbr
63*.tlb
64*.tli
65*.tlh
66*.tmp
67*.tmp_proj
68*.log
69*.vspscc
70*.vssscc
71.builds
72*.pidb
73*.svclog
74*.scc
75
76# Chutzpah Test files
77_Chutzpah*
78
79# Visual C++ cache files
80ipch/
81*.aps
82*.ncb
83*.opendb
84*.opensdf
85*.sdf
86*.cachefile
87*.VC.db
88*.VC.VC.opendb
89
90# Visual Studio profiler
91*.psess
92*.vsp
93*.vspx
94*.sap
95
96# TFS 2012 Local Workspace
97$tf/
98
99# Guidance Automation Toolkit
100*.gpState
101
102# ReSharper is a .NET coding add-in
103_ReSharper*/
104*.[Rr]e[Ss]harper
105*.DotSettings.user
106
107# JustCode is a .NET coding add-in
108.JustCode
109
110# TeamCity is a build add-in
111_TeamCity*
112
113# DotCover is a Code Coverage Tool
114*.dotCover
115
116# Visual Studio code coverage results
117*.coverage
118*.coveragexml
119
120# NCrunch
121_NCrunch_*
122.*crunch*.local.xml
123nCrunchTemp_*
124
125# MightyMoose
126*.mm.*
127AutoTest.Net/
128
129# Web workbench (sass)
130.sass-cache/
131
132# Installshield output folder
133[Ee]xpress/
134
135# DocProject is a documentation generator add-in
136DocProject/buildhelp/
137DocProject/Help/*.HxT
138DocProject/Help/*.HxC
139DocProject/Help/*.hhc
140DocProject/Help/*.hhk
141DocProject/Help/*.hhp
142DocProject/Help/Html2
143DocProject/Help/html
144
145# Click-Once directory
146publish/
147
148# Publish Web Output
149*.[Pp]ublish.xml
150*.azurePubxml
151# TODO: Comment the next line if you want to checkin your web deploy settings
152# but database connection strings (with potential passwords) will be unencrypted
153*.pubxml
154*.publishproj
155
156# Microsoft Azure Web App publish settings. Comment the next line if you want to
157# checkin your Azure Web App publish settings, but sensitive information contained
158# in these scripts will be unencrypted
159PublishScripts/
160
161# NuGet Packages
162*.nupkg
163# The packages folder can be ignored because of Package Restore
164**/packages/*
165# except build/, which is used as an MSBuild target.
166!**/packages/build/
167# Uncomment if necessary however generally it will be regenerated when needed
168#!**/packages/repositories.config
169# NuGet v3's project.json files produces more ignorable files
170*.nuget.props
171*.nuget.targets
172
173# Microsoft Azure Build Output
174csx/
175*.build.csdef
176
177# Microsoft Azure Emulator
178ecf/
179rcf/
180
181# Windows Store app package directories and files
182AppPackages/
183BundleArtifacts/
184Package.StoreAssociation.xml
185_pkginfo.txt
186
187# Visual Studio cache files
188# files ending in .cache can be ignored
189*.[Cc]ache
190# but keep track of directories ending in .cache
191!*.[Cc]ache/
192
193# Others
194ClientBin/
195~$*
196*~
197*.dbmdl
198*.dbproj.schemaview
199*.jfm
200*.pfx
201*.publishsettings
202orleans.codegen.cs
203
204# Since there are multiple workflows, uncomment next line to ignore bower_components
205# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
206#bower_components/
207
208# RIA/Silverlight projects
209Generated_Code/
210
211# Backup & report files from converting an old project file
212# to a newer Visual Studio version. Backup files are not needed,
213# because we have git ;-)
214_UpgradeReport_Files/
215Backup*/
216UpgradeLog*.XML
217UpgradeLog*.htm
218
219# SQL Server files
220*.mdf
221*.ldf
222
223# Business Intelligence projects
224*.rdl.data
225*.bim.layout
226*.bim_*.settings
227
228# Microsoft Fakes
229FakesAssemblies/
230
231# GhostDoc plugin setting file
232*.GhostDoc.xml
233
234# Node.js Tools for Visual Studio
235.ntvs_analysis.dat
236node_modules/
237
238# Typescript v1 declaration files
239typings/
240
241# Visual Studio 6 build log
242*.plg
243
244# Visual Studio 6 workspace options file
245*.opt
246
247# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
248*.vbw
249
250# Visual Studio LightSwitch build output
251**/*.HTMLClient/GeneratedArtifacts
252**/*.DesktopClient/GeneratedArtifacts
253**/*.DesktopClient/ModelManifest.xml
254**/*.Server/GeneratedArtifacts
255**/*.Server/ModelManifest.xml
256_Pvt_Extensions
257
258# Paket dependency manager
259.paket/paket.exe
260paket-files/
261
262# FAKE - F# Make
263.fake/
264
265# JetBrains Rider
266.idea/
267*.sln.iml
268
269# CodeRush
270.cr/
271
272# Python Tools for Visual Studio (PTVS)
273__pycache__/
274*.pyc
275
276# Cake - Uncomment if you are using it
277# tools/**
278# !tools/packages.config
279
280# Telerik's JustMock configuration file
281*.jmconfig
282
283# BizTalk build output
284*.btp.cs
285*.btm.cs
286*.odx.cs
287*.xsd.cs \ No newline at end of file
diff --git a/addon-modules/OpenSim.Modules.Warp3DCachedImageModule/LICENSE b/addon-modules/OpenSim.Modules.Warp3DCachedImageModule/LICENSE
new file mode 100644
index 0000000..570f732
--- /dev/null
+++ b/addon-modules/OpenSim.Modules.Warp3DCachedImageModule/LICENSE
@@ -0,0 +1,25 @@
1Copyright (c) Contributors, http://opensimulator.org/
2See CONTRIBUTORS.TXT for a full list of copyright holders.
3
4Redistribution and use in source and binary forms, with or without
5modification, are permitted provided that the following conditions are met:
6 * Redistributions of source code must retain the above copyright
7 notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above copyright
9 notice, this list of conditions and the following disclaimer in the
10 documentation and/or other materials provided with the distribution.
11 * Neither the name of the OpenSimulator Project nor the
12 names of its contributors may be used to endorse or promote products
13 derived from this software without specific prior written permission.
14
15THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR
16IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
19DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/addon-modules/OpenSim.Modules.Warp3DCachedImageModule/prebuild.xml b/addon-modules/OpenSim.Modules.Warp3DCachedImageModule/prebuild.xml
new file mode 100644
index 0000000..df5b460
--- /dev/null
+++ b/addon-modules/OpenSim.Modules.Warp3DCachedImageModule/prebuild.xml
@@ -0,0 +1,41 @@
1<Project frameworkVersion="v4_6" name="OpenSim.Modules.Warp3DCachedImageModule" path="addon-modules/OpenSim.Modules.Warp3DCachedImageModule/src" type="Library">
2 <Configuration name="Debug">
3 <Options>
4 <OutputPath>../../../bin</OutputPath>
5 </Options>
6 </Configuration>
7 <Configuration name="Release">
8 <Options>
9 <OutputPath>../../../bin</OutputPath>
10 </Options>
11 </Configuration>
12
13 <ReferencePath>../../../bin</ReferencePath>
14 <Reference name="System" localCopy="false"/>
15 <Reference name="System.Xml"/>
16 <Reference name="System.Drawing"/>
17 <Reference name="System.Runtime.Remoting"/>
18 <Reference name="Nini.dll" path="../../../bin"/>
19 <Reference name="log4net.dll" path="../../../bin"/>
20 <Reference name="XMLRPC.dll" path="../../../bin"/>
21 <Reference name="CSJ2K.dll" path="../../../bin"/>
22 <Reference name="Warp3D.dll" path="../../../bin"/>
23 <Reference name="Mono.Addins.dll" path="../../../bin"/>
24 <Reference name="OpenMetaverseTypes.dll" path="../../../bin"/>
25 <Reference name="OpenSim.Region.PhysicsModules.SharedBase.dll" path="../../../bin"/>
26 <Reference name="OpenMetaverse.dll" path="../../../bin"/>
27 <Reference name="OpenMetaverse.StructuredData.dll" path="../../../bin"/>
28 <Reference name="HttpServer_OpenSim.dll" path="../../../bin"/>
29 <Reference name="OpenSim.Region.Framework" path="../../../bin"/>
30 <Reference name="OpenSim.Framework" path="../../../bin"/>
31 <Reference name="OpenSim.Framework.Console" path="../../../bin"/>
32 <Reference name="OpenSim.Framework.Servers" path="../../../bin"/>
33 <Reference name="OpenSim.Framework.Servers.HttpServer" path="../../../bin"/>
34 <Reference name="OpenSim.Services.Interfaces" path="../../../bin"/>
35 <Reference name="OpenSim.Server.Base" path="../../../bin"/>
36 <Reference name="OpenSim.Data" path="../../../bin"/>
37
38 <Files>
39 <Match pattern="*.cs" recurse="true"/>
40 </Files>
41</Project>
diff --git a/addon-modules/OpenSim.Modules.Warp3DCachedImageModule/src/Perlin.cs b/addon-modules/OpenSim.Modules.Warp3DCachedImageModule/src/Perlin.cs
new file mode 100644
index 0000000..2279b76
--- /dev/null
+++ b/addon-modules/OpenSim.Modules.Warp3DCachedImageModule/src/Perlin.cs
@@ -0,0 +1,264 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using OpenMetaverse;
30
31namespace OpenSim.Region.CoreModules.World.Warp3DMap
32{
33 public static class Perlin
34 {
35 // We use a hardcoded seed to keep the noise generation consistent between runs
36 private const int SEED = 42;
37
38 private const int SAMPLE_SIZE = 1024;
39 private const int B = SAMPLE_SIZE;
40 private const int BM = SAMPLE_SIZE - 1;
41 private const int N = 0x1000;
42
43 private static readonly int[] p = new int[SAMPLE_SIZE + SAMPLE_SIZE + 2];
44 private static readonly float[,] g3 = new float[SAMPLE_SIZE + SAMPLE_SIZE + 2, 3];
45 private static readonly float[,] g2 = new float[SAMPLE_SIZE + SAMPLE_SIZE + 2, 2];
46 private static readonly float[] g1 = new float[SAMPLE_SIZE + SAMPLE_SIZE + 2];
47
48 static Perlin()
49 {
50 Random rng = new Random(SEED);
51 int i, j, k;
52
53 for (i = 0; i < B; i++)
54 {
55 p[i] = i;
56 g1[i] = (float)((rng.Next() % (B + B)) - B) / B;
57
58 for (j = 0; j < 2; j++)
59 g2[i, j] = (float)((rng.Next() % (B + B)) - B) / B;
60 normalize2(g2, i);
61
62 for (j = 0; j < 3; j++)
63 g3[i, j] = (float)((rng.Next() % (B + B)) - B) / B;
64 normalize3(g3, i);
65 }
66
67 while (--i > 0)
68 {
69 k = p[i];
70 p[i] = p[j = rng.Next() % B];
71 p[j] = k;
72 }
73
74 for (i = 0; i < B + 2; i++)
75 {
76 p[B + i] = p[i];
77 g1[B + i] = g1[i];
78 for (j = 0; j < 2; j++)
79 g2[B + i, j] = g2[i, j];
80 for (j = 0; j < 3; j++)
81 g3[B + i, j] = g3[i, j];
82 }
83 }
84
85 public static float noise1(float arg)
86 {
87 int bx0, bx1;
88 float rx0, rx1, sx, t, u, v;
89
90 t = arg + N;
91 bx0 = ((int)t) & BM;
92 bx1 = (bx0 + 1) & BM;
93 rx0 = t - (int)t;
94 rx1 = rx0 - 1f;
95
96 sx = s_curve(rx0);
97
98 u = rx0 * g1[p[bx0]];
99 v = rx1 * g1[p[bx1]];
100
101 return Utils.Lerp(u, v, sx);
102 }
103
104 public static float noise2(float x, float y)
105 {
106 int bx, by, b00, b10, b01, b11;
107 float rx0, rx1, ry0, ry1, sx, sy, a, b, t, u, v;
108 int i, j;
109
110 t = x + N;
111 rx0 = t - (int)t;
112 bx = ((int)t) & BM;
113 i = p[bx];
114 bx = (bx + 1) & BM;
115 j = p[bx];
116
117 t = y + N;
118 ry0 = t - (int)t;
119 by = ((int)t) & BM;
120 b00 = p[i + by];
121 b10 = p[j + by];
122
123 by = (by + 1) & BM;
124 b01 = p[i + by];
125 b11 = p[j + by];
126
127 sx = s_curve(rx0);
128 u = rx0 * g2[b00, 0] + ry0 * g2[b00, 1];
129 rx1 = rx0 - 1f;
130 v = rx1 * g2[b10, 0] + ry0 * g2[b10, 1];
131 a = Utils.Lerp(u, v, sx);
132
133 ry1 = ry0 - 1f;
134 u = rx0 * g2[b01, 0] + ry1 * g2[b01, 1];
135 v = rx1 * g2[b11, 0] + ry1 * g2[b11, 1];
136 b = Utils.Lerp(u, v, sx);
137
138 sy = s_curve(ry0);
139 return Utils.Lerp(a, b, sy);
140 }
141
142 public static float noise3(float x, float y, float z)
143 {
144 int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
145 float rx0, rx1, ry0, ry1, rz0, rz1, sy, sz, a, b, c, d, t, u, v;
146 int i, j;
147
148 t = x + N;
149 bx0 = ((int)t) & BM;
150 bx1 = (bx0 + 1) & BM;
151 rx0 = t - (int)t;
152 rx1 = rx0 - 1f;
153
154 t = y + N;
155 by0 = ((int)t) & BM;
156 by1 = (by0 + 1) & BM;
157 ry0 = t - (int)t;
158 ry1 = ry0 - 1f;
159
160 t = z + N;
161 bz0 = ((int)t) & BM;
162 bz1 = (bz0 + 1) & BM;
163 rz0 = t - (int)t;
164 rz1 = rz0 - 1f;
165
166 i = p[bx0];
167 j = p[bx1];
168
169 b00 = p[i + by0];
170 b10 = p[j + by0];
171 b01 = p[i + by1];
172 b11 = p[j + by1];
173
174 t = s_curve(rx0);
175 sy = s_curve(ry0);
176 sz = s_curve(rz0);
177
178 u = rx0 * g3[b00 + bz0, 0] + ry0 * g3[b00 + bz0, 1] + rz0 * g3[b00 + bz0, 2];
179 v = rx1 * g3[b10 + bz0, 0] + ry0 * g3[b10 + bz0, 1] + rz0 * g3[b10 + bz0, 2];
180 a = Utils.Lerp(u, v, t);
181
182 u = rx0 * g3[b01 + bz0, 0] + ry1 * g3[b01 + bz0, 1] + rz0 * g3[b01 + bz0, 2];
183 v = rx1 * g3[b11 + bz0, 0] + ry1 * g3[b11 + bz0, 1] + rz0 * g3[b11 + bz0, 2];
184 b = Utils.Lerp(u, v, t);
185
186 c = Utils.Lerp(a, b, sy);
187
188 u = rx0 * g3[b00 + bz1, 0] + ry0 * g3[b00 + bz1, 1] + rz1 * g3[b00 + bz1, 2];
189 v = rx1 * g3[b10 + bz1, 0] + ry0 * g3[b10 + bz1, 1] + rz1 * g3[b10 + bz1, 2];
190 a = Utils.Lerp(u, v, t);
191
192 u = rx0 * g3[b01 + bz1, 0] + ry1 * g3[b01 + bz1, 1] + rz1 * g3[b01 + bz1, 2];
193 v = rx1 * g3[b11 + bz1, 0] + ry1 * g3[b11 + bz1, 1] + rz1 * g3[b11 + bz1, 2];
194 b = Utils.Lerp(u, v, t);
195
196 d = Utils.Lerp(a, b, sy);
197 return Utils.Lerp(c, d, sz);
198 }
199
200 public static float turbulence1(float x, float freq)
201 {
202 float t;
203
204 for (t = 0f; freq >= 1f; freq *= 0.5f)
205 {
206 t += noise1(freq * x) / freq;
207 }
208 return t;
209 }
210
211 public static float turbulence2(float x, float y, float freq)
212 {
213 float t;
214
215 for (t = 0f; freq >= 1f; freq *= 0.5f)
216 t += noise2(freq * x, freq * y) / freq;
217
218 return t;
219 }
220
221 public static float turbulence3(float x, float y, float z, float freq)
222 {
223 float t;
224
225 for (t = 0f; freq >= 1f; freq *= 0.5f)
226 {
227 t += noise3(freq * x, freq * y, freq * z) / freq;
228 }
229 return t;
230 }
231
232 private static void normalize2(float[,] v, int i)
233 {
234 float s;
235 float a = v[i, 0];
236 float b = v[i, 1];
237
238 s = (float)Math.Sqrt(a * a + b * b);
239 s = 1.0f / s;
240 v[i, 0] = a * s;
241 v[i, 1] = b * s;
242 }
243
244 private static void normalize3(float[,] v, int i)
245 {
246 float s;
247 float a = v[i, 0];
248 float b = v[i, 1];
249 float c = v[i, 2];
250
251 s = (float)Math.Sqrt(a * a + b * b + c * c);
252 s = 1.0f / s;
253
254 v[i, 0] = a * s;
255 v[i, 1] = b * s;
256 v[i, 2] = c * s;
257 }
258
259 private static float s_curve(float t)
260 {
261 return t * t * (3f - 2f * t);
262 }
263 }
264}
diff --git a/addon-modules/OpenSim.Modules.Warp3DCachedImageModule/src/TerrainSplat.cs b/addon-modules/OpenSim.Modules.Warp3DCachedImageModule/src/TerrainSplat.cs
new file mode 100644
index 0000000..f60beaf
--- /dev/null
+++ b/addon-modules/OpenSim.Modules.Warp3DCachedImageModule/src/TerrainSplat.cs
@@ -0,0 +1,470 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Diagnostics;
30using System.Drawing;
31using System.Drawing.Imaging;
32using log4net;
33using OpenMetaverse;
34using OpenSim.Framework;
35using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Services.Interfaces;
37
38namespace OpenSim.Region.CoreModules.World.Warp3DMap
39{
40 public static class TerrainSplat
41 {
42 #region Constants
43
44 private static readonly UUID DIRT_DETAIL = new UUID("0bc58228-74a0-7e83-89bc-5c23464bcec5");
45 private static readonly UUID GRASS_DETAIL = new UUID("63338ede-0037-c4fd-855b-015d77112fc8");
46 private static readonly UUID MOUNTAIN_DETAIL = new UUID("303cd381-8560-7579-23f1-f0a880799740");
47 private static readonly UUID ROCK_DETAIL = new UUID("53a2f406-4895-1d13-d541-d2e3b86bc19c");
48
49 private static readonly UUID[] DEFAULT_TERRAIN_DETAIL = new UUID[]
50 {
51 DIRT_DETAIL,
52 GRASS_DETAIL,
53 MOUNTAIN_DETAIL,
54 ROCK_DETAIL
55 };
56
57 private static readonly Color[] DEFAULT_TERRAIN_COLOR = new Color[]
58 {
59 Color.FromArgb(255, 164, 136, 117),
60 Color.FromArgb(255, 65, 87, 47),
61 Color.FromArgb(255, 157, 145, 131),
62 Color.FromArgb(255, 125, 128, 130)
63 };
64
65 private static readonly UUID TERRAIN_CACHE_MAGIC = new UUID("2c0c7ef2-56be-4eb8-aacb-76712c535b4b");
66
67 #endregion Constants
68
69 private static readonly ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
70 private static string LogHeader = "[WARP3D TERRAIN SPLAT]";
71
72 /// <summary>
73 /// Builds a composited terrain texture given the region texture
74 /// and heightmap settings
75 /// </summary>
76 /// <param name="terrain">Terrain heightmap</param>
77 /// <param name="regionInfo">Region information including terrain texture parameters</param>
78 /// <returns>A 256x256 square RGB texture ready for rendering</returns>
79 /// <remarks>Based on the algorithm described at http://opensimulator.org/wiki/Terrain_Splatting
80 /// Note we create a 256x256 dimension texture even if the actual terrain is larger.
81 /// </remarks>
82
83 public static Bitmap Splat(ITerrainChannel terrain, UUID[] textureIDs,
84 float[] startHeights, float[] heightRanges,
85 uint regionPositionX, uint regionPositionY,
86 IAssetService assetService, IJ2KDecoder decoder,
87 bool textureTerrain, bool averagetextureTerrain,
88 int twidth, int theight)
89 {
90 Debug.Assert(textureIDs.Length == 4);
91 Debug.Assert(startHeights.Length == 4);
92 Debug.Assert(heightRanges.Length == 4);
93
94 Bitmap[] detailTexture = new Bitmap[4];
95
96 byte[] mapColorsRed = new byte[4];
97 byte[] mapColorsGreen = new byte[4];
98 byte[] mapColorsBlue = new byte[4];
99
100 bool usecolors = false;
101
102 if (textureTerrain)
103 {
104 // Swap empty terrain textureIDs with default IDs
105 for(int i = 0; i < textureIDs.Length; i++)
106 {
107 if(textureIDs[i] == UUID.Zero)
108 textureIDs[i] = DEFAULT_TERRAIN_DETAIL[i];
109 }
110
111 #region Texture Fetching
112
113 if(assetService != null)
114 {
115 for(int i = 0; i < 4; i++)
116 {
117 AssetBase asset = null;
118
119 // asset cache indexes are strings
120 string cacheName ="MAP-Patch" + textureIDs[i].ToString();
121
122 // Try to fetch a cached copy of the decoded/resized version of this texture
123 asset = assetService.GetCached(cacheName);
124 if(asset != null)
125 {
126 try
127 {
128 using(System.IO.MemoryStream stream = new System.IO.MemoryStream(asset.Data))
129 detailTexture[i] = (Bitmap)Image.FromStream(stream);
130
131 if(detailTexture[i].PixelFormat != PixelFormat.Format24bppRgb ||
132 detailTexture[i].Width != 16 || detailTexture[i].Height != 16)
133 {
134 detailTexture[i].Dispose();
135 detailTexture[i] = null;
136 }
137 }
138 catch(Exception ex)
139 {
140 m_log.Warn("Failed to decode cached terrain patch texture" + textureIDs[i] + "): " + ex.Message);
141 }
142 }
143
144 if(detailTexture[i] == null)
145 {
146 // Try to fetch the original JPEG2000 texture, resize if needed, and cache as PNG
147 asset = assetService.Get(textureIDs[i].ToString());
148 if(asset != null)
149 {
150 try
151 {
152 detailTexture[i] = (Bitmap)decoder.DecodeToImage(asset.Data);
153 }
154 catch(Exception ex)
155 {
156 m_log.Warn("Failed to decode terrain texture " + asset.ID + ": " + ex.Message);
157 }
158 }
159
160 if(detailTexture[i] != null)
161 {
162 if(detailTexture[i].PixelFormat != PixelFormat.Format24bppRgb ||
163 detailTexture[i].Width != 16 || detailTexture[i].Height != 16)
164 using(Bitmap origBitmap = detailTexture[i])
165 detailTexture[i] = Util.ResizeImageSolid(origBitmap, 16, 16);
166
167 // Save the decoded and resized texture to the cache
168 byte[] data;
169 using(System.IO.MemoryStream stream = new System.IO.MemoryStream())
170 {
171 detailTexture[i].Save(stream, ImageFormat.Png);
172 data = stream.ToArray();
173 }
174
175 // Cache a PNG copy of this terrain texture
176 AssetBase newAsset = new AssetBase
177 {
178 Data = data,
179 Description = "PNG",
180 Flags = AssetFlags.Collectable,
181 FullID = UUID.Zero,
182 ID = cacheName,
183 Local = true,
184 Name = String.Empty,
185 Temporary = true,
186 Type = (sbyte)AssetType.Unknown
187 };
188 newAsset.Metadata.ContentType = "image/png";
189 assetService.Store(newAsset);
190 }
191 }
192 }
193 }
194
195 #endregion Texture Fetching
196 if(averagetextureTerrain)
197 {
198 for(int t = 0; t < 4; t++)
199 {
200 usecolors = true;
201 if(detailTexture[t] == null)
202 {
203 mapColorsRed[t] = DEFAULT_TERRAIN_COLOR[t].R;
204 mapColorsGreen[t] = DEFAULT_TERRAIN_COLOR[t].G;
205 mapColorsBlue[t] = DEFAULT_TERRAIN_COLOR[t].B;
206 continue;
207 }
208
209 int npixeis = 0;
210 int cR = 0;
211 int cG = 0;
212 int cB = 0;
213
214 BitmapData bmdata = detailTexture[t].LockBits(new Rectangle(0, 0, 16, 16),
215 ImageLockMode.ReadOnly, detailTexture[t].PixelFormat);
216
217 npixeis = bmdata.Height * bmdata.Width;
218 int ylen = bmdata.Height * bmdata.Stride;
219
220 unsafe
221 {
222 for(int y = 0; y < ylen; y += bmdata.Stride)
223 {
224 byte* ptrc = (byte*)bmdata.Scan0 + y;
225 for(int x = 0 ; x < bmdata.Width; ++x)
226 {
227 cR += *(ptrc++);
228 cG += *(ptrc++);
229 cB += *(ptrc++);
230 }
231 }
232
233 }
234 detailTexture[t].UnlockBits(bmdata);
235 detailTexture[t].Dispose();
236
237 mapColorsRed[t] = (byte)Util.Clamp(cR / npixeis, 0 , 255);
238 mapColorsGreen[t] = (byte)Util.Clamp(cG / npixeis, 0 , 255);
239 mapColorsBlue[t] = (byte)Util.Clamp(cB / npixeis, 0 , 255);
240 }
241 }
242 else
243 {
244 // Fill in any missing textures with a solid color
245 for(int i = 0; i < 4; i++)
246 {
247 if(detailTexture[i] == null)
248 {
249 m_log.DebugFormat("{0} Missing terrain texture for layer {1}. Filling with solid default color", LogHeader, i);
250
251 // Create a solid color texture for this layer
252 detailTexture[i] = new Bitmap(16, 16, PixelFormat.Format24bppRgb);
253 using(Graphics gfx = Graphics.FromImage(detailTexture[i]))
254 {
255 using(SolidBrush brush = new SolidBrush(DEFAULT_TERRAIN_COLOR[i]))
256 gfx.FillRectangle(brush, 0, 0, 16, 16);
257 }
258 }
259 else
260 {
261 if(detailTexture[i].Width != 16 || detailTexture[i].Height != 16)
262 {
263 using(Bitmap origBitmap = detailTexture[i])
264 detailTexture[i] = Util.ResizeImageSolid(origBitmap, 16, 16);
265 }
266 }
267 }
268 }
269 }
270 else
271 {
272 usecolors = true;
273 for(int t = 0; t < 4; t++)
274 {
275 mapColorsRed[t] = DEFAULT_TERRAIN_COLOR[t].R;
276 mapColorsGreen[t] = DEFAULT_TERRAIN_COLOR[t].G;
277 mapColorsBlue[t] = DEFAULT_TERRAIN_COLOR[t].B;
278 }
279 }
280
281 #region Layer Map
282
283 float xFactor = terrain.Width / twidth;
284 float yFactor = terrain.Height / theight;
285
286 #endregion Layer Map
287
288 #region Texture Compositing
289
290 Bitmap output = new Bitmap(twidth, theight, PixelFormat.Format24bppRgb);
291 BitmapData outputData = output.LockBits(new Rectangle(0, 0, twidth, theight), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
292
293 // Unsafe work as we lock down the source textures for quicker access and access the
294 // pixel data directly
295 float invtwitdthMinus1 = 1.0f / (twidth - 1);
296 float invtheightMinus1 = 1.0f / (theight - 1);
297 int ty;
298 int tx;
299 float pctx;
300 float pcty;
301 float height;
302 float layer;
303 float layerDiff;
304 int l0;
305 int l1;
306 uint yglobalpos;
307
308 if(usecolors)
309 {
310 float a;
311 float b;
312 unsafe
313 {
314 byte* ptrO;
315 for(int y = 0; y < theight; ++y)
316 {
317 pcty = y * invtheightMinus1;
318 ptrO = (byte*)outputData.Scan0 + y * outputData.Stride;
319 ty = (int)(y * yFactor);
320 yglobalpos = (uint)ty + regionPositionY;
321
322 for(int x = 0; x < twidth; ++x)
323 {
324 tx = (int)(x * xFactor);
325 pctx = x * invtwitdthMinus1;
326 height = (float)terrain[tx, ty];
327 layer = getLayerTex(height, pctx, pcty,
328 (uint)tx + regionPositionX, yglobalpos,
329 startHeights, heightRanges);
330
331 // Select two textures
332 l0 = (int)layer;
333 l1 = Math.Min(l0 + 1, 3);
334
335 layerDiff = layer - l0;
336
337 a = mapColorsRed[l0];
338 b = mapColorsRed[l1];
339 *(ptrO++) = (byte)(a + layerDiff * (b - a));
340
341 a = mapColorsGreen[l0];
342 b = mapColorsGreen[l1];
343 *(ptrO++) = (byte)(a + layerDiff * (b - a));
344
345 a = mapColorsBlue[l0];
346 b = mapColorsBlue[l1];
347 *(ptrO++) = (byte)(a + layerDiff * (b - a));
348 }
349 }
350 }
351 }
352 else
353 {
354 float aB;
355 float aG;
356 float aR;
357 float bB;
358 float bG;
359 float bR;
360
361 unsafe
362 {
363 // Get handles to all of the texture data arrays
364 BitmapData[] datas = new BitmapData[]
365 {
366 detailTexture[0].LockBits(new Rectangle(0, 0, 16, 16), ImageLockMode.ReadOnly, detailTexture[0].PixelFormat),
367 detailTexture[1].LockBits(new Rectangle(0, 0, 16, 16), ImageLockMode.ReadOnly, detailTexture[1].PixelFormat),
368 detailTexture[2].LockBits(new Rectangle(0, 0, 16, 16), ImageLockMode.ReadOnly, detailTexture[2].PixelFormat),
369 detailTexture[3].LockBits(new Rectangle(0, 0, 16, 16), ImageLockMode.ReadOnly, detailTexture[3].PixelFormat)
370 };
371
372 byte* ptr;
373 byte* ptrO;
374 for(int y = 0; y < theight; y++)
375 {
376 pcty = y * invtheightMinus1;
377 int ypatch = ((int)(y * yFactor) & 0x0f) * datas[0].Stride;
378 ptrO = (byte*)outputData.Scan0 + y * outputData.Stride;
379 ty = (int)(y * yFactor);
380 yglobalpos = (uint)ty + regionPositionY;
381
382 for(int x = 0; x < twidth; x++)
383 {
384 tx = (int)(x * xFactor);
385 pctx = x * invtwitdthMinus1;
386 height = (float)terrain[tx, ty];
387 layer = getLayerTex(height, pctx, pcty,
388 (uint)tx + regionPositionX, yglobalpos,
389 startHeights, heightRanges);
390
391 // Select two textures
392 l0 = (int)layer;
393 layerDiff = layer - l0;
394
395 int patchOffset = (tx & 0x0f) * 3 + ypatch;
396
397 ptr = (byte*)datas[l0].Scan0 + patchOffset;
398 aB = *(ptr++);
399 aG = *(ptr++);
400 aR = *(ptr);
401
402 l1 = Math.Min(l0 + 1, 3);
403 ptr = (byte*)datas[l1].Scan0 + patchOffset;
404 bB = *(ptr++);
405 bG = *(ptr++);
406 bR = *(ptr);
407
408
409 // Interpolate between the two selected textures
410 *(ptrO++) = (byte)(aB + layerDiff * (bB - aB));
411 *(ptrO++) = (byte)(aG + layerDiff * (bG - aG));
412 *(ptrO++) = (byte)(aR + layerDiff * (bR - aR));
413 }
414 }
415
416 for(int i = 0; i < detailTexture.Length; i++)
417 detailTexture[i].UnlockBits(datas[i]);
418 }
419
420 for(int i = 0; i < detailTexture.Length; i++)
421 if(detailTexture[i] != null)
422 detailTexture[i].Dispose();
423 }
424
425 output.UnlockBits(outputData);
426
427//output.Save("terr.png",ImageFormat.Png);
428
429 #endregion Texture Compositing
430
431 return output;
432 }
433
434 [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
435 private static float getLayerTex(float height, float pctX, float pctY, uint X, uint Y,
436 float[] startHeights, float[] heightRanges)
437 {
438 // Use bilinear interpolation between the four corners of start height and
439 // height range to select the current values at this position
440 float startHeight = ImageUtils.Bilinear(
441 startHeights[0], startHeights[2],
442 startHeights[1], startHeights[3],
443 pctX, pctY);
444 if (float.IsNaN(startHeight))
445 return 0;
446
447 startHeight = Utils.Clamp(startHeight, 0f, 255f);
448
449 float heightRange = ImageUtils.Bilinear(
450 heightRanges[0], heightRanges[2],
451 heightRanges[1], heightRanges[3],
452 pctX, pctY);
453 heightRange = Utils.Clamp(heightRange, 0f, 255f);
454 if(heightRange == 0f || float.IsNaN(heightRange))
455 return 0;
456
457 // Generate two frequencies of perlin noise based on our global position
458 // The magic values were taken from http://opensimulator.org/wiki/Terrain_Splatting
459 float sX = X * 0.20319f;
460 float sY = Y * 0.20319f;
461
462 float noise = Perlin.noise2(sX * 0.222222f, sY * 0.222222f) * 13.0f;
463 noise += Perlin.turbulence2(sX, sY, 2f) * 4.5f;
464
465 // Combine the current height, generated noise, start height, and height range parameters, then scale all of it
466 float layer = ((height + noise - startHeight) / heightRange) * 4f;
467 return Utils.Clamp(layer, 0f, 3f);
468 }
469 }
470}
diff --git a/addon-modules/OpenSim.Modules.Warp3DCachedImageModule/src/Warp3DImageModule.cs b/addon-modules/OpenSim.Modules.Warp3DCachedImageModule/src/Warp3DImageModule.cs
new file mode 100644
index 0000000..05d5ab2
--- /dev/null
+++ b/addon-modules/OpenSim.Modules.Warp3DCachedImageModule/src/Warp3DImageModule.cs
@@ -0,0 +1,1089 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Drawing;
31using System.Drawing.Imaging;
32using System.IO;
33using System.Reflection;
34using System.Runtime;
35
36using CSJ2K;
37using Nini.Config;
38using log4net;
39using Warp3D;
40using Mono.Addins;
41
42using OpenSim.Framework;
43using OpenSim.Region.Framework.Interfaces;
44using OpenSim.Region.Framework.Scenes;
45////using OpenSim.Region.PhysicsModules.SharedBase;
46////using OpenSim.Services.Interfaces;
47
48using OpenMetaverse;
49using OpenMetaverse.Assets;
50using OpenMetaverse.Imaging;
51using OpenMetaverse.Rendering;
52using OpenMetaverse.StructuredData;
53
54using WarpRenderer = Warp3D.Warp3D;
55using System.Drawing.Drawing2D;
56
57[assembly: Addin("Warp3DCachedImageModule", "1.1")]
58[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]
59namespace OpenSim.Region.CoreModules.World.Warp3DMap
60{
61 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "Warp3DCachedImageModule")]
62 public class Warp3DImageModule : IMapImageGenerator, INonSharedRegionModule
63 {
64 private static readonly Color4 WATER_COLOR = new Color4(29, 72, 96, 216);
65 // private static readonly Color4 WATER_COLOR = new Color4(29, 72, 96, 128);
66
67 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
68
69#pragma warning disable 414
70 private static string LogHeader = "[WARP 3D CACHED IMAGE MODULE]";
71#pragma warning restore 414
72 private const float m_cameraHeight = 4096f;
73
74 internal Scene m_scene;
75 private IRendering m_primMesher;
76 internal IJ2KDecoder m_imgDecoder;
77
78 // caches per rendering
79 private Dictionary<string, warp_Texture> m_warpTextures = new Dictionary<string, warp_Texture>();
80 private Dictionary<UUID, int> m_colors = new Dictionary<UUID, int>();
81
82 private IConfigSource m_config;
83 private bool m_drawPrimVolume = true; // true if should render the prims on the tile
84 private bool m_textureTerrain = true; // true if to create terrain splatting texture
85 private bool m_textureAverageTerrain = false; // replace terrain textures by their average color
86 private bool m_texturePrims = true; // true if should texture the rendered prims
87 private float m_texturePrimSize = 48f; // size of prim before we consider texturing it
88 private bool m_renderMeshes = false; // true if to render meshes rather than just bounding boxes
89 private float m_renderMinHeight = -100f;
90 private float m_renderMaxHeight = 4096f;
91
92 private String m_cacheDirectory = "";
93//// private bool m_enable_date = false;
94//// private bool m_enable_regionName = false;
95 private bool m_enable_regionPosition = false;
96 private bool m_enable_refreshEveryMonth = false;
97//// private bool m_enable_HostedBy = false;
98//// private String m_enable_HostedByText = "";
99
100 private bool m_Enabled = false;
101
102 // private Bitmap lastImage = null;
103 private DateTime lastImageTime = DateTime.MinValue;
104
105 #region Region Module interface
106
107 public void Initialise(IConfigSource source)
108 {
109 m_config = source;
110
111 string[] configSections = new string[] { "Map", "Startup" };
112
113 if (Util.GetConfigVarFromSections<string>(
114 m_config, "MapImageModule", configSections, "MapImageModule") != "Warp3DCachedImageModule")
115 return;
116
117 m_Enabled = true;
118
119 m_drawPrimVolume =
120 Util.GetConfigVarFromSections<bool>(m_config, "DrawPrimOnMapTile", configSections, m_drawPrimVolume);
121 m_textureTerrain =
122 Util.GetConfigVarFromSections<bool>(m_config, "TextureOnMapTile", configSections, m_textureTerrain);
123 m_textureAverageTerrain =
124 Util.GetConfigVarFromSections<bool>(m_config, "AverageTextureColorOnMapTile", configSections, m_textureAverageTerrain);
125 if (m_textureAverageTerrain)
126 m_textureTerrain = true;
127 m_texturePrims =
128 Util.GetConfigVarFromSections<bool>(m_config, "TexturePrims", configSections, m_texturePrims);
129 m_texturePrimSize =
130 Util.GetConfigVarFromSections<float>(m_config, "TexturePrimSize", configSections, m_texturePrimSize);
131 m_renderMeshes =
132 Util.GetConfigVarFromSections<bool>(m_config, "RenderMeshes", configSections, m_renderMeshes);
133 m_cacheDirectory =
134 Util.GetConfigVarFromSections<string>(m_config, "CacheDirectory", configSections, System.IO.Path.Combine(Util.cacheDir(), "MapImageCache"));
135
136
137//// m_enable_date = Util.GetConfigVarFromSections<bool>(m_config, "enableDate", configSections, false);
138//// m_enable_regionName = Util.GetConfigVarFromSections<bool>(m_config, "enableName", configSections, false);
139 m_enable_regionPosition = Util.GetConfigVarFromSections<bool>(m_config, "enablePosition", configSections, false);
140 m_enable_refreshEveryMonth = Util.GetConfigVarFromSections<bool>(m_config, "RefreshEveryMonth", configSections, true);
141//// m_enable_HostedBy = Util.GetConfigVarFromSections<bool>(m_config, "enableHostedBy", configSections, false);
142//// m_enable_HostedByText = Util.GetConfigVarFromSections<String>(m_config, "HosterText", configSections, String.Empty);
143
144 m_renderMaxHeight = Util.GetConfigVarFromSections<float>(m_config, "RenderMaxHeight", configSections, m_renderMaxHeight);
145 m_renderMinHeight = Util.GetConfigVarFromSections<float>(m_config, "RenderMinHeight", configSections, m_renderMinHeight);
146
147 if (!Directory.Exists(m_cacheDirectory))
148 Directory.CreateDirectory(m_cacheDirectory);
149
150 if (m_renderMaxHeight < 100f)
151 m_renderMaxHeight = 100f;
152 else if (m_renderMaxHeight > m_cameraHeight - 10f)
153 m_renderMaxHeight = m_cameraHeight - 10f;
154
155 if (m_renderMinHeight < -100f)
156 m_renderMinHeight = -100f;
157 else if (m_renderMinHeight > m_renderMaxHeight - 10f)
158 m_renderMinHeight = m_renderMaxHeight - 10f;
159 }
160
161 public void AddRegion(Scene scene)
162 {
163 if (!m_Enabled)
164 return;
165
166 m_scene = scene;
167
168 List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory());
169 if (renderers.Count > 0)
170 m_log.Info("[WARP 3D CACHED IMAGE MODULE]: Loaded prim mesher " + renderers[0]);
171 else
172 m_log.Info("[WARP 3D CACHED IMAGE MODULE]: No prim mesher loaded, prim rendering will be disabled");
173
174 m_scene.RegisterModuleInterface<IMapImageGenerator>(this);
175 }
176
177 public void RegionLoaded(Scene scene)
178 {
179 if (!m_Enabled)
180 return;
181
182 m_imgDecoder = m_scene.RequestModuleInterface<IJ2KDecoder>();
183 }
184
185 public void RemoveRegion(Scene scene)
186 {
187 }
188
189 public void Close()
190 {
191 }
192
193 public string Name
194 {
195 get { return "Warp3DCachedImageModule"; }
196 }
197
198 public Type ReplaceableInterface
199 {
200 get { return null; }
201 }
202
203 #endregion
204
205 #region IMapImageGenerator Members
206
207 private Vector3 cameraPos;
208 private Vector3 cameraDir;
209 private int viewWitdh = 256;
210 private int viewHeight = 256;
211 private float fov;
212 private bool orto;
213
214/*
215 public static string fillInt(int _i, int _l)
216 {
217 String _return = _i.ToString();
218
219 while (_return.Length < _l)
220 {
221 _return = 0 + _return;
222 }
223
224 return _return;
225 }
226
227 public static int getCurrentUnixTime()
228 {
229 return (Int32)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
230 }
231
232 public static String unixTimeToDateString(int unixTime)
233 {
234 DateTime unixStart = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
235 long unixTimeStampInTicks = (long)(unixTime * TimeSpan.TicksPerSecond);
236 DateTime _date = new DateTime(unixStart.Ticks + unixTimeStampInTicks, System.DateTimeKind.Utc);
237
238 return fillInt(_date.Day, 2) + "." + fillInt(_date.Month, 2) + "." + fillInt(_date.Year, 4) + " " + fillInt(_date.Hour, 2) + ":" + fillInt(_date.Minute, 2);
239 }
240
241 private void writeDateOnMap(ref Bitmap _map)
242 {
243 RectangleF rectf = new RectangleF(2, 1, 200, 25);
244
245 Graphics g = Graphics.FromImage(_map);
246 g.SmoothingMode = SmoothingMode.AntiAlias;
247 g.InterpolationMode = InterpolationMode.HighQualityBicubic;
248 g.PixelOffsetMode = PixelOffsetMode.HighQuality;
249 g.DrawString(unixTimeToDateString(getCurrentUnixTime()), new Font("Arial", 8), Brushes.White, rectf);
250 g.Flush();
251 }
252
253 private void writeNameOnMap(ref Bitmap _map)
254 {
255 RectangleF rectf = new RectangleF(2, m_scene.RegionInfo.RegionSizeX - 15, 200, 25);
256
257 Graphics g = Graphics.FromImage(_map);
258 g.SmoothingMode = SmoothingMode.AntiAlias;
259 g.InterpolationMode = InterpolationMode.HighQualityBicubic;
260 g.PixelOffsetMode = PixelOffsetMode.HighQuality;
261 g.DrawString(m_scene.Name, new Font("Arial", 8), Brushes.White, rectf);
262 g.Flush();
263 }
264*/
265
266 private void writePositionOnMap(ref Bitmap _map)
267 {
268 RectangleF rectf = new RectangleF(m_scene.RegionInfo.RegionSizeY - 85, m_scene.RegionInfo.RegionSizeX - 15, 80, 25);
269
270 Graphics g = Graphics.FromImage(_map);
271 g.SmoothingMode = SmoothingMode.AntiAlias;
272 g.InterpolationMode = InterpolationMode.HighQualityBicubic;
273 g.PixelOffsetMode = PixelOffsetMode.HighQuality;
274 g.DrawString(m_scene.RegionInfo.RegionLocX + ", " + m_scene.RegionInfo.RegionLocY, new Font("Arial", 8), Brushes.White, rectf);
275 g.Flush();
276 }
277
278/*
279 private void writeHostedByOnMap(ref Bitmap _map)
280 {
281 RectangleF rectf = new RectangleF(2, m_scene.RegionInfo.RegionSizeX - 15, 200, 25);
282
283 Graphics g = Graphics.FromImage(_map);
284 g.SmoothingMode = SmoothingMode.AntiAlias;
285 g.InterpolationMode = InterpolationMode.HighQualityBicubic;
286 g.PixelOffsetMode = PixelOffsetMode.HighQuality;
287 g.DrawString(m_enable_HostedByText, new Font("Arial", 8), Brushes.Gray, rectf);
288 g.Flush();
289 }
290*/
291
292 public Bitmap CreateMapTileForce()
293 {
294 m_log.Info("[WARP 3D CACHED IMAGE MODULE]: Forcing a map tile regenerate.");
295 File.Delete(System.IO.Path.Combine(m_cacheDirectory, m_scene.RegionInfo.RegionID + ".bmp"));
296 return CreateMapTile();
297 }
298
299 public Bitmap CreateMapTile()
300 {
301 if ((File.GetCreationTime(System.IO.Path.Combine(m_cacheDirectory, m_scene.RegionInfo.RegionID + ".bmp")).Month != DateTime.Now.Month) && (m_enable_refreshEveryMonth == true))
302 {
303 m_log.InfoFormat("[WARP 3D CACHED IMAGE MODULE]: Clearing old map tile out of cache {0} {1}.",
304 File.GetCreationTime(System.IO.Path.Combine(m_cacheDirectory, m_scene.RegionInfo.RegionID + ".bmp")).Month, DateTime.Now.Month);
305 File.Delete(System.IO.Path.Combine(m_cacheDirectory, m_scene.RegionInfo.RegionID + ".bmp"));
306 }
307
308 if (File.Exists(System.IO.Path.Combine(m_cacheDirectory, m_scene.RegionInfo.RegionID + ".bmp")))
309 {
310 return new Bitmap(System.IO.Path.Combine(m_cacheDirectory, m_scene.RegionInfo.RegionID + ".bmp"));
311 }
312 else
313 {
314 m_log.Info("[WARP 3D CACHED IMAGE MODULE]: Actually generating a map tile.");
315 List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory());
316 if (renderers.Count > 0)
317 {
318 m_primMesher = RenderingLoader.LoadRenderer(renderers[0]);
319 }
320
321 cameraPos = new Vector3(
322 (m_scene.RegionInfo.RegionSizeX) * 0.5f,
323 (m_scene.RegionInfo.RegionSizeY) * 0.5f,
324 m_cameraHeight);
325
326 cameraDir = -Vector3.UnitZ;
327 viewWitdh = (int)m_scene.RegionInfo.RegionSizeX;
328 viewHeight = (int)m_scene.RegionInfo.RegionSizeY;
329 orto = true;
330
331 // fov = warp_Math.rad2deg(2f * (float)Math.Atan2(viewWitdh, 4096f));
332 // orto = false;
333
334 Bitmap tile = GenImage();
335
336//// if (m_enable_date)
337//// writeDateOnMap(ref tile);
338
339//// if (m_enable_regionName)
340//// writeNameOnMap(ref tile);
341
342 if (m_enable_regionPosition)
343 writePositionOnMap(ref tile);
344
345//// if (m_enable_HostedBy)
346//// writeHostedByOnMap(ref tile);
347
348 tile.Save(System.IO.Path.Combine(m_cacheDirectory, m_scene.RegionInfo.RegionID + ".bmp"));
349
350 // image may be reloaded elsewhere, so no compression format
351 string filename = System.IO.Path.Combine(m_cacheDirectory, "MAP-" + m_scene.RegionInfo.RegionID.ToString() + ".png");
352 m_log.Info("[WARP 3D CACHED IMAGE MODULE]: Generating map tile " + filename);
353 tile.Save(filename, ImageFormat.Png);
354 m_primMesher = null;
355 return tile;
356 }
357 }
358
359 public Bitmap CreateViewImage(Vector3 camPos, Vector3 camDir, float pfov, int width, int height, bool useTextures)
360 {
361 List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory());
362 if (renderers.Count > 0)
363 {
364 m_primMesher = RenderingLoader.LoadRenderer(renderers[0]);
365 }
366
367 cameraPos = camPos;
368 cameraDir = camDir;
369 viewWitdh = width;
370 viewHeight = height;
371 fov = pfov;
372 orto = false;
373
374 Bitmap tile = GenImage();
375 m_primMesher = null;
376 return tile;
377 }
378
379 private Bitmap GenImage()
380 {
381 m_colors.Clear();
382 m_warpTextures.Clear();
383
384 WarpRenderer renderer = new WarpRenderer();
385
386 if (!renderer.CreateScene(viewWitdh, viewHeight))
387 return new Bitmap(viewWitdh, viewHeight);
388
389 #region Camera
390
391 warp_Vector pos = ConvertVector(cameraPos);
392 warp_Vector lookat = warp_Vector.add(pos, ConvertVector(cameraDir));
393
394 if (orto)
395 renderer.Scene.defaultCamera.setOrthographic(true, viewWitdh, viewHeight);
396 else
397 renderer.Scene.defaultCamera.setFov(fov);
398
399 renderer.Scene.defaultCamera.setPos(pos);
400 renderer.Scene.defaultCamera.lookAt(lookat);
401 #endregion Camera
402
403 renderer.Scene.setAmbient(warp_Color.getColor(192, 191, 173));
404 renderer.Scene.addLight("Light1", new warp_Light(new warp_Vector(0f, 1f, 8f), warp_Color.White, 0, 320, 40));
405
406 CreateWater(renderer);
407 CreateTerrain(renderer);
408 if (m_drawPrimVolume)
409 CreateAllPrims(renderer);
410
411 renderer.Render();
412 Bitmap bitmap = renderer.Scene.getImage();
413
414 renderer.Scene.destroy();
415 renderer.Reset();
416 renderer = null;
417
418 m_colors.Clear();
419 m_warpTextures.Clear();
420
421 GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
422 GC.Collect();
423 GC.WaitForPendingFinalizers();
424 GC.Collect();
425 GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.Default;
426 return bitmap;
427 }
428
429 public byte[] WriteJpeg2000Image()
430 {
431 try
432 {
433 using (Bitmap mapbmp = CreateMapTile())
434 return OpenJPEG.EncodeFromImage(mapbmp, false);
435 }
436 catch (Exception e)
437 {
438 // JPEG2000 encoder failed
439 m_log.Error("[WARP 3D CACHED IMAGE MODULE]: Failed generating terrain map: ", e);
440 }
441
442 return null;
443 }
444
445 #endregion
446
447 #region Rendering Methods
448
449 // Add a water plane to the renderer.
450 private void CreateWater(WarpRenderer renderer)
451 {
452 float waterHeight = (float)m_scene.RegionInfo.RegionSettings.WaterHeight;
453
454 renderer.AddPlane("Water", m_scene.RegionInfo.RegionSizeX * 0.5f);
455 renderer.Scene.sceneobject("Water").setPos(m_scene.RegionInfo.RegionSizeX * 0.5f,
456 waterHeight,
457 m_scene.RegionInfo.RegionSizeY * 0.5f);
458
459 warp_Material waterMaterial = new warp_Material(ConvertColor(WATER_COLOR));
460 renderer.Scene.addMaterial("WaterMat", waterMaterial);
461 renderer.SetObjectMaterial("Water", "WaterMat");
462 }
463
464 // Add a terrain to the renderer.
465 // Note that we create a 'low resolution' 257x257 vertex terrain rather than trying for
466 // full resolution. This saves a lot of memory especially for very large regions.
467 private void CreateTerrain(WarpRenderer renderer)
468 {
469 ITerrainChannel terrain = m_scene.Heightmap;
470
471 float regionsx = m_scene.RegionInfo.RegionSizeX;
472 float regionsy = m_scene.RegionInfo.RegionSizeY;
473
474 // 'diff' is the difference in scale between the real region size and the size of terrain we're buiding
475
476 int bitWidth;
477 int bitHeight;
478
479 const double log2inv = 1.4426950408889634073599246810019;
480 bitWidth = (int)Math.Ceiling((Math.Log(terrain.Width) * log2inv));
481 bitHeight = (int)Math.Ceiling((Math.Log(terrain.Height) * log2inv));
482
483 if (bitWidth > 8) // more than 256 is very heavy :(
484 bitWidth = 8;
485 if (bitHeight > 8)
486 bitHeight = 8;
487
488 int twidth = (int)Math.Pow(2, bitWidth);
489 int theight = (int)Math.Pow(2, bitHeight);
490
491 float diff = regionsx / twidth;
492
493 int npointsx = (int)(regionsx / diff);
494 int npointsy = (int)(regionsy / diff);
495
496 float invsx = 1.0f / (npointsx * diff);
497 float invsy = 1.0f / (npointsy * diff);
498
499 npointsx++;
500 npointsy++;
501
502 // Create all the vertices for the terrain
503 warp_Object obj = new warp_Object();
504 warp_Vector pos;
505 float x, y;
506 float tv;
507 for (y = 0; y < regionsy; y += diff)
508 {
509 tv = y * invsy;
510 for (x = 0; x < regionsx; x += diff)
511 {
512 pos = ConvertVector(x, y, (float)terrain[(int)x, (int)y]);
513 obj.addVertex(new warp_Vertex(pos, x * invsx, tv));
514 }
515 pos = ConvertVector(x, y, (float)terrain[(int)(x - diff), (int)y]);
516 obj.addVertex(new warp_Vertex(pos, 1.0f, tv));
517 }
518
519 int lastY = (int)(y - diff);
520 for (x = 0; x < regionsx; x += diff)
521 {
522 pos = ConvertVector(x, y, (float)terrain[(int)x, lastY]);
523 obj.addVertex(new warp_Vertex(pos, x * invsx, 1.0f));
524 }
525 pos = ConvertVector(x, y, (float)terrain[(int)(x - diff), lastY]);
526 obj.addVertex(new warp_Vertex(pos, 1.0f, 1.0f));
527
528 // create triangles.
529 int limx = npointsx - 1;
530 int limy = npointsy - 1;
531 for (int j = 0; j < limy; j++)
532 {
533 for (int i = 0; i < limx; i++)
534 {
535 int v = j * npointsx + i;
536
537 // Make two triangles for each of the squares in the grid of vertices
538 obj.addTriangle(
539 v,
540 v + 1,
541 v + npointsx);
542
543 obj.addTriangle(
544 v + npointsx + 1,
545 v + npointsx,
546 v + 1);
547 }
548 }
549
550 renderer.Scene.addObject("Terrain", obj);
551
552 UUID[] textureIDs = new UUID[4];
553 float[] startHeights = new float[4];
554 float[] heightRanges = new float[4];
555
556 OpenSim.Framework.RegionSettings regionInfo = m_scene.RegionInfo.RegionSettings;
557
558 textureIDs[0] = regionInfo.TerrainTexture1;
559 textureIDs[1] = regionInfo.TerrainTexture2;
560 textureIDs[2] = regionInfo.TerrainTexture3;
561 textureIDs[3] = regionInfo.TerrainTexture4;
562
563 startHeights[0] = (float)regionInfo.Elevation1SW;
564 startHeights[1] = (float)regionInfo.Elevation1NW;
565 startHeights[2] = (float)regionInfo.Elevation1SE;
566 startHeights[3] = (float)regionInfo.Elevation1NE;
567
568 heightRanges[0] = (float)regionInfo.Elevation2SW;
569 heightRanges[1] = (float)regionInfo.Elevation2NW;
570 heightRanges[2] = (float)regionInfo.Elevation2SE;
571 heightRanges[3] = (float)regionInfo.Elevation2NE;
572
573 warp_Texture texture;
574 using (Bitmap image = TerrainSplat.Splat(terrain, textureIDs, startHeights, heightRanges,
575 m_scene.RegionInfo.WorldLocX, m_scene.RegionInfo.WorldLocY,
576 m_scene.AssetService, m_imgDecoder, m_textureTerrain, m_textureAverageTerrain,
577 twidth, twidth))
578 texture = new warp_Texture(image);
579
580 warp_Material material = new warp_Material(texture);
581 renderer.Scene.addMaterial("TerrainMat", material);
582 renderer.SetObjectMaterial("Terrain", "TerrainMat");
583 }
584
585 private void CreateAllPrims(WarpRenderer renderer)
586 {
587 if (m_primMesher == null)
588 return;
589
590 m_scene.ForEachSOG(
591 delegate (SceneObjectGroup group)
592 {
593 foreach (SceneObjectPart child in group.Parts)
594 CreatePrim(renderer, child);
595 }
596 );
597 }
598
599 private void UVPlanarMap(Vertex v, Vector3 scale, out float tu, out float tv)
600 {
601 Vector3 scaledPos = v.Position * scale;
602 float d = v.Normal.X;
603 if (d >= 0.5f)
604 {
605 tu = 2f * scaledPos.Y;
606 tv = scaledPos.X * v.Normal.Z - scaledPos.Z * v.Normal.X;
607 }
608 else if (d <= -0.5f)
609 {
610 tu = -2f * scaledPos.Y;
611 tv = -scaledPos.X * v.Normal.Z + scaledPos.Z * v.Normal.X;
612 }
613 else if (v.Normal.Y > 0f)
614 {
615 tu = -2f * scaledPos.X;
616 tv = scaledPos.Y * v.Normal.Z - scaledPos.Z * v.Normal.Y;
617 }
618 else
619 {
620 tu = 2f * scaledPos.X;
621 tv = -scaledPos.Y * v.Normal.Z + scaledPos.Z * v.Normal.Y;
622 }
623
624 tv *= 2f;
625 }
626
627 private void CreatePrim(WarpRenderer renderer, SceneObjectPart prim)
628 {
629 if ((PCode)prim.Shape.PCode != PCode.Prim)
630 return;
631
632 Vector3 ppos = prim.GetWorldPosition();
633 if (ppos.Z < m_renderMinHeight || ppos.Z > m_renderMaxHeight)
634 return;
635
636 warp_Vector primPos = ConvertVector(ppos);
637 warp_Quaternion primRot = ConvertQuaternion(prim.GetWorldRotation());
638 warp_Matrix m = warp_Matrix.quaternionMatrix(primRot);
639
640 float screenFactor = renderer.Scene.EstimateBoxProjectedArea(primPos, ConvertVector(prim.Scale), m);
641 if (screenFactor < 0)
642 return;
643
644 int p2 = (int)(-(float)Math.Log(screenFactor) * 1.442695f * 0.5 - 1);
645
646 if (p2 < 0)
647 p2 = 0;
648 else if (p2 > 3)
649 p2 = 3;
650
651 DetailLevel lod = (DetailLevel)(3 - p2);
652
653 FacetedMesh renderMesh = null;
654 Primitive omvPrim = prim.Shape.ToOmvPrimitive(prim.OffsetPosition, prim.RotationOffset);
655
656 if (m_renderMeshes)
657 {
658 if (omvPrim.Sculpt != null && omvPrim.Sculpt.SculptTexture != UUID.Zero)
659 {
660 // Try fetchinng the asset
661 byte[] sculptAsset = m_scene.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString());
662 if (sculptAsset != null)
663 {
664 // Is it a mesh?
665 if (omvPrim.Sculpt.Type == SculptType.Mesh)
666 {
667 AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset);
668 FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, lod, out renderMesh);
669 meshAsset = null;
670 }
671 else // It's sculptie
672 {
673 if (m_imgDecoder != null)
674 {
675 Image sculpt = m_imgDecoder.DecodeToImage(sculptAsset);
676 if (sculpt != null)
677 {
678 renderMesh = m_primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap)sculpt, lod);
679 sculpt.Dispose();
680 }
681 }
682 }
683 }
684 else
685 {
686 m_log.WarnFormat("[WARP 3D CACHED IMAGE MODULE] failed to get mesh or sculpt asset {0} of prim {1} at {2}",
687 omvPrim.Sculpt.SculptTexture.ToString(), prim.Name, prim.GetWorldPosition().ToString());
688 }
689 }
690 }
691
692 // If not a mesh or sculptie, try the regular mesher
693 if (renderMesh == null)
694 {
695 renderMesh = m_primMesher.GenerateFacetedMesh(omvPrim, lod);
696 }
697
698 if (renderMesh == null)
699 return;
700
701 string primID = prim.UUID.ToString();
702
703 // Create the prim faces
704 // TODO: Implement the useTextures flag behavior
705 for (int i = 0; i < renderMesh.Faces.Count; i++)
706 {
707 Face face = renderMesh.Faces[i];
708 string meshName = primID + i.ToString();
709
710 // Avoid adding duplicate meshes to the scene
711 if (renderer.Scene.objectData.ContainsKey(meshName))
712 continue;
713
714 warp_Object faceObj = new warp_Object();
715
716 Primitive.TextureEntryFace teFace = prim.Shape.Textures.GetFace((uint)i);
717 Color4 faceColor = teFace.RGBA;
718 if (faceColor.A == 0)
719 continue;
720
721 string materialName = String.Empty;
722 if (m_texturePrims)
723 {
724 // if(lod > DetailLevel.Low)
725 {
726 // materialName = GetOrCreateMaterial(renderer, faceColor, teFace.TextureID, lod == DetailLevel.Low);
727 materialName = GetOrCreateMaterial(renderer, faceColor, teFace.TextureID, false, prim);
728 if (String.IsNullOrEmpty(materialName))
729 continue;
730 int c = renderer.Scene.material(materialName).getColor();
731 if ((c & warp_Color.MASKALPHA) == 0)
732 continue;
733 }
734 }
735 else
736 materialName = GetOrCreateMaterial(renderer, faceColor);
737
738 if (renderer.Scene.material(materialName).getTexture() == null)
739 {
740 // uv map details dont not matter for color;
741 for (int j = 0; j < face.Vertices.Count; j++)
742 {
743 Vertex v = face.Vertices[j];
744 warp_Vector pos = ConvertVector(v.Position);
745 warp_Vertex vert = new warp_Vertex(pos, v.TexCoord.X, v.TexCoord.Y);
746 faceObj.addVertex(vert);
747 }
748 }
749 else
750 {
751 float tu;
752 float tv;
753 float offsetu = teFace.OffsetU + 0.5f;
754 float offsetv = teFace.OffsetV + 0.5f;
755 float scaleu = teFace.RepeatU;
756 float scalev = teFace.RepeatV;
757 float rotation = teFace.Rotation;
758 float rc = 0;
759 float rs = 0;
760 if (rotation != 0)
761 {
762 rc = (float)Math.Cos(rotation);
763 rs = (float)Math.Sin(rotation);
764 }
765
766 for (int j = 0; j < face.Vertices.Count; j++)
767 {
768 warp_Vertex vert;
769 Vertex v = face.Vertices[j];
770 warp_Vector pos = ConvertVector(v.Position);
771 if (teFace.TexMapType == MappingType.Planar)
772 UVPlanarMap(v, prim.Scale, out tu, out tv);
773 else
774 {
775 tu = v.TexCoord.X - 0.5f;
776 tv = 0.5f - v.TexCoord.Y;
777 }
778 if (rotation != 0)
779 {
780 float tur = tu * rc - tv * rs;
781 float tvr = tu * rs + tv * rc;
782 tur *= scaleu;
783 tur += offsetu;
784
785 tvr *= scalev;
786 tvr += offsetv;
787 vert = new warp_Vertex(pos, tur, tvr);
788 }
789 else
790 {
791 tu *= scaleu;
792 tu += offsetu;
793 tv *= scalev;
794 tv += offsetv;
795 vert = new warp_Vertex(pos, tu, tv);
796 }
797
798 faceObj.addVertex(vert);
799 }
800 }
801
802 for (int j = 0; j < face.Indices.Count; j += 3)
803 {
804 faceObj.addTriangle(
805 face.Indices[j + 0],
806 face.Indices[j + 1],
807 face.Indices[j + 2]);
808 }
809
810 faceObj.scaleSelf(prim.Scale.X, prim.Scale.Z, prim.Scale.Y);
811 faceObj.transform(m);
812 faceObj.setPos(primPos);
813
814 renderer.Scene.addObject(meshName, faceObj);
815 renderer.SetObjectMaterial(meshName, materialName);
816 }
817 }
818
819 private int GetFaceColor(Primitive.TextureEntryFace face)
820 {
821 int color;
822 Color4 ctmp = Color4.White;
823
824 if (face.TextureID == UUID.Zero)
825 return warp_Color.White;
826
827 if (!m_colors.TryGetValue(face.TextureID, out color))
828 {
829 bool fetched = false;
830
831 // Attempt to fetch the texture metadata
832 string cacheName = "MAPCLR" + face.TextureID.ToString();
833 AssetBase metadata = m_scene.AssetService.GetCached(cacheName);
834 if (metadata != null)
835 {
836 OSDMap map = null;
837 try { map = OSDParser.Deserialize(metadata.Data) as OSDMap; } catch { }
838
839 if (map != null)
840 {
841 ctmp = map["X-RGBA"].AsColor4();
842 fetched = true;
843 }
844 }
845
846 if (!fetched)
847 {
848 // Fetch the texture, decode and get the average color,
849 // then save it to a temporary metadata asset
850 AssetBase textureAsset = m_scene.AssetService.Get(face.TextureID.ToString());
851 if (textureAsset != null)
852 {
853 int width, height;
854 ctmp = GetAverageColor(textureAsset.FullID, textureAsset.Data, out width, out height);
855
856 OSDMap data = new OSDMap { { "X-RGBA", OSD.FromColor4(ctmp) } };
857 metadata = new AssetBase
858 {
859 Data = System.Text.Encoding.UTF8.GetBytes(OSDParser.SerializeJsonString(data)),
860 Description = "Metadata for texture color" + face.TextureID.ToString(),
861 Flags = AssetFlags.Collectable,
862 FullID = UUID.Zero,
863 ID = cacheName,
864 Local = true,
865 Temporary = true,
866 Name = String.Empty,
867 Type = (sbyte)AssetType.Unknown
868 };
869 m_scene.AssetService.Store(metadata);
870 }
871 else
872 {
873 ctmp = new Color4(0.5f, 0.5f, 0.5f, 1.0f);
874 }
875 }
876 color = ConvertColor(ctmp);
877 m_colors[face.TextureID] = color;
878 }
879
880 return color;
881 }
882
883 private string GetOrCreateMaterial(WarpRenderer renderer, Color4 color)
884 {
885 string name = color.ToString();
886
887 warp_Material material = renderer.Scene.material(name);
888 if (material != null)
889 return name;
890
891 renderer.AddMaterial(name, ConvertColor(color));
892 return name;
893 }
894
895 public string GetOrCreateMaterial(WarpRenderer renderer, Color4 faceColor, UUID textureID, bool useAverageTextureColor, SceneObjectPart sop)
896 {
897 int color = ConvertColor(faceColor);
898 string idstr = textureID.ToString() + color.ToString();
899 string materialName = "MAPMAT" + idstr;
900
901 if (renderer.Scene.material(materialName) != null)
902 return materialName;
903
904 warp_Material mat = new warp_Material();
905 warp_Texture texture = GetTexture(textureID, sop);
906 if (texture != null)
907 {
908 if (useAverageTextureColor)
909 color = warp_Color.multiply(color, texture.averageColor);
910 else
911 mat.setTexture(texture);
912 }
913 else
914 color = warp_Color.multiply(color, warp_Color.Grey);
915
916 mat.setColor(color);
917 renderer.Scene.addMaterial(materialName, mat);
918
919 return materialName;
920 }
921
922 private warp_Texture GetTexture(UUID id, SceneObjectPart sop)
923 {
924 warp_Texture ret = null;
925 if (id == UUID.Zero)
926 return ret;
927
928 if (m_warpTextures.TryGetValue(id.ToString(), out ret))
929 return ret;
930
931 byte[] asset = m_scene.AssetService.GetData(id.ToString());
932
933 if (asset != null)
934 {
935 try
936 {
937 using (Bitmap img = (Bitmap)m_imgDecoder.DecodeToImage(asset))
938 ret = new warp_Texture(img, 8); // reduce textures size to 256x256
939 }
940 catch (Exception e)
941 {
942 m_log.WarnFormat("[WARP 3D CACHED IMAGE MODULE]: Failed to decode texture {0} for prim {1} at {2}, exception {3}", id.ToString(), sop.Name, sop.GetWorldPosition().ToString(), e.Message);
943 }
944 }
945 else
946 m_log.WarnFormat("[WARP 3D CACHED IMAGE MODULE]: missing texture {0} data for prim {1} at {2}",
947 id.ToString(), sop.Name, sop.GetWorldPosition().ToString());
948
949 m_warpTextures[id.ToString()] = ret;
950 return ret;
951 }
952
953 #endregion Rendering Methods
954
955 #region Static Helpers
956 // Note: axis change.
957 private static warp_Vector ConvertVector(float x, float y, float z)
958 {
959 return new warp_Vector(x, z, y);
960 }
961
962 private static warp_Vector ConvertVector(Vector3 vector)
963 {
964 return new warp_Vector(vector.X, vector.Z, vector.Y);
965 }
966
967 private static warp_Quaternion ConvertQuaternion(Quaternion quat)
968 {
969 return new warp_Quaternion(quat.X, quat.Z, quat.Y, -quat.W);
970 }
971
972 private static int ConvertColor(Color4 color)
973 {
974 int c = warp_Color.getColor((byte)(color.R * 255f), (byte)(color.G * 255f), (byte)(color.B * 255f), (byte)(color.A * 255f));
975 return c;
976 }
977
978 private static Vector3 SurfaceNormal(Vector3 c1, Vector3 c2, Vector3 c3)
979 {
980 Vector3 edge1 = new Vector3(c2.X - c1.X, c2.Y - c1.Y, c2.Z - c1.Z);
981 Vector3 edge2 = new Vector3(c3.X - c1.X, c3.Y - c1.Y, c3.Z - c1.Z);
982
983 Vector3 normal = Vector3.Cross(edge1, edge2);
984 normal.Normalize();
985
986 return normal;
987 }
988
989 public Color4 GetAverageColor(UUID textureID, byte[] j2kData, out int width, out int height)
990 {
991 ulong r = 0;
992 ulong g = 0;
993 ulong b = 0;
994 ulong a = 0;
995 int pixelBytes;
996
997 try
998 {
999 using (MemoryStream stream = new MemoryStream(j2kData))
1000 using (Bitmap bitmap = (Bitmap)J2kImage.FromStream(stream))
1001 {
1002 width = bitmap.Width;
1003 height = bitmap.Height;
1004
1005 BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
1006 pixelBytes = (bitmap.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4;
1007
1008 // Sum up the individual channels
1009 unsafe
1010 {
1011 if (pixelBytes == 4)
1012 {
1013 for (int y = 0; y < height; y++)
1014 {
1015 byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride);
1016
1017 for (int x = 0; x < width; x++)
1018 {
1019 b += row[x * pixelBytes + 0];
1020 g += row[x * pixelBytes + 1];
1021 r += row[x * pixelBytes + 2];
1022 a += row[x * pixelBytes + 3];
1023 }
1024 }
1025 }
1026 else
1027 {
1028 for (int y = 0; y < height; y++)
1029 {
1030 byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride);
1031
1032 for (int x = 0; x < width; x++)
1033 {
1034 b += row[x * pixelBytes + 0];
1035 g += row[x * pixelBytes + 1];
1036 r += row[x * pixelBytes + 2];
1037 }
1038 }
1039 }
1040 }
1041 }
1042 // Get the averages for each channel
1043 const decimal OO_255 = 1m / 255m;
1044 decimal totalPixels = (decimal)(width * height);
1045
1046 decimal rm = ((decimal)r / totalPixels) * OO_255;
1047 decimal gm = ((decimal)g / totalPixels) * OO_255;
1048 decimal bm = ((decimal)b / totalPixels) * OO_255;
1049 decimal am = ((decimal)a / totalPixels) * OO_255;
1050
1051 if (pixelBytes == 3)
1052 am = 1m;
1053
1054 return new Color4((float)rm, (float)gm, (float)bm, (float)am);
1055
1056 }
1057 catch (Exception ex)
1058 {
1059 m_log.WarnFormat(
1060 "[WARP 3D CACHED IMAGE MODULE]: Error decoding JPEG2000 texture {0} ({1} bytes): {2}",
1061 textureID, j2kData.Length, ex.Message);
1062
1063 width = 0;
1064 height = 0;
1065 return new Color4(0.5f, 0.5f, 0.5f, 1.0f);
1066 }
1067 }
1068
1069 #endregion Static Helpers
1070 }
1071
1072 public static class ImageUtils
1073 {
1074 /// <summary>
1075 /// Performs bilinear interpolation between four values
1076 /// </summary>
1077 /// <param name="v00">First, or top left value</param>
1078 /// <param name="v01">Second, or top right value</param>
1079 /// <param name="v10">Third, or bottom left value</param>
1080 /// <param name="v11">Fourth, or bottom right value</param>
1081 /// <param name="xPercent">Interpolation value on the X axis, between 0.0 and 1.0</param>
1082 /// <param name="yPercent">Interpolation value on fht Y axis, between 0.0 and 1.0</param>
1083 /// <returns>The bilinearly interpolated result</returns>
1084 public static float Bilinear(float v00, float v01, float v10, float v11, float xPercent, float yPercent)
1085 {
1086 return Utils.Lerp(Utils.Lerp(v00, v01, xPercent), Utils.Lerp(v10, v11, xPercent), yPercent);
1087 }
1088 }
1089}