! Example showing how touse OpenGL's feedback mode to capture
! transformed vertices and output them as Encapsulated PostScript.
! Handles limited hidden surface removal by sorting and does
! smooth shading (albeit limited due to PostScript).
! Modified for use with PHAML graphics, William F. Mitchell, 5/15/97
! Translated to Fortran by William F. Mitchell, 6/16/00
! Extended to an example for f90gl by William F. Mitchell, 1/3/03
! Translated to F by William F. Mitchell, 1/23/04
! This is a translation of a C program written by Mark J. Kilgard. The
! original C program had the following notice:
! /* Copyright (c) Mark J. Kilgard, 1997. */
!
! /* This program is freely distributable without licensing fees
! and is provided without guarantee or warrantee expressed or
! implied. This program is -not- in the public domain. */
! (end of Mark's notice)
! The Fortran version is a contribution of NIST, not subject to copyright.
! The OpenGL image must be drawn in display list number 1, since this
! routine uses "call glCallList(1_GLint)"to render the image.
! bsize is the amount of space (in words) toallocate for the feedback buffer.
! doSort indicates whether or not to sort the rendered objects, back to front.
! With F, doSort is ignored (because my sort routine is an old FORTRAN 77
! routine from Netlib and I don't want to translate it).
! filename is the name of the fileto which towrite the postscript. If it
! is not present, the feedback buffer is printed (for debugging)
module rendereps use opengl_gl implicitnone private public :: outputEPS
character(len=74), private, dimension(25) :: gouraudtriangleEPS = (/ & "/bd{bind def}bind def /triangle { aload pop setrgbcolor aload pop 5 3 ",& "roll 4 2 roll 3 2 roll exch moveto lineto lineto closepath fill } bd ",& "/computediff1 { 2 copy sub abs threshold ge {pop pop pop true} { exch 2 ",& "index sub abs threshold ge { pop pop true} { sub abs threshold ge } ifelse",& "} ifelse } bd /computediff3 { 3 copy 0 get 3 1 roll 0 get 3 1 roll 0 get ",& "computediff1 {true} { 3 copy 1 get 3 1 roll 1 get 3 1 roll 1 get ",& "computediff1 {true} { 3 copy 2 get 3 1 roll 2 get 3 1 roll 2 get ",& "computediff1 } ifelse } ifelse } bd /middlecolor { aload pop 4 -1 roll ",& "aload pop 4 -1 roll add 2 div 5 1 roll 3 -1 roll add 2 div 3 1 roll add 2 ",& "div 3 1 roll exch 3 array astore } bd /gouraudtriangle { computediff3 { 4 ",& "-1 roll aload 7 1 roll 6 -1 roll pop 3 -1 roll pop add 2 div 3 1 roll add ",& "2 div exch 3 -1 roll aload 7 1 roll exch pop 4 -1 roll pop add 2 div 3 1 ",& "roll add 2 div exch 3 -1 roll aload 7 1 roll pop 3 -1 roll pop add 2 div 3",& "1 roll add 2 div exch 7 3 roll 10 -3 roll dup 3 index middlecolor 4 1 roll",& "2 copy middlecolor 4 1 roll 3 copy pop middlecolor 4 1 roll 13 -1 roll ",& "aload pop 17 index 6 index 15 index 19 index 6 index 17 index 6 array ",& "astore 10 index 10 index 14 index gouraudtriangle 17 index 5 index 17 ",& "index 19 index 5 index 19 index 6 array astore 10 index 9 index 13 index ",& "gouraudtriangle 13 index 16 index 5 index 15 index 18 index 5 index 6 ",& "array astore 12 index 12 index 9 index gouraudtriangle 17 index 16 index ",& "15 index 19 index 18 index 17 index 6 array astore 10 index 12 index 14 ",& "index gouraudtriangle 18 {pop} repeat } { aload pop 5 3 roll aload pop 7 3",& "roll aload pop 9 3 roll 4 index 6 index 4 index add add 3 div 10 1 roll 7 ",& "index 5 index 3 index add add 3 div 10 1 roll 6 index 4 index 2 index add ",& "add 3 div 10 1 roll 9 {pop} repeat 3 array astore triangle } ifelse } bd " &
/)
! OpenGL's GL_3D_COLOR feedback vertex format. Use as offsets from base entry.
loc = loc + 14 ! Each vertex element in the feedback buffer is 7 GLfloats.
case (GL_POLYGON_TOKEN)
nvertices = buffer(loc)
loc = loc + 1
if (nvertices > 0) then
red = buffer(loc+CRED)
green = buffer(loc+CGREEN)
blue = buffer(loc+CBLUE)
smooth = .false. do i=1,nvertices-1 if (red /= buffer(loc+7*i+CRED) .or. green /= buffer(loc+7*i+CGREEN) &
.or. blue /= buffer(loc+7*i+CBLUE)) then
smooth = .true. exit endif enddo if (smooth) then
! Smooth shaded polygon; varying colors at vetices.
! Draw a filled triangle. write(unit=file,fmt=*) buffer(loc+X),buffer(loc+Y)," moveto" do i=1,nvertices-1 write(unit=file,fmt=*) buffer(loc+7*i+X),buffer(loc+7*i+Y)," lineto" enddo write(unit=file,fmt=*) "closepath fill" write(unit=file,fmt=*) "" endif endif
loc = loc + nvertices * 7 ! Each vertex element in the
! feedback buffer is 7 GLfloats. case (GL_POINT_TOKEN) write(unit=file,fmt=*) buffer(loc+CRED),buffer(loc+CGREEN),buffer(loc+CBLUE), & " setrgbcolor" write(unit=file,fmt=*) buffer(loc+X),buffer(loc+Y),pointSize(1)/2.0,0, &
360," arc fill" write(unit=file,fmt=*) ""
loc = loc + 7 ! Each vertex element in the feedback buffer is 7 GLfloats.
case default write(unit=*,fmt=*) "Incomplete implementation. Unexpected token ",token
loc = 1 do if (loc >= bsize) exit call spewPrimitiveEPS(file, loc, buffer) enddo endsubroutine spewUnsortedFeedback
!! ------------------
!subroutine spewSortedFeedback(file, bsize, buffer)
!! ------------------
!integer, intent(in) :: file, bsize
!real(GLfloat), intent(in) :: buffer(:)
!
! integer(GLint) :: token
! integer :: loc
! real(GLfloat) :: depthSum
! integer :: nprimitives, item
! type(DepthIndex), allocatable :: prims(:)
! integer :: nvertices, i
! real :: ydum(1)
!
!! Count how many primitives there are.
! nprimitives = 0
! loc = 1
! dowhile (loc < bsize)
! token = buffer(loc)
! loc = loc + 1
! selectcase (token)
! case (GL_LINE_TOKEN, GL_LINE_RESET_TOKEN)
! loc = loc + 14
! nprimitives = nprimitives + 1
! case (GL_POLYGON_TOKEN)
! nvertices = buffer(loc)
! loc = loc + 1
! loc = loc + 7*nvertices
! nprimitives = nprimitives + 1
! case (GL_POINT_TOKEN)
! loc = loc + 7
! nprimitives = nprimitives + 1
! case default
! write(unit=*,fmt=*) "Incomplete implementation. Unexpected token ",token
! endselect
! enddo
!
!! Allocate an array of pointers that will point back at
!! primitives in the feedback buffer. There will be one
!! entry per primitive. This array is also where we keep the
!! primitive's average depth. There is one entry per
!! primitive in the feedback buffer.
! allocate(prims(nprimitives))
!
! item = 1
! loc = 1
! dowhile (loc < bsize)
! prims(item)%ptr = loc ! Save this primitive's location.
! token = buffer(loc)
! loc = loc + 1
! selectcase (token)
! case (GL_LINE_TOKEN, GL_LINE_RESET_TOKEN)
! depthSum = buffer(loc+Z) + buffer(loc+7+Z)
! prims(item)%depth = depthSum / 2.0
!! WFM to force triangle edges on top of filled triangle
!! prims(item)%depth = prims(item)%depth - .0001
! loc = loc + 14
! case (GL_POLYGON_TOKEN)
! nvertices = buffer(loc)
! loc = loc + 1
! depthSum = buffer(loc+Z)
! do i=1,nvertices-1
! depthSum = depthSum + buffer(loc+7*i+Z)
! enddo
! prims(item)%depth = depthSum / nvertices
! loc = loc + 7*nvertices
! case (GL_POINT_TOKEN)
! prims(item)%depth = buffer(loc+Z)
! loc = loc + 7
! case default
! write(unit=*,fmt=*) "Incomplete implementation. Unexpected token ",token
! endselect
! item = item + 1
! enddo
!
!! Sort the primitives back to front.
!! call ssort(prims, ydum, nprimitives, -1)
!
!! XXX Understand that sorting by a primitives average depth
!! doesn't allow us to disambiguate some cases like self
!! intersecting polygons. Handling these cases would require
!! breaking up the primitives. That's too involved for this
!! example. Sorting by depth is good enough for lots of
!! applications.
!
!! Emit the Encapsulated PostScript for the primitives in
!! back to front order.
! do item=1,nprimitives
! call spewPrimitiveEPS(file, prims(item)%ptr, buffer)
! enddo
!
! deallocate(prims)
!endsubroutine spewSortedFeedback
! Read back a bunch of OpenGL state to help make the EPS
! consistent with the OpenGL clear color, line width, point
! bsize, and viewport. call glGetFloatv(GL_VIEWPORT, viewport) call glGetFloatv(GL_COLOR_CLEAR_VALUE, clearColor) call glGetFloatv(GL_LINE_WIDTH, lineWidth) call glGetFloatv(GL_POINT_SIZE, pointSize)
! Clear the background like OpenGL had it. write(unit=file,fmt=*) clearColor(1:3)," setrgbcolor" write(unit=file,fmt=*) viewport," rectfill" write(unit=file,fmt=*) ""
! if (doSort) then
! call spewSortedFeedback(file, bsize, buffer)
! else call spewUnsortedFeedback(file, bsize, buffer)
! endif
! Emit EPS trailer. write(unit=file,fmt=*) "grestore" write(unit=file,fmt=*) ""
! WFM I don't know why Mark put this comment instead of showpage, unless some
! apps that take eps input don't like it (ghostview is fine with it)
! write(unit=file,fmt=*) "%Add `showpage' to the end of this file to be able to print to a printer."
write(unit=file,fmt=*) "% 'showpage' is needed to print to a printer, but there" write(unit=file,fmt=*) "% may be some apps for which it must be removed" write(unit=file,fmt=*) "showpage"
allocate(feedbackBuffer(bsize)) call glFeedbackBuffer(bsize, GL_3D_COLOR, feedbackBuffer)
idum = glRenderMode(GL_FEEDBACK) call glCallList(1_GLint)
returned = glRenderMode(GL_RENDER) if (present(filename)) then file = 11 do inquire(unit=file,opened=opened) if (.not. opened) exit file = file + 1 enddo open(unit=file,file=filename,iostat=iostat,status="NEW",action="WRITE") if (iostat==0) then call spewWireFrameEPS(file, doSort, returned, feedbackBuffer, "rendereps") else write(unit=*,fmt=*) "Could not open ", filename endif else
! Helps debugging to be able to see the decode feedback buffer as text. call printBuffer(returned, feedbackBuffer) endif deallocate(feedbackBuffer) endsubroutine outputEPS
endmodule rendereps
!-----------------------------------------------------------
!
! Use the fscene.f90 programto illustrate use of rendereps. Contrast the
! remainder of this fileto the file fscene.f90.
! GLUT Fortran programto render simple red scene.
! In a risky move, this program assumes that the default kind of
! integer is the same as glint and glsizei and also that the
! default real is the same kind as glfloat
module callbacks
private public :: mainmenu, display, myinit, submenu
contains
subroutine display() use opengl_gl use opengl_glu use opengl_glut call gldeletelists(1_gluint, 1_glsizei)
! put the display in list 1 for rendereps call glnewlist(1_gluint, gl_compile_and_execute) call glclear(GL_COLOR_BUFFER_BIT + GL_DEPTH_BUFFER_BIT) call glpushmatrix() call glscalef(1.3, 1.3, 1.3) call glrotatef(20.0, 1.0, 0.0, 0.0)
subroutine reshape(w,h) use opengl_gl use opengl_glu use opengl_glut integer, intent(inout) :: w,h real(kind=gldouble) :: wr,hr,d call glviewport(0, 0, w, h) call glmatrixmode(GL_PROJECTION) call glloadidentity()
wr = w
hr = h
d = 1.0_gldouble if ( w <= h ) then call glortho(-2.5_gldouble, 2.5_gldouble, &
-2.5_gldouble * hr/wr, 2.5_gldouble * hr/wr, &
-10.0_gldouble, 10.0_gldouble) else call glortho(-2.5_gldouble * hr/wr, &
2.5_gldouble * hr/wr, &
-2.5_gldouble, 2.5_gldouble, -10.0_gldouble, &
10.0_gldouble) endif call glmatrixmode(GL_MODELVIEW) endsubroutine reshape
subroutine submenu(value) use opengl_gl use opengl_glu use opengl_glut integer, intent(inout) :: value if ( value == 1 ) then call glenable(GL_DEPTH_TEST) call glenable(GL_LIGHTING) call gldisable(GL_BLEND) call glpolygonmode(GL_FRONT_AND_BACK, GL_FILL) else call gldisable(GL_DEPTH_TEST) call gldisable(GL_LIGHTING) call glcolor3f(1.0, 1.0, 1.0) call glpolygonmode(GL_FRONT_AND_BACK, GL_LINE) call glenable(GL_LINE_SMOOTH) call glenable(GL_BLEND) call glblendfunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) endif call glutpostredisplay() endsubroutine submenu
subroutine mainmenu(value) use rendereps use opengl_glut integer, intent(inout) :: value if (value == 10) then call glutsetcursor(glut_cursor_wait) call outputeps(100000,.true.,"epsout.eps") call glutsetcursor(glut_cursor_inherit) endif if (value == 666) stop endsubroutine mainmenu
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.