[GRASS-SVN] r48608 - in grass/trunk: gui/wxpython/gui_modules include lib/nviz

svn_grass at osgeo.org svn_grass at osgeo.org
Mon Oct 3 14:14:50 EDT 2011


Author: annakrat
Date: 2011-10-03 11:14:49 -0700 (Mon, 03 Oct 2011)
New Revision: 48608

Modified:
   grass/trunk/gui/wxpython/gui_modules/mapdisp.py
   grass/trunk/gui/wxpython/gui_modules/nviz_mapdisp.py
   grass/trunk/gui/wxpython/gui_modules/wxnviz.py
   grass/trunk/include/nviz.h
   grass/trunk/lib/nviz/draw.c
Log:
wxNviz: draw overlays as textures

Modified: grass/trunk/gui/wxpython/gui_modules/mapdisp.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/mapdisp.py	2011-10-03 16:00:49 UTC (rev 48607)
+++ grass/trunk/gui/wxpython/gui_modules/mapdisp.py	2011-10-03 18:14:49 UTC (rev 48608)
@@ -404,9 +404,6 @@
                                              Map = self.Map, tree = self.tree, lmgr = self._layerManager)
             self.MapWindow = self.MapWindow3D
             self.MapWindow.SetCursor(self.cursors["default"])
-            self.MapWindow3D.overlays = self.MapWindow2D.overlays
-            self.MapWindow3D.textdict = self.MapWindow2D.textdict
-            self.MapWindow3D.UpdateOverlays()
             
             # add Nviz notebookpage
             self._layerManager.AddNvizTools()
@@ -428,7 +425,6 @@
             self.MapWindow3D.GetDisplay().Init()
             del os.environ['GRASS_REGION']
             
-            self.MapWindow3D.UpdateOverlays()
             
             # switch from MapWindow to MapWindowGL
             self._mgr.GetPane('2d').Hide()
