New StdGen for each OpenGL/GLUT loop iteration - opengl

I have a program that displays a bunch of random triangles using Haskell, OpenGL, and GLUT. However I'd like the random triangles to change every time I click, or something of that nature (not important when they change).
Currently my working code looks like this:
main :: IO ()
main = do
(pname, _) <- getArgsAndInitialize
createWindow $ "Haskellisa"
-- TODO set based on command line args
windowSize $= (Size 640 480)
blend $= Enabled
blendFunc $= (SrcAlpha, OneMinusSrcAlpha)
displayCallback $= display
keyboardMouseCallback $= Just (keyboardMouse)
mainLoop
display :: IO ()
display = do
clear [ ColorBuffer ]
gen0 <- getStdGen
let (tris,gen1) = randomTris 10 gen0
let (cols,gen2) = randomColor4s 10 gen1
let triColPairs = zip tris cols
mapM_ (\(tri, col) -> drawTri tri col) triColPairs
flush
However display takes the same StdGen every time by calling getStdGen. What I'd like is for the gen2 from the line let (cols,gen2)... to be used as the generator for the next time, but obviously that requires some sort of mutable state or something of that nature.
What's the best way to do what I'm asking, such that I will get different randomness every time display runs?

Since you're in IO anyway, you could just store gen2 via setStdGen:
setStdGen gen2
so your next round takes off where your previous stopped.
Another option is to split the StdGen and use one of the results using newStdGen instead of getStdGen.

Related

How do I animate an arrow using gnuplot? [duplicate]

I'm trying to animate 2D vector with gnuplot. I want to show one line i.e, one vector at a time.
My Data Structure is as follows: They x,y,u,v
2.24448 0.270645 1.00 1.00
3.24448 0.270645 0.500 1.20
I'm able to create a static plot sing following command:
plot "datam.dat" using 1:2:3:4 with vectors filled head lw 3
Here is the output:
Here is my question: I would like to animate and show one row (i.e,) one vector at a time, how to accomplish this in GNU plot using GIF?
Thanks
Animated GIFs are created with set terminal gif animate. Check help gif for details.
Below is a simple example (tested with gnuplot 5.2). You have to make a new plot for each frame. So, put your plot command into a do for-loop. With every ::i::i you are plotting only the ith line (check help every). If you don't know the total number of lines of your datafile, do stats "YourFile.dat" and the variable STATS_records will tell you this number.
Code:
### animated graph with vectors
reset session
set term gif size 300,300 animate delay 12 loop 0 optimize
set output "AnimateVectors.gif"
# create some dummy data
set angle degrees
N = 60
set samples N
set table $Data
plot [0:360] '+' u (cos($1)):(sin($1)):(sin($1)):(cos($1)) w table
unset table
set xrange[-2.5:2.5]
set yrange[-2.5:2.5]
do for [i=0:N-1] {
plot $Data u 1:2:3:4 every ::i::i w vectors lw 2 lc rgb "red" notitle
}
set output
### end of code
Result:
Addition:
This would be the non-animated version, e.g. in a wxt-terminal.
Code:
### non-animated graph with vectors
reset session
set term wxt size 400,400
# create some dummy data
set angle degrees
N = 60
set samples N
set table $Data
plot [0:360] '+' u (cos($1)):(sin($1)):(sin($1)):(cos($1)) w table
unset table
set xrange[-2.5:2.5]
set yrange[-2.5:2.5]
plot $Data u 1:2:3:4 w vectors lw 1.5 lc rgb "red" notitle
### end of code
Result:
Addition2:
Do you maybe mean something like this? A "semi"-animated arrow? By the way, as you can see the arrow look quite different in gif and wxt terminal.
Code:
### "semi"-animated graph with vectors
reset session
set term gif size 300,300 animate delay 12 loop 0 optimize
set output "AnimateVectorsSemi.gif"
# create some dummy data
set angle degrees
N = 60
set samples N
set table $Data
plot [0:360] '+' u (cos($1)):(sin($1)):(sin($1)):(cos($1)) w table
unset table
set xrange[-2.5:2.5]
set yrange[-2.5:2.5]
do for [i=0:N-1] {
plot $Data u 1:2:3:4 every ::0::i w vectors lw 1.5 lc rgb "red" notitle
}
set output
### end of code
Result:

