diff options
author | Dahlia Trimble | 2008-11-30 03:52:18 +0000 |
---|---|---|
committer | Dahlia Trimble | 2008-11-30 03:52:18 +0000 |
commit | 07ee2c3504edb0c328020aed6f5d3f182a3b67c5 (patch) | |
tree | eb373c5e8fef7ce2a840ecfa87c04cc7a10fa425 /OpenSim/Region/Physics/Meshing/SculptMesh.cs | |
parent | * try a prebuild fix to the primmesher thing (diff) | |
download | opensim-SC_OLD-07ee2c3504edb0c328020aed6f5d3f182a3b67c5.zip opensim-SC_OLD-07ee2c3504edb0c328020aed6f5d3f182a3b67c5.tar.gz opensim-SC_OLD-07ee2c3504edb0c328020aed6f5d3f182a3b67c5.tar.bz2 opensim-SC_OLD-07ee2c3504edb0c328020aed6f5d3f182a3b67c5.tar.xz |
Revert r7548 and r7549 until someone with prebuild-fu can help structure the dependencies
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/Physics/Meshing/SculptMesh.cs | 343 |
1 files changed, 343 insertions, 0 deletions
diff --git a/OpenSim/Region/Physics/Meshing/SculptMesh.cs b/OpenSim/Region/Physics/Meshing/SculptMesh.cs new file mode 100644 index 0000000..312f89a --- /dev/null +++ b/OpenSim/Region/Physics/Meshing/SculptMesh.cs | |||
@@ -0,0 +1,343 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors | ||
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 OpenSim 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 | |||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using System.Text; | ||
31 | using System.IO; | ||
32 | using System.Drawing; | ||
33 | using System.Drawing.Imaging; | ||
34 | |||
35 | namespace PrimMesher | ||
36 | { | ||
37 | |||
38 | public class SculptMesh | ||
39 | { | ||
40 | public List<Coord> coords; | ||
41 | public List<Face> faces; | ||
42 | |||
43 | public List<ViewerFace> viewerFaces; | ||
44 | public List<Coord> normals; | ||
45 | public List<UVCoord> uvs; | ||
46 | |||
47 | public enum SculptType { sphere = 1, torus = 2, plane = 3, cylinder = 4 }; | ||
48 | private const float pixScale = 0.00390625f; // 1.0 / 256 | ||
49 | |||
50 | private Bitmap ScaleImage(Bitmap srcImage, float scale) | ||
51 | { | ||
52 | int sourceWidth = srcImage.Width; | ||
53 | int sourceHeight = srcImage.Height; | ||
54 | int sourceX = 0; | ||
55 | int sourceY = 0; | ||
56 | |||
57 | int destX = 0; | ||
58 | int destY = 0; | ||
59 | int destWidth = (int)(sourceWidth * scale); | ||
60 | int destHeight = (int)(sourceHeight * scale); | ||
61 | |||
62 | Bitmap scaledImage = new Bitmap(destWidth, destHeight, | ||
63 | PixelFormat.Format24bppRgb); | ||
64 | scaledImage.SetResolution(srcImage.HorizontalResolution, | ||
65 | srcImage.VerticalResolution); | ||
66 | |||
67 | Graphics grPhoto = Graphics.FromImage(scaledImage); | ||
68 | grPhoto.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Bilinear; | ||
69 | |||
70 | grPhoto.DrawImage(srcImage, | ||
71 | new Rectangle(destX, destY, destWidth, destHeight), | ||
72 | new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight), | ||
73 | GraphicsUnit.Pixel); | ||
74 | |||
75 | grPhoto.Dispose(); | ||
76 | return scaledImage; | ||
77 | } | ||
78 | |||
79 | public SculptMesh SculptMeshFromFile(string fileName, SculptType sculptType, int lod, bool viewerMode) | ||
80 | { | ||
81 | Bitmap bitmap = (Bitmap)Bitmap.FromFile(fileName); | ||
82 | SculptMesh sculptMesh = new SculptMesh(bitmap, sculptType, lod, viewerMode); | ||
83 | bitmap.Dispose(); | ||
84 | return sculptMesh; | ||
85 | } | ||
86 | |||
87 | public SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode) | ||
88 | { | ||
89 | coords = new List<Coord>(); | ||
90 | faces = new List<Face>(); | ||
91 | normals = new List<Coord>(); | ||
92 | uvs = new List<UVCoord>(); | ||
93 | |||
94 | float sourceScaleFactor = (float)lod / (float)Math.Max(sculptBitmap.Width, sculptBitmap.Height); | ||
95 | bool scaleSourceImage = sourceScaleFactor < 1.0f ? true : false; | ||
96 | |||
97 | Bitmap bitmap; | ||
98 | if (scaleSourceImage) | ||
99 | bitmap = ScaleImage(sculptBitmap, sourceScaleFactor); | ||
100 | else | ||
101 | bitmap = sculptBitmap; | ||
102 | |||
103 | viewerFaces = new List<ViewerFace>(); | ||
104 | |||
105 | int width = bitmap.Width; | ||
106 | int height = bitmap.Height; | ||
107 | |||
108 | float widthUnit = 1.0f / width; | ||
109 | float heightUnit = 1.0f / (height - 1); | ||
110 | |||
111 | int p1, p2, p3, p4; | ||
112 | Color color; | ||
113 | float x, y, z; | ||
114 | |||
115 | int imageX, imageY; | ||
116 | |||
117 | if (sculptType == SculptType.sphere) | ||
118 | { // average the top and bottom row pixel values so the resulting vertices appear to converge | ||
119 | int lastRow = height - 1; | ||
120 | int r1 = 0, g1 = 0, b1 = 0; | ||
121 | int r2 = 0, g2 = 0, b2 = 0; | ||
122 | for (imageX = 0; imageX < width; imageX++) | ||
123 | { | ||
124 | Color c1 = bitmap.GetPixel(imageX, 0); | ||
125 | Color c2 = bitmap.GetPixel(imageX, lastRow); | ||
126 | |||
127 | r1 += c1.R; | ||
128 | g1 += c1.G; | ||
129 | b1 += c1.B; | ||
130 | |||
131 | r2 += c2.R; | ||
132 | g2 += c2.G; | ||
133 | b2 += c2.B; | ||
134 | } | ||
135 | |||
136 | Color newC1 = Color.FromArgb(r1 / width, g1 / width, b1 / width); | ||
137 | Color newC2 = Color.FromArgb(r2 / width, g2 / width, b2 / width); | ||
138 | |||
139 | for (imageX = 0; imageX < width; imageX++) | ||
140 | { | ||
141 | bitmap.SetPixel(imageX, 0, newC1); | ||
142 | bitmap.SetPixel(imageX, lastRow, newC2); | ||
143 | } | ||
144 | } | ||
145 | |||
146 | |||
147 | int pixelsAcross = sculptType == SculptType.plane ? width : width + 1; | ||
148 | int pixelsDown = sculptType == SculptType.sphere || sculptType == SculptType.cylinder ? height + 1 : height; | ||
149 | |||
150 | for (imageY = 0; imageY < pixelsDown; imageY++) | ||
151 | { | ||
152 | int rowOffset = imageY * width; | ||
153 | |||
154 | for (imageX = 0; imageX < pixelsAcross; imageX++) | ||
155 | { | ||
156 | /* | ||
157 | * p1-----p2 | ||
158 | * | \ f2 | | ||
159 | * | \ | | ||
160 | * | f1 \| | ||
161 | * p3-----p4 | ||
162 | */ | ||
163 | |||
164 | if (imageX < width) | ||
165 | { | ||
166 | p4 = rowOffset + imageX; | ||
167 | p3 = p4 - 1; | ||
168 | } | ||
169 | else | ||
170 | { | ||
171 | p4 = rowOffset; // wrap around to beginning | ||
172 | p3 = rowOffset + imageX - 1; | ||
173 | } | ||
174 | |||
175 | p2 = p4 - width; | ||
176 | p1 = p3 - width; | ||
177 | |||
178 | color = bitmap.GetPixel(imageX == width ? 0 : imageX, imageY == height ? height - 1 : imageY); | ||
179 | |||
180 | x = (color.R - 128) * pixScale; | ||
181 | y = (color.G - 128) * pixScale; | ||
182 | z = (color.B - 128) * pixScale; | ||
183 | |||
184 | Coord c = new Coord(x, y, z); | ||
185 | this.coords.Add(c); | ||
186 | if (viewerMode) | ||
187 | { | ||
188 | this.normals.Add(new Coord()); | ||
189 | this.uvs.Add(new UVCoord(widthUnit * imageX, heightUnit * imageY)); | ||
190 | } | ||
191 | |||
192 | if (imageY > 0 && imageX > 0) | ||
193 | { | ||
194 | Face f1, f2; | ||
195 | |||
196 | if (viewerMode) | ||
197 | { | ||
198 | f1 = new Face(p1, p3, p4, p1, p3, p4); | ||
199 | f1.uv1 = p1; | ||
200 | f1.uv2 = p3; | ||
201 | f1.uv3 = p4; | ||
202 | |||
203 | f2 = new Face(p1, p4, p2, p1, p4, p2); | ||
204 | f2.uv1 = p1; | ||
205 | f2.uv2 = p4; | ||
206 | f2.uv3 = p2; | ||
207 | } | ||
208 | else | ||
209 | { | ||
210 | f1 = new Face(p1, p3, p4); | ||
211 | f2 = new Face(p1, p4, p2); | ||
212 | } | ||
213 | |||
214 | this.faces.Add(f1); | ||
215 | this.faces.Add(f2); | ||
216 | } | ||
217 | } | ||
218 | } | ||
219 | |||
220 | if (scaleSourceImage) | ||
221 | bitmap.Dispose(); | ||
222 | |||
223 | if (viewerMode) | ||
224 | { // compute vertex normals by summing all the surface normals of all the triangles sharing | ||
225 | // each vertex and then normalizing | ||
226 | int numFaces = this.faces.Count; | ||
227 | for (int i = 0; i < numFaces; i++) | ||
228 | { | ||
229 | Face face = this.faces[i]; | ||
230 | Coord surfaceNormal = face.SurfaceNormal(this.coords); | ||
231 | this.normals[face.v1] += surfaceNormal; | ||
232 | this.normals[face.v2] += surfaceNormal; | ||
233 | this.normals[face.v3] += surfaceNormal; | ||
234 | } | ||
235 | |||
236 | int numCoords = this.coords.Count; | ||
237 | for (int i = 0; i < numCoords; i++) | ||
238 | this.coords[i].Normalize(); | ||
239 | |||
240 | if (sculptType != SculptType.plane) | ||
241 | { // blend the vertex normals at the cylinder seam | ||
242 | pixelsAcross = width + 1; | ||
243 | for (imageY = 0; imageY < height; imageY++) | ||
244 | { | ||
245 | int rowOffset = imageY * pixelsAcross; | ||
246 | |||
247 | this.normals[rowOffset] = this.normals[rowOffset + width - 1] = (this.normals[rowOffset] + this.normals[rowOffset + width - 1]).Normalize(); | ||
248 | } | ||
249 | } | ||
250 | |||
251 | foreach (Face face in this.faces) | ||
252 | { | ||
253 | ViewerFace vf = new ViewerFace(0); | ||
254 | vf.v1 = this.coords[face.v1]; | ||
255 | vf.v2 = this.coords[face.v2]; | ||
256 | vf.v3 = this.coords[face.v3]; | ||
257 | |||
258 | vf.n1 = this.normals[face.n1]; | ||
259 | vf.n2 = this.normals[face.n2]; | ||
260 | vf.n3 = this.normals[face.n3]; | ||
261 | |||
262 | vf.uv1 = this.uvs[face.uv1]; | ||
263 | vf.uv2 = this.uvs[face.uv2]; | ||
264 | vf.uv3 = this.uvs[face.uv3]; | ||
265 | |||
266 | this.viewerFaces.Add(vf); | ||
267 | } | ||
268 | } | ||
269 | } | ||
270 | |||
271 | public void AddRot(Quat q) | ||
272 | { | ||
273 | int i; | ||
274 | int numVerts = this.coords.Count; | ||
275 | |||
276 | for (i = 0; i < numVerts; i++) | ||
277 | this.coords[i] *= q; | ||
278 | |||
279 | if (this.viewerFaces != null) | ||
280 | { | ||
281 | int numViewerFaces = this.viewerFaces.Count; | ||
282 | |||
283 | for (i = 0; i < numViewerFaces; i++) | ||
284 | { | ||
285 | ViewerFace v = this.viewerFaces[i]; | ||
286 | v.v1 *= q; | ||
287 | v.v2 *= q; | ||
288 | v.v3 *= q; | ||
289 | |||
290 | v.n1 *= q; | ||
291 | v.n2 *= q; | ||
292 | v.n3 *= q; | ||
293 | |||
294 | this.viewerFaces[i] = v; | ||
295 | } | ||
296 | } | ||
297 | } | ||
298 | |||
299 | public void Scale(float x, float y, float z) | ||
300 | { | ||
301 | int i; | ||
302 | int numVerts = this.coords.Count; | ||
303 | //Coord vert; | ||
304 | |||
305 | Coord m = new Coord(x, y, z); | ||
306 | for (i = 0; i < numVerts; i++) | ||
307 | this.coords[i] *= m; | ||
308 | |||
309 | if (this.viewerFaces != null) | ||
310 | { | ||
311 | int numViewerFaces = this.viewerFaces.Count; | ||
312 | for (i = 0; i < numViewerFaces; i++) | ||
313 | { | ||
314 | ViewerFace v = this.viewerFaces[i]; | ||
315 | v.v1 *= m; | ||
316 | v.v2 *= m; | ||
317 | v.v3 *= m; | ||
318 | this.viewerFaces[i] = v; | ||
319 | } | ||
320 | } | ||
321 | } | ||
322 | |||
323 | public void DumpRaw(String path, String name, String title) | ||
324 | { | ||
325 | if (path == null) | ||
326 | return; | ||
327 | String fileName = name + "_" + title + ".raw"; | ||
328 | String completePath = Path.Combine(path, fileName); | ||
329 | StreamWriter sw = new StreamWriter(completePath); | ||
330 | |||
331 | for (int i = 0; i < this.faces.Count; i++) | ||
332 | { | ||
333 | string s = this.coords[this.faces[i].v1].ToString(); | ||
334 | s += " " + this.coords[this.faces[i].v2].ToString(); | ||
335 | s += " " + this.coords[this.faces[i].v3].ToString(); | ||
336 | |||
337 | sw.WriteLine(s); | ||
338 | } | ||
339 | |||
340 | sw.Close(); | ||
341 | } | ||
342 | } | ||
343 | } | ||