@@ -1833,6 +1829,7 @@
         """
         if self.MapWindow.dragid > -1:
             id = self.MapWindow.dragid
+            self.MapWindow.dragid = -1
         else:
             # index for overlay layer in render
             if len(self.MapWindow.textdict.keys()) > 0:
@@ -1853,23 +1850,28 @@
             # delete object if it has no text or is not active
             if text == '' or active == False:
                 try:
-                    self.MapWindow.pdc.ClearId(id)
-                    self.MapWindow.pdc.RemoveId(id)
+                    self.MapWindow2D.pdc.ClearId(id)
+                    self.MapWindow2D.pdc.RemoveId(id)
                     del self.MapWindow.textdict[id]
+                    if self.IsPaneShown('3d'):
+                        self.MapWindow3D.UpdateOverlays()
+                        self.MapWindow.UpdateMap()
+                    else:
+                        self.MapWindow2D.UpdateMap(render = False, renderVector = False)
                 except:
                     pass
                 return
 
-            self.MapWindow.pdc.ClearId(id)
-            self.MapWindow.pdc.SetId(id)
+            
             self.MapWindow.textdict[id] = self.dialogs['text'].GetValues()
-##            if self.MapWindow3D:
-##                self.MapWindow3D.textdict[id] = self.dialogs['text'].GetValues()
-                
             
-            self.MapWindow2D.UpdateMap(render = False, renderVector = False)
-            if self.MapWindow3D:
+            if self.IsPaneShown('3d'):
                 self.MapWindow3D.UpdateOverlays()
+                self.MapWindow3D.UpdateMap()
+            else:
+                self.MapWindow2D.pdc.ClearId(id)
+                self.MapWindow2D.pdc.SetId(id)
+                self.MapWindow2D.UpdateMap(render = False, renderVector = False)
             
         self.MapWindow.mouse['use'] = 'pointer'
     

Modified: grass/trunk/gui/wxpython/gui_modules/nviz_mapdisp.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/nviz_mapdisp.py	2011-10-03 16:00:49 UTC (rev 48607)
+++ grass/trunk/gui/wxpython/gui_modules/nviz_mapdisp.py	2011-10-03 18:14:49 UTC (rev 48608)
@@ -26,6 +26,7 @@
 import copy
 import math
 import types
+import tempfile
 
 from threading import Thread
 
@@ -36,6 +37,7 @@
 
 import gcmd
 import globalvar
+import grass.script as grass
 from debug          import Debug
 from mapdisp_window import MapWindow
 from goutput        import wxCmdOutput
@@ -112,11 +114,11 @@
         self.dialogOffset = 5
         # overlays
         self.overlays = {}
-        self.imagedict = {}
+        self.imagelist = []
         self.overlay = wx.Overlay()
-        self.pdc = wx.PseudoDC()
+        #self.pdc = wx.PseudoDC()
         self.textdict = {}
-        self.dragid = None
+        self.dragid = -1
         self.hitradius = 5
     
         if self.lmgr:
@@ -157,7 +159,6 @@
         self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
         self.Bind(wx.EVT_SIZE,             self.OnSize)
         self.Bind(wx.EVT_PAINT,            self.OnPaint)
-        self.Bind(wx.EVT_IDLE,             self.OnIdle)
         self._bindMouseEvents()
         
         self.Bind(EVT_UPDATE_PROP,   self.UpdateMapObjProperties)
@@ -184,23 +185,6 @@
             cplane['on'] = False
             self.cplanes.append(cplane)
             
-    def GetOverlay(self):
-        """!Converts rendered overlay files to wx.Image
-        
-        Updates self.imagedict
-        
-        @return list of images
-        """
-        imgs = []
-        for overlay in self.Map.GetListOfLayers(l_type = "overlay", l_active = True):
-            if os.path.isfile(overlay.mapfile) and os.path.getsize(overlay.mapfile):
-                img = wx.Image(overlay.mapfile, wx.BITMAP_TYPE_ANY)
-                self.imagedict[img] = { 'id' : overlay.id,
-                                        'layer' : overlay }
-                imgs.append(img)
-
-        return imgs        
-    
     def OnClose(self, event):
         # cleanup when window actually closes (on quit) and not just is hidden
         self.UnloadDataLayers(force = True)
@@ -219,12 +203,7 @@
                                        size.height)
         self.size = size
         event.Skip()
-    
-    def OnIdle(self, event):
-        if self.render['overlays']:
-            self.DrawOverlays()
-            self.render['overlays'] = False
-            
+       
     def OnPaint(self, event):
         Debug.msg(1, "GLCanvas.OnPaint()")
         
@@ -269,68 +248,125 @@
             self.init = True
         
         self.UpdateMap()
-    
-    def DrawOverlays(self):
-        """!Draw overlays with wx.Overlay"""
-        dc = wx.ClientDC(self)
-        odc = wx.DCOverlay(self.overlay, dc)
-        self.pdc.Clear()
-        self.pdc.RemoveAll()
-        for img in self.GetOverlay():
-            # draw any active and defined overlays
-            if self.imagedict[img]['layer'].IsActive():
-                id = self.imagedict[img]['id']
-                self.DrawImage(img = img, drawid = id, coords = self.overlays[id]['coords'])
+        
+    def DrawImages(self):
+        """!Draw overlay image"""
+        for texture in self.imagelist:
+            texture.Draw()
             
-        for textId in self.textdict.keys():
-            # create a bitmap the same size as our text
-            self.DrawText(drawid = textId)
+    def GetLegendRect(self):
+        """!Estimates legend size for dragging"""
+        size = None
+        if 1 in self.overlays:
+            for param in self.overlays[1]['cmd'][1:]:
+                if param.startswith("at="):
+                    size = map(int, param.split("=")[-1].split(','))
+                    break
+        if size:
+            wSize = self.GetClientSizeTuple()
+            x, y = size[2]/100. * wSize[0], wSize[1] - (size[1]/100. * wSize[1])
+            w = (size[3] - size[2])/100. * wSize[0]
+            h = (size[1] - size[0])/100. * wSize[1]
             
-        self.pdc.DrawToDC(dc)
-        del odc
-        self.overlay.Reset()
+            rect = wx.Rect(x, y, w, h)
+            return rect
         
-    def DrawImage(self, img, drawid, coords):
-        """!Draw overlay image"""
-        bitmap = wx.BitmapFromImage(img)
-        w,h = bitmap.GetSize()
+        return wx.Rect()        
         
-        self.pdc.BeginDrawing()
-        self.pdc.SetBackground(wx.TRANSPARENT_BRUSH)
-        self.pdc.RemoveId(drawid)
-        self.pdc.SetId(drawid)
-        self.pdc.DrawBitmap(bitmap, coords[0], coords[1], True)
-        self.pdc.SetIdBounds(drawid, wx.Rect(coords[0],coords[1], w, h))
-        self.pdc.EndDrawing()
+    def DrawTextImage(self, textDict, relCoords):
+        """!Draw overlay text"""
+        bmp = wx.EmptyBitmap(textDict['bbox'][2], textDict['bbox'][3])
+        memDC = wx.MemoryDC()
+        memDC.SelectObject(bmp)
         
-    def DrawText(self, drawid):
-        """!Draw overlay text"""
-        self.pdc.BeginDrawing()
-        self.pdc.SetBackground(wx.TRANSPARENT_BRUSH)
-        self.pdc.RemoveId(drawid)
-        self.pdc.SetId(drawid)
-        self.pdc.SetFont(self.textdict[drawid]['font'])
-        self.pdc.SetTextForeground(self.textdict[drawid]['color'])
-        if self.textdict[drawid]['rotation'] == 0:
-            self.pdc.DrawText(self.textdict[drawid]['text'], self.textdict[drawid]['coords'][0],
-                                                             self.textdict[drawid]['coords'][1])
+        mask = self.view['background']['color']
+        if mask == textDict['color']:
+            mask = wx.WHITE
+        memDC.SetBackground(wx.Brush(mask))
+        memDC.Clear()
+        memDC.SetFont(textDict['font'])
+        memDC.SetTextForeground(textDict['color'])
+        if textDict['rotation'] == 0:
+            memDC.DrawText(textDict['text'], 0, 0)
         else:
-            self.pdc.DrawRotatedText(self.textdict[drawid]['text'], self.textdict[drawid]['coords'][0],
-                                                                    self.textdict[drawid]['coords'][1],
-                                                                    self.textdict[drawid]['rotation'])
-        self.pdc.SetIdBounds(drawid, self.textdict[drawid]['bbox'])
-        self.pdc.EndDrawing()
+            memDC.DrawRotatedText(textDict['text'], relCoords[0], relCoords[1],
+                                  textDict['rotation'])
+        bmp.SetMaskColour(mask)
+        memDC.DrawBitmap(bmp, 0, 0, 1)
         
+        filename = grass.tempfile(create = False) + '.png'
+        bmp.SaveFile(filename, wx.BITMAP_TYPE_PNG)
+        memDC.SelectObject(wx.NullBitmap)
+        
+        return filename
+        
     def UpdateOverlays(self):
+        """!Converts rendered overlay files and text labels to wx.Image
+            and then to textures so that they can be rendered by OpenGL.
+            Updates self.imagelist"""
         self.Map.ChangeMapSize(self.GetClientSize())
         self.Map.RenderOverlays(force = True)
-
+        
+        # delete textures
+        overlays = self.Map.GetListOfLayers(l_type = "overlay", l_active = True)
+        for texture in self.imagelist:
+            if texture.id not in [o.id for o in overlays] + self.textdict.keys():
+                self.imagelist.remove(texture)
+        # update images (legend)
+        for overlay in overlays:
+            if os.path.isfile(overlay.mapfile) and os.path.getsize(overlay.mapfile):
+                if overlay.id not in [t.id for t in self.imagelist]: # new
+                    self.CreateTexture(overlay)
+                else:
+                    for t in self.imagelist: # check if it is the same
+                        if t.id == overlay.id and sorted(t.cmd) != sorted(self.overlays[overlay.id]['cmd']):
+                            self.imagelist.remove(t)
+                            self.CreateTexture(overlay)
+        # update text labels
         for textId in self.textdict.keys():
+            if textId not in [t.id for t in self.imagelist]:# new
+                self.CreateTexture(textId = textId)
+            else:
+                for t in self.imagelist:# check if it is the same
+                    if not t.textDict:
+                        continue
+                    self.textdict[textId]['bbox'] = t.textDict['bbox'] # compare without bbox
+                    if t.id == textId and t.textDict and t.textDict != self.textdict[textId]:
+                        self.imagelist.remove(t)
+                        self.CreateTexture(textId = textId)
+            
+    def CreateTexture(self, overlay = None, textId = None):
+        """!Create texture from overlay image or from textdict"""
+        if overlay: # legend  
+            texture = wxnviz.Texture(filepath = overlay.mapfile, overlayId = overlay.id,
+                                     coords = list(self.overlays[overlay.id]['coords']),
+                                     cmd = self.overlays[overlay.id]['cmd'])
+            if overlay.id == 1: # legend
+                texture.SetBounds(self.GetLegendRect())
+        else: # text
             coords, bbox, relCoords = self.TextBounds(self.textdict[textId])
             self.textdict[textId]['coords'] = coords
             self.textdict[textId]['bbox'] = bbox
-        # rerender OnIdle
-        self.render['overlays'] = True
+            file = self.DrawTextImage(self.textdict[textId], relCoords)
+            texture = wxnviz.Texture(filepath = file, overlayId = textId,
+                                     coords = coords, textDict = self.textdict[textId])
+            bbox.OffsetXY(*relCoords)
+            texture.SetBounds(bbox)
+            
+        if not texture.textureId: # texture too big
+            gcmd.GMessage(parent = self, message = 
+                          _("Image is too large, your OpenGL implementation "
+                            "supports maximum texture size %d px.") % texture.maxSize)
+            return
+        self.imagelist.append(texture)
+        
+    def FindObjects(self, mouseX, mouseY, radius):
+        """Find object which was clicked on"""
+        for texture in self.imagelist:
+            if texture.HitTest(mouseX, mouseY, radius):
+                return texture.id
+        return -1
+                
                     
     def OnMouseAction(self, event):
         """!Handle mouse events"""
@@ -394,18 +430,16 @@
         
         if self.mouse['use'] == 'pointer':
             # get decoration or text id
-            self.dragid = None
-            idlist = self.pdc.FindObjects(self.mouse['tmp'][0], self.mouse['tmp'][1],
-                                          self.hitradius)                            
-            if idlist != []:
-                self.dragid = idlist[0] #drag whatever is on top
+            self.dragid = self.FindObjects(self.mouse['tmp'][0], self.mouse['tmp'][1],
+                                          self.hitradius)   
                 
         event.Skip()    
         
     def OnDragging(self, event):
                 
         if self.mouse['use'] == 'pointer':
-            self.DragItem(self.dragid, event)
+            if self.dragid > 0:
+                self.DragItem(self.dragid, event)
             
         if self.mouse['use'] == 'rotate':    
             dx, dy = event.GetX() - self.mouse['tmp'][0], event.GetY() - self.mouse['tmp'][1]
@@ -495,12 +529,9 @@
             self.mouse['use'] = 'pointer'
             self.SetCursor(self.cursors['default'])
         elif self.mouse['use'] == 'pointer':
-            if self.dragid < 99 and self.dragid in self.overlays:
-                self.overlays[self.dragid]['coords'] = self.pdc.GetIdBounds(self.dragid)
-            elif self.dragid > 100 and self.dragid in self.textdict:
-                self.textdict[self.dragid]['bbox'] = self.pdc.GetIdBounds(self.dragid)
-            if self.dragid:    
-                self.dragid = None
+            if self.dragid > 0:    
+                self.dragid = -1
+                self.render['quick'] = False
                 self.Refresh(False)
             
         elif self.mouse['use'] == 'rotate':
@@ -522,15 +553,14 @@
         """!On mouse double click"""
         if self.mouse['use'] != 'pointer': return
         pos = event.GetPositionTuple()
-        idlist  = self.pdc.FindObjects(pos[0], pos[1], self.hitradius)
-        if idlist == []:
-            return
-        self.dragid = idlist[0]
+        self.dragid = self.FindObjects(pos[0], pos[1], self.hitradius)
         
         if self.dragid == 1:
             self.parent.OnAddLegend(None)
         elif self.dragid > 100:
             self.parent.OnAddText(None)
+        else:
+            return
     
     def FocusPanning(self, event):
         """!Simulation of panning using focus"""
@@ -606,28 +636,16 @@
         """
         if not id: return
         Debug.msg (5, "GLWindow.DragItem(): id=%d" % id)