How can I generate a square wave plot of a pulse train of multiple signals from the data in a csv file (in Linux)?

For instance, given the data in a text file:
10:37:18.459 1
10:37:18.659 0
10:37:19.559 1
How could this be displayed as an image that looked like a square wave that correctly represented the high time and low time? I am trying both gnuplot and scipy. The result should ultimately include more than one sensor, and all plots would have to be displayed above one another so as to show a time delta.
The code in the following link creates a square wave from the formulas listed,
link to waveforms. How can the lower waveform (pwm) be driven by the numbers above if they were in a file (to show a high state for 200 ms, then a low state for 100 ms, and finally a high state)?
If I understood your question correctly you want to plot a step function based on timedata. To avoid further guessing please specify in more detail.
In gnuplot there is the plotting style with steps. Check help steps.
Code:
### display waveform as steps
reset sesion
$Data <<EOD
10:37:18.459 1
10:37:18.659 0
10:37:19.559 1
10:37:19.789 0
10:37:20.123 1
10:37:20.456 0
10:37:20.789 1
EOD
set yrange [-0.05:1.2]
myTimeFmt = "%H:%M:%S" # input time format
set format x "%M:%.1S" time # output time format on x axis
plot $Data u (timecolumn(1,myTimeFmt)):2 w steps lc rgb "red" lw 2 ti "my square wave"
### end of code
Result:
The answer I ended up with was:
file_info = os.stat( self.__outfile)
if file_info.st_size:
x,y,z,a = np.genfromtxt( self.__outfile, delimiter=',',unpack=True )
fig = plt.figure(self.__outfile)
ax = fig.add_subplot(111)
fig.canvas.draw()
test_array = [(datetime.datetime.utcfromtimestamp(e2).strftime('%d_%H:%M:%S.%f')).rstrip('0') for e2 in x]
plt.xticks(x, test_array)
l1, = plt.plot(x,y, drawstyle='steps-post')
l2, = plt.plot(x,a-2, drawstyle='steps-post')
l3, = plt.plot(x,z-4, drawstyle='steps-post')
ax.grid()
ax.set_xlabel('Time (s)')
ax.set_ylabel('HIGH/LOW')
ax.set_ylim((-6.5,1.5))
ax.set_title('Sensor Sequence')
fig.autofmt_xdate()
ax.legend([l1,l2, l3],['sprinkler','lights', 'alarm'], loc='lower left')
plt.show()
I had a input file that had convertDateToFloat values in it. That was passed in to this function. The name is perhaps misleading (__outfile), but on the previous function, it was the output.

How to redraw a curve to Photoshop with Autoit?

