diff --git a/GravityField/.gitignore b/GravityField/.gitignore index e121fb9..dad9484 100644 --- a/GravityField/.gitignore +++ b/GravityField/.gitignore @@ -1,9 +1,15 @@ essai +animation WS/*.pgm +WS/*.png *.gif +*.log +*.mp4 + +pov.stderr foo.pgm bar.pgm diff --git a/GravityField/Makefile b/GravityField/Makefile index 4dd8a92..c2d1490 100644 --- a/GravityField/Makefile +++ b/GravityField/Makefile @@ -7,10 +7,16 @@ MODOBJ = '../Modules/spitpgm.o' all: essai +# ----------- modules + realfield.o: realfield.f90 Makefile gfortran $(GFOPT) -c $< +# ----------- progs + essai: essai.f90 Makefile realfield.o gfortran $(GFOPT) $< realfield.o $(MODOBJ) -o $@ +animation: animation.f90 Makefile realfield.o + gfortran $(GFOPT) $< realfield.o $(MODOBJ) -o $@ diff --git a/GravityField/animation.f90 b/GravityField/animation.f90 new file mode 100644 index 0000000..a2b502f --- /dev/null +++ b/GravityField/animation.f90 @@ -0,0 +1,27 @@ +!----------------------------------------------------------------------- +!- +! Project "gravity field" - Firts renderer +!- +!----------------------------------------------------------------------- +program animation + + use realfield + use spitpgm + implicit none + + ! some configuration constants + integer, parameter :: S_WIDTH = 800 + integer, parameter :: S_HEIGHT = 600 + integer, parameter :: NB_BODY = 20 + + type(massbody) :: planets(NB_BODY) + integer :: foo + character(len=100) :: filename + + call init_random() + call create_some_planets(planets, 13.37, 2048, 2048) + + + STOP ': YOLO TIME' + +end program diff --git a/GravityField/encode.sh b/GravityField/encode.sh new file mode 100755 index 0000000..d2d5ad2 --- /dev/null +++ b/GravityField/encode.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +if [ $# -ne 2 ] ; then + echo + echo "need two arguments:" + echo " 1) source dir" + echo " 2) mp4 filename" + exit 1 +fi + +SDIR="$1" +FNAME="$2" +echo "Encoding from " $SDIR " to " $FNAME + +TITLE='---{ experimental gravity field }---' + +ffmpeg -nostdin \ + -loglevel warning \ + -y -r 30 -f image2 -i $SDIR/%05d.pgm \ + -metadata artist='---{ tTh }---' \ + -metadata title="${TITLE}" \ + -c:v libx264 -pix_fmt yuv420p \ + $FNAME + + diff --git a/GravityField/essai.f90 b/GravityField/essai.f90 index a8cbd08..58c073b 100644 --- a/GravityField/essai.f90 +++ b/GravityField/essai.f90 @@ -9,21 +9,30 @@ program essai implicit none - type(massbody) :: planets(60) + ! some configuration constants + integer, parameter :: S_WIDTH = 800 + integer, parameter :: S_HEIGHT = 600 + integer, parameter :: NB_BODY = 51 + + type(massbody) :: planets(NB_BODY) integer :: foo character(len=100) :: filename call init_random() + call create_some_planets(planets, 45e5, S_WIDTH, S_HEIGHT) - call create_some_planets(planets, 45e5) - - do foo=0, 72 - write (filename, "(a, i5.5, a)") 'WS/A', foo, '.pgm' - call build_and_write_a_field(640, 480, planets, filename) - print *, trim(filename) + do foo=0, 1999 + write (filename, "(a, i5.5, a)") 'WS/', foo, '.pgm' + call build_and_write_a_field(S_WIDTH, S_HEIGHT, planets, filename) + ! print *, trim(filename) ! OMG! two magic numbers, wtf? - planets(1)%posx = planets(1)%posx + 8.08 - planets(1)%posy = planets(1)%posy + 6.42 + planets(1)%posx = planets(1)%posx + 3 + (4.5*rand()) + planets(1)%posy = planets(1)%posy + 3 + (2.1*rand()) + if (planets(1)%posx .GT. S_WIDTH) planets(1)%posx = 0.0 + if (planets(1)%posy .GT. S_HEIGHT) planets(1)%posy = 0.0 + + call boulegue_les_astres(planets, 2.21) + enddo STOP 'BECAUSE YOLO' @@ -31,98 +40,21 @@ program essai contains !----------------------------------------------------------------------- !- -! Yes, I know, this is a disturbing kluge, but I like it :} -! May be, it's time to read the doc of modern Fortran +! Et si on bougeait un peu tous ces corps planétaires ? !- -subroutine init_random() +subroutine boulegue_les_astres(astres, factor) + type(massbody), intent(inout) :: astres(:) + real, intent(in) :: factor - integer, dimension(3) :: tarray - integer :: t3 - real :: dummy - call itime(tarray) - t3 = 8971*tarray(1) + 443*tarray(2) + tarray(3) - write(0, '(A,3I3,A,I6)') "sranding: ", tarray, " --> ", t3 - call srand(t3) - ! after initializing the random generator engine, - ! you MUST use it for initializing the initializer - dummy = rand() - write(0, *) 'dummy was ', dummy - -end subroutine -!----------------------------------------------------------------------- -!- -! make a few solid body to play with... -!- -subroutine create_some_planets(planets, coef) - type(massbody), intent(inout) :: planets(:) - real, intent(in) :: coef integer :: foo - ! real :: quux, quuy - character(100) :: fmt - fmt = "(I4, ' : ', 2(F9.2, ' '), e11.3, I7)" - - do foo=1, ubound(planets, 1) - if (foo .EQ. 1) then - planets(1)%posx = 20 - planets(1)%posy = 20 - planets(1)%mass = 9e8 - planets(1)%serial = 1337 - else - planets(foo)%posx = rand() * 639.999 - planets(foo)%posy = rand() * 479.999 - planets(foo)%mass = 7e6 + coef*foo - planets(foo)%serial = foo - endif - write (*, fmt) foo, planets(foo) + do foo = 2, ubound(astres, 1) + astres(foo)%posx = astres(foo)%posx + factor*(rand() - 0.5) + astres(foo)%posy = astres(foo)%posy + factor*(rand() - 0.5) enddo - ! STOP 'ABEND' end subroutine -!----------------------------------------------------------------------- -!- -! compute a field with only one body; and write pic file -!- -subroutine build_and_write_a_field(szx, szy, moons, fname) - integer, intent(in) :: szx, szy - type(massbody), intent(in) :: moons(:) - character(len=*), intent(in) :: fname - - real :: maxi, mini - integer :: errcode, foo - real, dimension(:,:), allocatable :: field, tmpf - integer, dimension(:,:), allocatable :: greymap - - allocate(field(szx, szy), stat=errcode) - allocate(tmpf(szx, szy), stat=errcode) - - field = 0.0 - do foo=1, ubound(moons, 1) - call compute_a_field(tmpf, moons(foo)) - tmpf = tmpf * 0.019 - field = field + tmpf - enddo - - maxi = maxval(field) - mini = minval(field) - ! print *, "field: ", mini, maxi, maxi-mini - - allocate(greymap(szx, szy), stat=errcode) - greymap = 0 - ! convert from real value to 16 bits int values - where (field < 65530.0) - greymap = int(field) - end where - - call spit_as_pgm_16(greymap, trim(fname)) - - ! make valgrind happy - deallocate(field) - deallocate(greymap) - -end subroutine - !----------------------------------------------------------------------- !----------------------------------------------------------------------- diff --git a/GravityField/raytrace.sh b/GravityField/raytrace.sh new file mode 100755 index 0000000..88bfb92 --- /dev/null +++ b/GravityField/raytrace.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +set -e + +POVOPT=" -q9 +a -W800 -H600 +WT2 -d -v " +SOURCE="vision.pov" +TMPF="/dev/shm/gravfield.png" + +# --------------------------------------- + +une_passe () +{ +clock=$1 + +povray -i${SOURCE} -K${clock} $POVOPT -O${TMPF} 2> pov.stderr + +timestamp=$(date | tr '01' 'Ol') +outfile=$(printf "WS/%05d.png" $clock) + +convert ${TMPF} \ + -pointsize 14 \ + -font Courier-Bold \ + -fill Orange \ + -annotate +10+16 "$timestamp" \ + ${outfile} +} + +# --------------------------------------- + +for foo in $(seq 0 1999) +do + echo '............' $foo + une_passe $foo +done + +ffmpeg -nostdin \ + -loglevel warning \ + -y -r 30 -f image2 -i WS/%05d.png \ + -metadata artist='---{ tTh }---' \ + -metadata title="Experiment on Gravity Field" \ + -c:v libx264 -pix_fmt yuv420p \ + bar.mp4 + diff --git a/GravityField/realfield.f90 b/GravityField/realfield.f90 index b434592..ab62aac 100644 --- a/GravityField/realfield.f90 +++ b/GravityField/realfield.f90 @@ -1,15 +1,20 @@ -! -! project "gravity field" -! +!----------------------------------------------------------------------- +!- +! some functions for the project "gravity field" +!- !----------------------------------------------------------------------- module realfield + use spitpgm ! XXX + implicit none !----------------------------------------------------------------------- ! definition of structures -! +!- type massbody real :: posx, posy + real :: heading = 33.21 + real :: speed = 1.007 real :: mass = 1.0 integer :: serial = 666 end type @@ -17,6 +22,57 @@ end type !----------------------------------------------------------------------- contains !----------------------------------------------------------------------- +subroutine barycentre_bodies(astres) + type(massbody), intent(in) :: astres(:) + + real :: cx, cy + integer :: foo + + !- + ! May be we have to use DOUBLE RPECSION here ? + !- + cx = 0.0 + cy = 0.0 + do foo=1, ubound(astres, 1) + cx = cx + astres(foo)%posx + cy = cy + astres(foo)%posy + enddo + cx = cx / real(ubound(astres, 1)) + cy = cy / real(ubound(astres, 1)) + print *, cx, cy + +end subroutine +!----------------------------------------------------------------------- +!- +! make a few solid body to play with... +!- +subroutine create_some_planets(planets, coef, sx, sy) + type(massbody), intent(inout) :: planets(:) + real, intent(in) :: coef + integer, intent(in) :: sx, sy + + integer :: foo + character(100) :: fmt + + fmt = "(I4, ' | ', 2(F10.2, ' '), ' | ', 2F9.3, ' ', e12.3, I7)" + + do foo=1, ubound(planets, 1) + if (foo .EQ. 1) then + planets(1)%posx = 10 + planets(1)%posy = 10 + planets(1)%mass = 7e8 + planets(1)%serial = 1337 + else + planets(foo)%posx = rand() * real(sx-1) + planets(foo)%posy = rand() * real(sy-1) + planets(foo)%mass = 7e6 + coef*foo + planets(foo)%serial = foo + endif + write (*, fmt) foo, planets(foo) + enddo + +end subroutine +!----------------------------------------------------------------------- function compute_gravity(fx, fy, body) real, intent(in) :: fx, fy @@ -62,6 +118,71 @@ subroutine compute_a_field(field, moon) enddo enddo +end subroutine +!----------------------------------------------------------------------- +!- +! compute a field with only one body; and write a pic file +!- +subroutine build_and_write_a_field(szx, szy, moons, fname) + integer, intent(in) :: szx, szy + type(massbody), intent(in) :: moons(:) + character(len=*), intent(in) :: fname + + real :: maxi, mini + integer :: errcode, foo + real, dimension(:,:), allocatable :: field, tmpf + integer, dimension(:,:), allocatable :: greymap + + allocate(field(szx, szy), stat=errcode) + allocate(tmpf(szx, szy), stat=errcode) + + field = 0.0 + do foo=1, ubound(moons, 1) + call compute_a_field(tmpf, moons(foo)) + tmpf = tmpf * 0.019 + field = field + tmpf + enddo + + maxi = maxval(field) + mini = minval(field) + ! print *, "field: ", mini, maxi, maxi-mini + + allocate(greymap(szx, szy), stat=errcode) + greymap = 65533 + ! convert from real value to 16 bits int values + where (field < 65530.0) + greymap = int(field) + end where + + call spit_as_pgm_16(greymap, trim(fname)) + + ! make valgrind happy + deallocate(field) + deallocate(greymap) + +end subroutine + +!----------------------------------------------------------------------- +!- +! Yes, I know, this is a disturbing kluge, but I like it :} +! May be, it's time to read the doc of modern Fortran +!- +subroutine init_random() + + integer, dimension(3) :: tarray + integer :: t3 + real :: dummy + call itime(tarray) + t3 = 8971*tarray(1) + 443*tarray(2) + tarray(3) + write(0, '(A,3I3,A,I6)') "sranding: ", tarray, " --> ", t3 + call srand(t3) + ! after initializing the random generator engine, + ! you MUST use it for initializing the initializer + do t3=1, 4 + dummy = rand() + write(0, *) 'dummy ', t3, dummy + enddo + end subroutine !----------------------------------------------------------------------- !----------------------------------------------------------------------- diff --git a/GravityField/runme.sh b/GravityField/runme.sh index f1411c2..d20b182 100755 --- a/GravityField/runme.sh +++ b/GravityField/runme.sh @@ -4,7 +4,7 @@ set -e # stop on error make essai -time ./essai +time ./essai | tee essai.log -convert -delay 20 WS/A*.pgm foo.gif +./encode.sh WS/ foo.mp4 diff --git a/GravityField/vision.pov b/GravityField/vision.pov new file mode 100644 index 0000000..8f12092 --- /dev/null +++ b/GravityField/vision.pov @@ -0,0 +1,56 @@ +/* + * Visualisation en 3d d'une tentative de champ gravitationnel + * + * tTh novembre 2022 + */ + +#version 3.7; +global_settings { + ambient_light rgb <0.07, 0.05, 0.05> + assumed_gamma 1.0 + max_trace_level 6 + } + + +#include "colors.inc" + +// ---------------------------------------------------------------------- + +#declare HFDIR = "WS/"; +#declare HFCK = mod(clock, 2000); + +#declare HFNAME = concat(HFDIR, str(HFCK , -5, 0), ".pgm"); + +#debug concat("- - - - - - - ", HFNAME, "\n") + +#declare GravityField = object +{ +height_field { + pgm HFNAME + smooth // on + translate <-0.5, 0, -0.5> + } +texture { + pigment { color Gray80 } + finish { phong 2.0 } + } +} + +object { GravityField scale <4, 1, 4> } + +// ---------------------------------------------------------------------- + +light_source { < -2, 9.3, -7> color Gray90 } +light_source { < -5, 9.3, -7> color Orange*0.75 } +light_source { < -15, 2.3, 17> color Blue*0.50 } + +// ---------------------------------------------------------------------- + +camera { + location <-8, 4, 3> + look_at <0, 0, 0> + right x*image_width/image_height + angle 35 + } + +// ----------------------------------------------------------------------