-    
         x, y = self.mouse['tmp']
         dx = event.GetX() - x
         dy = event.GetY() - y
-        self.pdc.SetBackground(wx.TRANSPARENT_BRUSH)
-        self.pdc.TranslateId(id, dx, dy)
+        for texture in self.imagelist:
+            if texture.id == id:
+                texture.MoveTexture(dx, dy)
+
+        self.render['quick'] = True
+        self.Refresh(False)
         
-        r2 = self.pdc.GetIdBounds(id)
-        if type(r2) is list:
-            r2 = wx.Rect(r[0], r[1], r[2], r[3])
-        if id > 100: # text
-            self.textdict[id]['bbox'] = r2
-            self.textdict[id]['coords'][0] += dx
-            self.textdict[id]['coords'][1] += dy
-        else:
-            self.overlays[id]['coords'] = r2
-        
-        dc = wx.ClientDC(self)
-        odc = wx.DCOverlay(self.overlay, dc)
-        odc.Clear()
-        self.pdc.DrawToDC(dc)
-        del odc
         self.mouse['tmp'] = (event.GetX(), event.GetY()) 
         
     def ZoomBack(self):
@@ -836,7 +854,14 @@
                 self._display.DrawArrow()
             if self.decoration['scalebar']:
                 self._display.DrawScalebar()