I want to draw a specific curve line to Photoshop or to mspaint. This drawing action should be saved for the possibility to redraw that curve in the exact same way. How can I do it with Autoit? Is there a recording and play mechanism? As far as I read, the AU3 recorder is not available anymore.
Photoshop is just an example. I want to be able to do that kind of drawing record for different purposes and programs. Maybe also for online image editors or something.
I am not that familiar with Autoit yet. I do not expect a full code example, maybe you can give me an idea - that would be very helpful.
Currently I tried a bit with mouse functions like MouseDown, MouseMove etc. and it is quite funny, but i do not really have a concept to record and redraw these mouse actions.
If I have to clarify more please let me know - i will do my best to be precise.
I recommend using two scripts, one for recording and the second to replay recorded actions.
Code for the recording:
; declaration
Global $sFileCoordinates = #ScriptDir & '\RecordedMouseMoveCoordinates.txt'
Global $iRecordingDurationInSeconds = 10
Global $iXSave, $iYSave
; functions
Func _recordMouseMoveCoordinatesToFile()
Local $aPos = MouseGetPos()
If $aPos[0] <> $iXSave Or $aPos[1] <> $iYSave Then
FileWrite($hFile, $aPos[0] & ',' & $aPos[1] & #CRLF)
Local $aPos = MouseGetPos()
$iXSave = $aPos[0]
$iYSave = $aPos[1]
EndIf
Sleep(80)
EndFunc
; processing
Sleep(4000) ; wait 4 seconds to place your mouse to the start position
Global $hFile = FileOpen($sFileCoordinates, 1 + 256)
Global $hTimer = TimerInit()
While Round((TimerDiff($hTimer) / 1000), 1) <= $iRecordingDurationInSeconds
ToolTip(Round((TimerDiff($hTimer) / 1000), 1))
_recordMouseMoveCoordinatesToFile()
WEnd
FileClose($hFile)
Recording will start after a 4 second delay. This should allow to move your mouse to the start point of your drawing action.
Global $iRecordingDurationInSeconds = 10 means your drawing action should be finished in 10 seconds (a tooltip displays remaining seconds). And here the seconds script.
Code to redraw curve:
; declaration
Global $sFileCoordinates = #ScriptDir & '\RecordedMouseMoveCoordinates.txt'
; functions
Func _getFileContent($sFile)
Local $hFile = FileOpen($sFile, 256)
Local $sFileContent = FileRead($hFile)
FileClose($hFile)
Return $sFileContent
EndFunc
Func _drawRecordedMouseMoveCoordinatesFromFile($sContent)
Local $aFileContent = StringSplit($sContent, #CRLF, 1)
Local $iX = StringSplit($aFileContent[1], ',')[1]
Local $iY = StringSplit($aFileContent[1], ',')[2]
MouseMove($iX, $iY, 4)
MouseDown('left')
For $i = 1 To $aFileContent[0] Step 1
If $aFileContent[$i] <> '' Then
Local $iX = StringSplit($aFileContent[$i], ',')[1]
Local $iY = StringSplit($aFileContent[$i], ',')[2]
MouseMove($iX, $iY, 4)
EndIf
Next
MouseUp('left')
EndFunc
; processing
Sleep(2000) ; wait 2 seconds till start
Global $sFileContent = _getFileContent($sFileCoordinates)
_drawRecordedMouseMoveCoordinatesFromFile($sFileContent)
There is a start delay of 2 seconds. All saved coordinates will be executed in the same way recorded. It starts with MouseDown('left'), then the mouse movements to MouseUp('left').
Notice:
This approach isn't really robust because of the coordinates which aren't relative to your window. Please see Opt('MouseCoordMode', 0|1|2) in the help file for more information. If you want to draw more than just one line or curve this approach isn't the best. But as your question describes only that requirement it should be fine.

Changing canvas scroll region on Python turtle canvas

Can I change the scrollregion on a Python turtle canvas? I want the drawing to move with it, not just the coordinates to shift. The appearance I'm going for is side-scroller like, where the screen's display region moves to center the turtle onscreen.
I've tried using turtle.setworldcoordinates(llx, lly, urx, ury), but, from the documentation, "This performs a screen.reset()". I've also looked at this SO question , but this involves scroll bars, will not center the turtle easily, and has a limited canvas space. What I'm looking for is something that:
Moves the display region to center the turtle
Also moves the drawing
Has an infinite scroll region
does not display scroll bars
can be called quickly with a function
My best guess would be to be able to have an infinite scrolled canvas somehow, then hide the scroll bars and set them according to turtle position.
Is this possible in Python 2.7? I don't mind if it uses tkinter as well.
EDIT: 6-3-15
I found the canvas.xview and canvas.yview functions, but they don't seem to work once I define screen = turtle.TurtleScreen(canvas), and TurtleScreen has no xview or yview functions. I can't seem to make this work.
Then I found turtle.ScrolledCanvas(). This seems ideal except it has no methods for setting scroll manually from the program. Can I set the scroll manually on a turtle.ScrolledCanvas()???
The position of a canvas can be changed without a reset using canvas.place() method. It will move the turtle and the drawings too, so the turtle needs to be relocated after every move.
The next code moves the canvas with Left and Right arrows and draws a circle with Space, while keeping the turtle in the center. No ScrolledCanvas needed, just a very large standard canvas:
import turtle
import Tkinter as tk
def keypress(event):
global xx, canvas, t, speed
ev = event.keysym
if ev == 'Left':
xx += speed
else:
xx -= speed
canvas.place(x=xx)
t.setposition((-canvas.winfo_width() / 4) - (xx + 250), 0)
return None
def drawCircle(_):
global t
t.pendown()
t.fillcolor(0, 0, 1.0)
t.fill(True)
t.circle(100)
t.fill(False)
t.fillcolor(0, 1, 0)
t.penup()
# Set the main window
window = tk.Tk()
window.geometry('500x500')
window.resizable(False, False)
# Create the canvas. Width is larger than window
canvas = turtle.Canvas(window, width=2000, height=500)
xx = -500
canvas.place(x=xx, y=0)
# Bring the turtle
t = turtle.RawTurtle(canvas)
t.shape('turtle') # nicer look
t.speed(0)
t.penup()
t.setposition((-canvas.winfo_width() / 4) - (xx + 250), 0)
# key binding
window.bind('<KeyPress-Left>', keypress)
window.bind('<KeyPress-Right>', keypress)
window.bind('<KeyPress-space>', drawCircle)
drawCircle(None)
speed = 3 # scrolling speed
window.mainloop()
Having a real infinite scrolling would require to redraw every item in the canvas every time with the required offset, instead of actually moving or scrolling the canvas. Functions like create_image() can give the illusion of movement with static backgrounds, but it resets the drawings.

How to change textures in OpenGL using Haskell

I'm stuck trying to get multiple textures working in OpenGL using Haskell. I've been following the NeHe tuts and some various other OpenGL resources online, but the combination of slightly different calls and my newbness has caused a roadblock.
To be specific I want to render two cubes, each with a different texture (same texture for all 6 faces for the time being). Rendering one cube, with a texture is fine. Rendering multiple cubes of the same texture works fine as well. But I've not been able to figure out how to change textures for the two cubes
If I'm not mistaken the call to change textures is:
textureBinding $ Texture2D $= Just *mytexture*
where mytexture is supposed to be some form of textureID (a TextureObject). What the heck goes into the mytexture spot? This should be really easy but I've spent the better part of 2 days trying to figure this out to no avail. Any help is appreciated.
Main:
-- imports --
import Graphics.Rendering.OpenGL
import Graphics.UI.GLUT
import Data.IORef
import Display
import Bindings
import Control.Monad
import Textures
-- main --
main = do
(program, _) <- getArgsAndInitialize -- convenience, return program name and non-GLUT commands
initialDisplayMode $= [DoubleBuffered, WithDepthBuffer] -- inital display mode
initialWindowSize $= Size 600 600
createWindow "OpenGL Basics"
reshapeCallback $= Just reshape
angle <- newIORef (0.1::GLfloat) -- linked to angle of rotation (speed?)
delta <- newIORef (0.1::GLfloat)
position <- newIORef (0.0::GLfloat, 0.0) -- position, pass to display
texture Texture2D $= Enabled
tex <- getAndCreateTextures ["goldblock","pumpkintop"]
keyboardMouseCallback $= Just (keyboardMouse delta position) --require keys, delta, and position
idleCallback $= Just (idle angle delta) --ref idle angle and delta
displayCallback $= (display angle position tex) --ref display angle and delta
cullFace $= Just Front
mainLoop -- runs forever until a hard exit is called
In Main I call getAndCreateTextures (borrowed from the net), which returns a list of texture objects.
Display (for rendering):
-- display (main) --
display angle position tex = do
clear [ColorBuffer, DepthBuffer]
loadIdentity --modelview
shadeModel $= Smooth
(x,z) <- get position --get current position from init or keys
translate $ Vector3 x 0 z -- move to the position before drawing stuff
-- DO STUFF HERE
-- texture $ Texture2D $= Just wtfgoeshere
preservingMatrix $ do
a <- get angle
rotate a $ Vector3 (1::GLfloat) 0 0
-- rotate a $ Vector3 0 0 (1::GLfloat)
rotate a $ Vector3 0 (1::GLfloat) 0
-- scale 0.7 0.7 (0.7::GLfloat)
-- color $ Color3 (0.5::GLfloat) (0.1::GLfloat) (0.1::GLfloat)
cubeTexture (0.1::GLfloat)
swapBuffers
--idle (main)
idle angle delta = do
a <- get angle -- get existing angle
d <- get delta -- get delta
angle $= a + d -- new angle is old angle plus plus delta
postRedisplay Nothing
getAndCreateTextures is almost certainly doing what you need. The function of that name I found on the web has type IO [Maybe TextureObject], those are the TextureObject values you need. So you could do,
[gtex, ptex] <- getAndCreateTextures ["goldblock","pumpkintop"]
textureBinding Texture2D $= gtex
for example.
You pass the texture object. getAndCreateTextures seemingly gives you a list of texture objects. You pass one of those to the binding, like
textureBinding $ Texture2D $= Just tex[0]