corrade-vassal – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Drawing;
5 using System.Drawing.Imaging;
6 using System.IO;
7 using System.Windows.Forms;
8 using Tao.OpenGl;
9 using Tao.Platform.Windows;
10 using ICSharpCode.SharpZipLib.Zip;
11 using OpenMetaverse;
12 using OpenMetaverse.StructuredData;
13 using OpenMetaverse.Imaging;
14 using OpenMetaverse.Rendering;
15  
16 // NOTE: Batches are divided by texture, fullbright, shiny, transparent, and glow
17  
18 namespace PrimWorkshop
19 {
20 public partial class frmPrimWorkshop : Form
21 {
22 #region Form Globals
23  
24 List<FacetedMesh> Prims = null;
25 FacetedMesh CurrentPrim = null;
26 ProfileFace? CurrentFace = null;
27  
28 bool DraggingTexture = false;
29 bool Wireframe = true;
30 int[] TexturePointers = new int[1];
31 Dictionary<UUID, Image> Textures = new Dictionary<UUID, Image>();
32  
33 #endregion Form Globals
34  
35 public frmPrimWorkshop()
36 {
37 InitializeComponent();
38 glControl.InitializeContexts();
39  
40 Gl.glShadeModel(Gl.GL_SMOOTH);
41 Gl.glClearColor(0f, 0f, 0f, 0f);
42  
43 Gl.glClearDepth(1.0f);
44 Gl.glEnable(Gl.GL_DEPTH_TEST);
45 Gl.glDepthMask(Gl.GL_TRUE);
46 Gl.glDepthFunc(Gl.GL_LEQUAL);
47 Gl.glHint(Gl.GL_PERSPECTIVE_CORRECTION_HINT, Gl.GL_NICEST);
48  
49 TexturePointers[0] = 0;
50  
51 // Call the resizing function which sets up the GL drawing window
52 // and will also invalidate the GL control
53 glControl_Resize(null, null);
54 }
55  
56 private void frmPrimWorkshop_Shown(object sender, EventArgs e)
57 {
58 // Get a list of rendering plugins
59 List<string> renderers = RenderingLoader.ListRenderers(".");
60  
61 foreach (string r in renderers)
62 {
63 DialogResult result = MessageBox.Show(
64 String.Format("Use renderer {0}?", r), "Select Rendering Plugin", MessageBoxButtons.YesNo);
65  
66 if (result == DialogResult.Yes)
67 {
68 Render.Plugin = RenderingLoader.LoadRenderer(r);
69 break;
70 }
71 }
72  
73 if (Render.Plugin == null)
74 {
75 MessageBox.Show("No valid rendering plugin loaded, exiting...");
76 Application.Exit();
77 }
78 }
79  
80 #region GLControl Callbacks
81  
82 private void glControl_Paint(object sender, PaintEventArgs e)
83 {
84 Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
85 Gl.glLoadIdentity();
86  
87 // Setup wireframe or solid fill drawing mode
88 if (Wireframe)
89 Gl.glPolygonMode(Gl.GL_FRONT_AND_BACK, Gl.GL_LINE);
90 else
91 Gl.glPolygonMode(Gl.GL_FRONT, Gl.GL_FILL);
92  
93 Vector3 center = Vector3.Zero;
94  
95 Glu.gluLookAt(
96 center.X, (double)scrollZoom.Value * 0.1d + center.Y, center.Z,
97 center.X, center.Y, center.Z,
98 0d, 0d, 1d);
99  
100 // Push the world matrix
101 Gl.glPushMatrix();
102  
103 Gl.glEnableClientState(Gl.GL_VERTEX_ARRAY);
104 Gl.glEnableClientState(Gl.GL_TEXTURE_COORD_ARRAY);
105  
106 // World rotations
107 Gl.glRotatef((float)scrollRoll.Value, 1f, 0f, 0f);
108 Gl.glRotatef((float)scrollPitch.Value, 0f, 1f, 0f);
109 Gl.glRotatef((float)scrollYaw.Value, 0f, 0f, 1f);
110  
111 if (Prims != null)
112 {
113 for (int i = 0; i < Prims.Count; i++)
114 {
115 Primitive prim = Prims[i].Prim;
116  
117 if (i == cboPrim.SelectedIndex)
118 Gl.glColor3f(1f, 0f, 0f);
119 else
120 Gl.glColor3f(1f, 1f, 1f);
121  
122 // Individual prim matrix
123 Gl.glPushMatrix();
124  
125 // The root prim position is sim-relative, while child prim positions are
126 // parent-relative. We want to apply parent-relative translations but not
127 // sim-relative ones
128 if (Prims[i].Prim.ParentID != 0)
129 {
130 // Apply prim translation and rotation
131 Gl.glMultMatrixf(Math3D.CreateTranslationMatrix(prim.Position));
132 Gl.glMultMatrixf(Math3D.CreateRotationMatrix(prim.Rotation));
133 }
134  
135 // Prim scaling
136 Gl.glScalef(prim.Scale.X, prim.Scale.Y, prim.Scale.Z);
137  
138 // Draw the prim faces
139 for (int j = 0; j < Prims[i].Faces.Count; j++)
140 {
141 if (i == cboPrim.SelectedIndex)
142 {
143 // This prim is currently selected in the dropdown
144 //Gl.glColor3f(0f, 1f, 0f);
145 Gl.glColor3f(1f, 1f, 1f);
146  
147 if (j == cboFace.SelectedIndex)
148 {
149 // This face is currently selected in the dropdown
150 }
151 else
152 {
153 // This face is not currently selected in the dropdown
154 }
155 }
156 else
157 {
158 // This prim is not currently selected in the dropdown
159 Gl.glColor3f(1f, 1f, 1f);
160 }
161  
162 #region Texturing
163  
164 Face face = Prims[i].Faces[j];
165 FaceData data = (FaceData)face.UserData;
166  
167 if (data.TexturePointer != 0)
168 {
169 // Set the color to solid white so the texture is not altered
170 //Gl.glColor3f(1f, 1f, 1f);
171 // Enable texturing for this face
172 Gl.glEnable(Gl.GL_TEXTURE_2D);
173 }
174 else
175 {
176 Gl.glDisable(Gl.GL_TEXTURE_2D);
177 }
178  
179 // Bind the texture
180 Gl.glBindTexture(Gl.GL_TEXTURE_2D, data.TexturePointer);
181  
182 #endregion Texturing
183  
184 Gl.glTexCoordPointer(2, Gl.GL_FLOAT, 0, data.TexCoords);
185 Gl.glVertexPointer(3, Gl.GL_FLOAT, 0, data.Vertices);
186 Gl.glDrawElements(Gl.GL_TRIANGLES, data.Indices.Length, Gl.GL_UNSIGNED_SHORT, data.Indices);
187 }
188  
189 // Pop the prim matrix
190 Gl.glPopMatrix();
191 }
192 }
193  
194 // Pop the world matrix
195 Gl.glPopMatrix();
196  
197 Gl.glDisableClientState(Gl.GL_TEXTURE_COORD_ARRAY);
198 Gl.glDisableClientState(Gl.GL_VERTEX_ARRAY);
199  
200 Gl.glFlush();
201 }
202  
203 private void glControl_Resize(object sender, EventArgs e)
204 {
205 Gl.glClearColor(0.39f, 0.58f, 0.93f, 1.0f);
206  
207 Gl.glViewport(0, 0, glControl.Width, glControl.Height);
208  
209 Gl.glPushMatrix();
210 Gl.glMatrixMode(Gl.GL_PROJECTION);
211 Gl.glLoadIdentity();
212  
213 Glu.gluPerspective(50.0d, 1.0d, 0.1d, 256d);
214  
215 Gl.glMatrixMode(Gl.GL_MODELVIEW);
216 Gl.glPopMatrix();
217 }
218  
219 #endregion GLControl Callbacks
220  
221 #region Menu Callbacks
222  
223 private void openPrimXMLToolStripMenuItem1_Click(object sender, EventArgs e)
224 {
225 Prims = null;
226 OpenFileDialog dialog = new OpenFileDialog();
227 dialog.Filter = "Prim Package (*.zip)|*.zip|Sculpt Map (*.png)|*.png|OAR XML (*.xml)|*.xml";
228  
229 if (dialog.ShowDialog() == DialogResult.OK)
230 {
231 if (dialog.FileName.ToLowerInvariant().EndsWith(".zip"))
232 {
233 LoadPrimPackage(dialog.FileName);
234 }
235 else if (dialog.FileName.ToLowerInvariant().EndsWith(".xml"))
236 {
237 LoadXmlPrim(dialog.FileName);
238 }
239 else
240 {
241 LoadSculpt(dialog.FileName);
242 }
243 }
244 }
245  
246 private void LoadDebugPrim()
247 {
248 Prims = new List<FacetedMesh>();
249 Primitive prim = new Primitive();
250 prim.Textures = new Primitive.TextureEntry(UUID.Zero);
251 prim.Scale = Vector3.One;
252 prim.PrimData = ObjectManager.BuildBasicShape(PrimType.Cylinder);
253 prim.PrimData.ProfileHollow = 0.95f;
254 SimpleMesh simpleMesh = Render.Plugin.GenerateSimpleMesh(prim, DetailLevel.High);
255 FacetedMesh facetedMesh = new FacetedMesh();
256 facetedMesh.Faces = new List<Face> { new Face { Vertices = simpleMesh.Vertices, Indices = simpleMesh.Indices } };
257 facetedMesh.Path = simpleMesh.Path;
258 facetedMesh.Profile = simpleMesh.Profile;
259 facetedMesh.Prim = prim;
260 LoadMesh(facetedMesh, ".");
261 PopulatePrimCombobox();
262 glControl.Invalidate();
263 }
264  
265 private void LoadXmlPrim(string filename)
266 {
267 byte[] data = File.ReadAllBytes(filename);
268  
269 OpenMetaverse.Assets.OarFile.LoadObjects(data, XmlObjectLoadedHandler, 0, data.Length);
270 }
271  
272 private void XmlObjectLoadedHandler(OpenMetaverse.Assets.AssetPrim linkset, long bytesRead, long totalBytes)
273 {
274 Prims = new List<FacetedMesh>(linkset.Children.Count + 1);
275  
276 Primitive parent = linkset.Parent.ToPrimitive();
277 {
278 FacetedMesh mesh = null;
279  
280 if (parent.Sculpt == null || parent.Sculpt.SculptTexture == UUID.Zero)
281 mesh = Render.Plugin.GenerateFacetedMesh(parent, DetailLevel.Highest);
282 if (mesh != null)
283 LoadMesh(mesh, null);
284 }
285  
286 for (int i = 0; i < linkset.Children.Count; i++)
287 {
288 Primitive child = linkset.Children[i].ToPrimitive();
289 FacetedMesh mesh = null;
290  
291 if (parent.Sculpt == null || child.Sculpt.SculptTexture == UUID.Zero)
292 mesh = Render.Plugin.GenerateFacetedMesh(child, DetailLevel.Highest);
293 if (mesh != null)
294 LoadMesh(mesh, null);
295 }
296  
297 PopulatePrimCombobox();
298  
299 glControl.Invalidate();
300 }
301  
302 private void LoadSculpt(string filename)
303 {
304 // Try to parse this as an image file
305 Image sculptTexture = Image.FromFile(filename);
306  
307 Primitive prim = new Primitive();
308 prim.PrimData = ObjectManager.BuildBasicShape(PrimType.Sculpt);
309 prim.Sculpt = new Primitive.SculptData { SculptTexture = UUID.Random(), Type = SculptType.Sphere };
310 prim.Textures = new Primitive.TextureEntry(UUID.Zero);
311 prim.Scale = Vector3.One * 3f;
312  
313 FacetedMesh mesh = Render.Plugin.GenerateFacetedSculptMesh(prim, (Bitmap)sculptTexture, DetailLevel.Highest);
314 if (mesh != null)
315 {
316 Prims = new List<FacetedMesh>(1);
317 LoadMesh(mesh, null);
318 }
319  
320 glControl.Invalidate();
321 }
322  
323 private void LoadPrimPackage(string filename)
324 {
325 string tempPath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), System.IO.Path.GetRandomFileName());
326  
327 try
328 {
329 // Create a temporary directory
330 Directory.CreateDirectory(tempPath);
331  
332 FastZip fastzip = new FastZip();
333 fastzip.ExtractZip(filename, tempPath, String.Empty);
334 }
335 catch (Exception ex)
336 {
337 MessageBox.Show(ex.Message);
338 return;
339 }
340  
341 // Check for the prims.xml file
342 string primsFile = System.IO.Path.Combine(tempPath, "prims.xml");
343 if (!File.Exists(primsFile))
344 {
345 MessageBox.Show("prims.xml not found in the archive");
346 return;
347 }
348  
349 OSD osd = null;
350  
351 try { osd = OSDParser.DeserializeLLSDXml(File.ReadAllText(primsFile)); }
352 catch (Exception ex) { MessageBox.Show(ex.Message); }
353  
354 if (osd != null && osd.Type == OSDType.Map)
355 {
356 List<Primitive> primList = Helpers.OSDToPrimList(osd);
357 Prims = new List<FacetedMesh>(primList.Count);
358  
359 for (int i = 0; i < primList.Count; i++)
360 {
361 Primitive prim = primList[i];
362 FacetedMesh mesh = null;
363  
364 if (prim.Sculpt.SculptTexture != UUID.Zero)
365 {
366 Image sculptTexture = null;
367 if (LoadTexture(tempPath, prim.Sculpt.SculptTexture, ref sculptTexture))
368 mesh = Render.Plugin.GenerateFacetedSculptMesh(prim, (Bitmap)sculptTexture, DetailLevel.Highest);
369 }
370 else
371 {
372 mesh = Render.Plugin.GenerateFacetedMesh(prim, DetailLevel.Highest);
373 }
374  
375 if (mesh != null)
376 LoadMesh(mesh, tempPath);
377 }
378  
379 // Setup the dropdown list of prims
380 PopulatePrimCombobox();
381  
382 glControl.Invalidate();
383 }
384 else
385 {
386 MessageBox.Show("Failed to load LLSD formatted primitive data from " + filename);
387 }
388  
389 Directory.Delete(tempPath);
390 }
391  
392 private void LoadMesh(FacetedMesh mesh, string basePath)
393 {
394 // Create a FaceData struct for each face that stores the 3D data
395 // in a Tao.OpenGL friendly format
396 for (int j = 0; j < mesh.Faces.Count; j++)
397 {
398 Face face = mesh.Faces[j];
399 FaceData data = new FaceData();
400  
401 // Vertices for this face
402 data.Vertices = new float[face.Vertices.Count * 3];
403 for (int k = 0; k < face.Vertices.Count; k++)
404 {
405 data.Vertices[k * 3 + 0] = face.Vertices[k].Position.X;
406 data.Vertices[k * 3 + 1] = face.Vertices[k].Position.Y;
407 data.Vertices[k * 3 + 2] = face.Vertices[k].Position.Z;
408 }
409  
410 // Indices for this face
411 data.Indices = face.Indices.ToArray();
412  
413 // Texture transform for this face
414 Primitive.TextureEntryFace teFace = mesh.Prim.Textures.GetFace((uint)j);
415 Render.Plugin.TransformTexCoords(face.Vertices, face.Center, teFace, mesh.Prim.Scale);
416  
417 // Texcoords for this face
418 data.TexCoords = new float[face.Vertices.Count * 2];
419 for (int k = 0; k < face.Vertices.Count; k++)
420 {
421 data.TexCoords[k * 2 + 0] = face.Vertices[k].TexCoord.X;
422 data.TexCoords[k * 2 + 1] = face.Vertices[k].TexCoord.Y;
423 }
424  
425 // Texture for this face
426 if (!String.IsNullOrEmpty(basePath) && LoadTexture(basePath, teFace.TextureID, ref data.Texture))
427 {
428 Bitmap bitmap = new Bitmap(data.Texture);
429 bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
430 Rectangle rectangle = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
431 BitmapData bitmapData = bitmap.LockBits(rectangle, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
432  
433 Gl.glGenTextures(1, out data.TexturePointer);
434 Gl.glBindTexture(Gl.GL_TEXTURE_2D, data.TexturePointer);
435  
436 Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_LINEAR_MIPMAP_LINEAR);
437 Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_LINEAR);
438 Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_WRAP_S, Gl.GL_REPEAT);
439 Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_WRAP_T, Gl.GL_REPEAT);
440 Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_GENERATE_MIPMAP, Gl.GL_TRUE);
441  
442 Glu.gluBuild2DMipmaps(Gl.GL_TEXTURE_2D, Gl.GL_RGB8, bitmap.Width, bitmap.Height, Gl.GL_BGR, Gl.GL_UNSIGNED_BYTE, bitmapData.Scan0);
443  
444 bitmap.UnlockBits(bitmapData);
445 bitmap.Dispose();
446 }
447  
448 // Set the UserData for this face to our FaceData struct
449 face.UserData = data;
450 mesh.Faces[j] = face;
451 }
452  
453 Prims.Add(mesh);
454 }
455  
456 private bool LoadTexture(string basePath, UUID textureID, ref System.Drawing.Image texture)
457 {
458 if (Textures.ContainsKey(textureID))
459 {
460 texture = Textures[textureID];
461 return true;
462 }
463  
464 string texturePath = System.IO.Path.Combine(basePath, textureID.ToString());
465  
466 if (File.Exists(texturePath + ".tga"))
467 {
468 try
469 {
470 texture = (Image)LoadTGAClass.LoadTGA(texturePath + ".tga");
471 Textures[textureID] = texture;
472 return true;
473 }
474 catch (Exception)
475 {
476 }
477 }
478 else if (File.Exists(texturePath + ".jp2"))
479 {
480 try
481 {
482 ManagedImage managedImage;
483 if (OpenJPEG.DecodeToImage(File.ReadAllBytes(texturePath + ".jp2"), out managedImage, out texture))
484 {
485 Textures[textureID] = texture;
486 return true;
487 }
488 }
489 catch (Exception)
490 {
491 }
492 }
493  
494 return false;
495 }
496  
497 private void textureToolStripMenuItem_Click(object sender, EventArgs e)
498 {
499 picTexture.Image = null;
500 TexturePointers[0] = 0;
501  
502 OpenFileDialog dialog = new OpenFileDialog();
503  
504 if (dialog.ShowDialog() == DialogResult.OK)
505 {
506 try
507 {
508 picTexture.Image = System.Drawing.Image.FromFile(dialog.FileName);
509 Bitmap bitmap = new Bitmap(picTexture.Image);
510 bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
511  
512 // Create the GL texture space
513 Gl.glGenTextures(1, TexturePointers);
514 Rectangle rectangle = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
515 BitmapData bitmapData = bitmap.LockBits(rectangle, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
516  
517 Gl.glBindTexture(Gl.GL_TEXTURE_2D, TexturePointers[0]);
518  
519 Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_LINEAR_MIPMAP_LINEAR);
520 Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_LINEAR);
521 Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_WRAP_S, Gl.GL_CLAMP_TO_EDGE);
522 Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_WRAP_T, Gl.GL_CLAMP_TO_EDGE);
523 Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_GENERATE_MIPMAP, Gl.GL_TRUE);
524  
525 Glu.gluBuild2DMipmaps(Gl.GL_TEXTURE_2D, Gl.GL_RGB8, bitmap.Width, bitmap.Height, Gl.GL_BGR, Gl.GL_UNSIGNED_BYTE, bitmapData.Scan0);
526  
527 bitmap.UnlockBits(bitmapData);
528 bitmap.Dispose();
529 }
530 catch (Exception ex)
531 {
532 MessageBox.Show("Failed to load image from file " + dialog.FileName + ": " + ex.Message);
533 }
534 }
535 }
536  
537 private void savePrimXMLToolStripMenuItem_Click(object sender, EventArgs e)
538 {
539  
540 }
541  
542 private void saveTextureToolStripMenuItem_Click(object sender, EventArgs e)
543 {
544  
545 }
546  
547 private void oBJToolStripMenuItem_Click(object sender, EventArgs e)
548 {
549 SaveFileDialog dialog = new SaveFileDialog();
550 dialog.Filter = "OBJ files (*.obj)|*.obj";
551  
552 if (dialog.ShowDialog() == DialogResult.OK)
553 {
554 if (!MeshToOBJ.MeshesToOBJ(Prims, dialog.FileName))
555 {
556 MessageBox.Show("Failed to save file " + dialog.FileName +
557 ". Ensure that you have permission to write to that file and it is currently not in use");
558 }
559 }
560 }
561  
562 private void exitToolStripMenuItem_Click(object sender, EventArgs e)
563 {
564 Close();
565 }
566  
567 private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
568 {
569 MessageBox.Show(
570 "Written by John Hurliman <jhurliman@jhurliman.org> (http://www.jhurliman.org/)");
571 }
572  
573 #endregion Menu Callbacks
574  
575 #region Scrollbar Callbacks
576  
577 private void scroll_ValueChanged(object sender, EventArgs e)
578 {
579 glControl.Invalidate();
580 }
581  
582 private void scrollZoom_ValueChanged(object sender, EventArgs e)
583 {
584 glControl_Resize(null, null);
585 glControl.Invalidate();
586 }
587  
588 #endregion Scrollbar Callbacks
589  
590 #region PictureBox Callbacks
591  
592 private void picTexture_MouseDown(object sender, MouseEventArgs e)
593 {
594 DraggingTexture = true;
595 }
596  
597 private void picTexture_MouseUp(object sender, MouseEventArgs e)
598 {
599 DraggingTexture = false;
600 }
601  
602 private void picTexture_MouseLeave(object sender, EventArgs e)
603 {
604 DraggingTexture = false;
605 }
606  
607 private void picTexture_MouseMove(object sender, MouseEventArgs e)
608 {
609 if (DraggingTexture)
610 {
611 // What is the current action?
612 // None, DraggingEdge, DraggingCorner, DraggingWhole
613 }
614 else
615 {
616 // Check if the mouse is close to the edge or corner of a selection
617 // rectangle
618  
619 // If so, change the cursor accordingly
620 }
621 }
622  
623 private void picTexture_Paint(object sender, PaintEventArgs e)
624 {
625 // Draw the current selection rectangles
626 }
627  
628 #endregion PictureBox Callbacks
629  
630 private void cboPrim_SelectedIndexChanged(object sender, EventArgs e)
631 {
632 CurrentPrim = (FacetedMesh)cboPrim.Items[cboPrim.SelectedIndex];
633 PopulateFaceCombobox();
634  
635 glControl.Invalidate();
636 }
637  
638 private void cboFace_SelectedIndexChanged(object sender, EventArgs e)
639 {
640 CurrentFace = (ProfileFace)cboFace.Items[cboFace.SelectedIndex];
641  
642 glControl.Invalidate();
643 }
644  
645 private void PopulatePrimCombobox()
646 {
647 cboPrim.Items.Clear();
648  
649 if (Prims != null)
650 {
651 for (int i = 0; i < Prims.Count; i++)
652 cboPrim.Items.Add(Prims[i]);
653 }
654  
655 if (cboPrim.Items.Count > 0)
656 cboPrim.SelectedIndex = 0;
657 }
658  
659 private void PopulateFaceCombobox()
660 {
661 cboFace.Items.Clear();
662  
663 if (CurrentPrim != null && CurrentPrim.Profile.Faces != null)
664 {
665 for (int i = 0; i < CurrentPrim.Profile.Faces.Count; i++)
666 cboFace.Items.Add(CurrentPrim.Profile.Faces[i]);
667 }
668  
669 if (cboFace.Items.Count > 0)
670 cboFace.SelectedIndex = 0;
671 }
672  
673 private void wireframeToolStripMenuItem_Click(object sender, EventArgs e)
674 {
675 wireframeToolStripMenuItem.Checked = !wireframeToolStripMenuItem.Checked;
676 Wireframe = wireframeToolStripMenuItem.Checked;
677  
678 glControl.Invalidate();
679 }
680  
681 private void worldBrowserToolStripMenuItem_Click(object sender, EventArgs e)
682 {
683 frmBrowser browser = new frmBrowser();
684 browser.ShowDialog();
685 }
686 }
687  
688 public struct FaceData
689 {
690 public float[] Vertices;
691 public ushort[] Indices;
692 public float[] TexCoords;
693 public int TexturePointer;
694 public System.Drawing.Image Texture;
695 // TODO: Normals
696 }
697  
698 public static class Render
699 {
700 public static IRendering Plugin;
701 }
702 }