-        
+        if self.imagelist:
+            if ((self.render['quick'] and self.dragid > -1) or # during dragging
+                (not self.render['quick'] and self.dragid < 0)): # redraw
+                self._display.Start2D()
+                self.DrawImages()
+                
+            
+            
         stop = time.clock()
         
         if self.render['quick'] is False:

Modified: grass/trunk/gui/wxpython/gui_modules/wxnviz.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/wxnviz.py	2011-10-03 16:00:49 UTC (rev 48607)
+++ grass/trunk/gui/wxpython/gui_modules/wxnviz.py	2011-10-03 18:14:49 UTC (rev 48608)
@@ -8,6 +8,7 @@
 
 List of classes:
  - Nviz
+ - Texture
 
 (C) 2008-2011 by the GRASS Development Team
 
@@ -20,8 +21,10 @@
 @author Anna Kratochvilova <KratochAnna seznam.cz> (Google SoC 2011)
 """
 
+import wx
 import sys
 import locale
+import struct
 from threading import Thread
 from math import sqrt
 from numpy import matrix
@@ -38,6 +41,7 @@
     sys.stderr.write(_("3D view mode: %s\n") % e)
     
 from debug import Debug
+import grass.script as grass
 
 log      = None
 progress = None
@@ -1852,3 +1856,112 @@
         for i in range(len(matrix)):
             mtrx[i] = matrix[i]
         GS_set_rotation_matrix(byref(mtrx))
+    
+    def Start2D(self):
+        Nviz_set_2D(self.width, self.height)
+        
+        
+class Texture(object):
+    """!Class representing OpenGL texture"""
+    def __init__(self, filepath, overlayId, coords, cmd = None, textDict = None):
+        """!Load image to texture
+
+        @param filepath path to image file
+        @param overlayId id of overlay (1 for legend, 101 and more for text)
+        @param coords image coordinates
+        @param cmd d.legend command (or None)
+        @param textDict text info (or None)      
+        """
+        self.path = filepath
+        self.image = wx.Image(filepath, wx.BITMAP_TYPE_ANY)
+        self.width = self.image.GetWidth()
+        self.height = self.image.GetHeight()
+        self.id = overlayId
+        self.coords = list(coords)
+        self.bounds = wx.Rect()
+        self.cmd = cmd
+        self.textDict = textDict
+        
+        # alpha needs to be initialized
+        self.image.InitAlpha()
+    
+        # resize image to match 2^n
+        self.Resize()
+        
+        # check max texture size
+        maxSize = c_int()
+        Nviz_get_max_texture(byref(maxSize))
+        self.maxSize = maxSize.value
+        if self.maxSize < self.width or self.maxSize < self.height:
+            # TODO: split up image 
+            self.textureId = None
+        else:
+            self.textureId = self.Load()
+            
+    def __del__(self):
+        """!Delete texture"""
+        if self.textureId:
+            Nviz_del_texture(self.textureId)
+        grass.try_remove(self.path)
+            
+    def Resize(self):    
+        """!Resize image to match 2^n"""
+        n = m = 1
+        while self.width > pow(2,n):
+            n += 1
+        while self.height > pow(2,m):
+            m += 1
+        self.image.Resize(size = (pow(2,n), pow(2,m)), pos = (0, 0))
+        self.width = self.image.GetWidth()
+        self.height = self.image.GetHeight()
+        
+    def Load(self):
+        """!Load image to texture"""  
+        if self.image.HasAlpha():
+            bytesPerPixel = 4
+        else:
+            bytesPerPixel = 3
+        bytes = bytesPerPixel * self.width * self.height
+        rev_val = self.height - 1
+        im = (c_ubyte * bytes)()
+        bytes3 = 3 * self.width * self.height
+        bytes1 = self.width * self.height
+        imageData = struct.unpack(str(bytes3) + 'B', self.image.GetData())
+        if self.image.HasAlpha():
+            alphaData = struct.unpack(str(bytes1) + 'B', self.image.GetAlphaData())
+        
+        # this takes too much time
+        wx.BeginBusyCursor()
+        for i in range(self.height):
+            for j in range(self.width):
+                im[(j + i * self.width) * bytesPerPixel + 0] = imageData[( j + (rev_val - i) * self.width) * 3 + 0]
+                im[(j + i * self.width) * bytesPerPixel + 1] = imageData[( j + (rev_val - i) * self.width) * 3 + 1]
+                im[(j + i * self.width) * bytesPerPixel + 2] = imageData[( j + (rev_val - i) * self.width) * 3 + 2]
+                if self.image.HasAlpha():
+                    im[(j + i * self.width) * bytesPerPixel + 3] = alphaData[( j + (rev_val - i) * self.width)]
+        wx.EndBusyCursor()
+        
+        id = Nviz_load_image(im, self.width, self.height, self.image.HasAlpha())
+        
+        return id
+        
+    def Draw(self):
+        """!Draw texture as an image"""
+        Nviz_draw_image(self.coords[0], self.coords[1], self.width, self.height, self.textureId)
+    
+        
+    def SetBounds(self, rect):
+        """!Set Bounding Rectangle"""
+        self.bounds = rect
+        
+    def HitTest(self, x, y, radius):
+        copy = wx.Rect(*self.bounds)
+        copy.Inflate(radius, radius)
+        return copy.ContainsXY(x, y)
+    
+    def MoveTexture(self, dx, dy):
+        """!Move texture on the screen"""
+        self.coords[0] += dx
+        self.coords[1] += dy
+        self.bounds.OffsetXY(dx, dy)
+        

Modified: grass/trunk/include/nviz.h
===================================================================
--- grass/trunk/include/nviz.h	2011-10-03 16:00:49 UTC (rev 48607)
+++ grass/trunk/include/nviz.h	2011-10-03 18:14:49 UTC (rev 48608)
@@ -180,6 +180,11 @@
 int Nviz_draw_all_vol();
 int Nviz_draw_all(nv_data *);
 int Nviz_draw_quick(nv_data *, int);
+int Nviz_load_image(GLubyte *, int, int, int);
+void Nviz_draw_image(int, int, int, int, int);
+void Nviz_set_2D(int, int);
+void Nviz_del_texture(int);
+void Nviz_get_max_texture(int *);
 
 /* exag.c */
 int Nviz_get_exag_height(double *, double *, double *);

Modified: grass/trunk/lib/nviz/draw.c
===================================================================
--- grass/trunk/lib/nviz/draw.c	2011-10-03 16:00:49 UTC (rev 48607)
+++ grass/trunk/lib/nviz/draw.c	2011-10-03 18:14:49 UTC (rev 48608)
@@ -299,3 +299,115 @@
     
     return 1;
 }
+
+/*!
+  \brief Load image into texture
+
+  \param image_data image data 
+  \param width, height image screen size 
+  \param alpha has alpha channel 
+*/
+int Nviz_load_image(GLubyte *image_data, int width, int height, int alpha)
+{
+    unsigned int texture_id;
+    int  in_format;
+    GLenum format;
+
+    if (alpha)
+    {
+	in_format = 4;
+	format = GL_RGBA;
+    }
+    else
+    {
+	in_format = 3;
+	format = GL_RGB;
+    }
+    glGenTextures( 1, &texture_id);
+    glBindTexture(GL_TEXTURE_2D, texture_id);
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+    glTexImage2D(GL_TEXTURE_2D, 0, in_format, width, height, 0,format,
+		 GL_UNSIGNED_BYTE, image_data);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 
+
+    return texture_id;
+}
+
+/*!
+  \brief Set ortho view for drawing images
+
+  \param width, height image screen size 
+*/
+void Nviz_set_2D(int width, int height)
+{
+    glEnable(GL_BLEND); // images are transparent
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+        
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    glOrtho(0, width, 0, height, -1, 1);
+    
+    // set coordinate system from upper left corner
+    glScalef(1, -1, 1);
+    glTranslatef(0, -height, 0);
+
+    glMatrixMode(GL_MODELVIEW);
+    glLoadIdentity();
+}
+
+/*!
+  \brief Draw image as texture
+
+  \param x, y image coordinates 
+  \param width, height image size 
+  \param texture_id texture id 
+*/
+void Nviz_draw_image(int x, int y, int width, int height, int texture_id)
+{
+    glBindTexture(GL_TEXTURE_2D, texture_id);
+    GS_set_draw(GSD_FRONT);
+
+    glEnable(GL_TEXTURE_2D);
+
+    glBegin(GL_QUADS);
+
+    glTexCoord2d(0.0,1.0);glVertex2d(x, y);
+    glTexCoord2d(0.0,0.0);glVertex2d(x, y + height);
+    glTexCoord2d(1.0,0.0);glVertex2d(x + width, y + height);
+    glTexCoord2d(1.0,1.0);glVertex2d(x + width, y);
+
+    glEnd();
+
+    GS_done_draw();
+    glDisable(GL_TEXTURE_2D);
+}
+
+/*!
+  \brief Delete texture
+
+  \param texture_id texture id
+*/
+void Nviz_del_texture(int texture_id)
+{
+    GLuint t[1];
+
+    t[0] = texture_id;
+    glDeleteTextures(1, t);
+}
+
+/*!
+  \brief Get maximum texture size
+
+*/
+void Nviz_get_max_texture(int *size)
+{
+    glGetIntegerv(GL_MAX_TEXTURE_SIZE, size);
+}



More information about the grass-commit mailing list