3D Cube Orthographic Projection

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
IcarusLives
Posts: 175
Joined: 17 Jan 2016 23:55

3D Cube Orthographic Projection

#1 Post by IcarusLives » 21 Jan 2024 15:26

Hello everyone,

I'm more than certain you guys at dostips could find ways to improve this, but I'm still happy to share :mrgreen:

References:
https://en.wikipedia.org/wiki/Orthographic_projection
https://en.wikipedia.org/wiki/Rotation_matrix


Update: Allows use of TAB key to quit, uses %esc% captured via prompt parse, instead of key, used deltaTime to demonstrate (maybe this not so good on all pc's, please let me know)

Code: Select all

@echo off & setlocal enableDelayedExpansion

if "%~1" neq "" goto :%~1

call :macro

set "points=-1" & for %%i in ( "-1 -1 -1" " 1 -1 -1" " 1  1 -1" "-1  1 -1" "-1 -1  1" " 1 -1  1" " 1  1  1" "-1  1  1") do (
	set /a "points+=1"
	for /f "tokens=1-3" %%x in ("%%~i") do (
		set /a "x[!points!]=%%~x, y[!points!]=%%~y, z[!points!]=%%~z"
	)
)

set /a "boxSize=15", "rotationSpeed=1", "wid=hei=90"
mode %wid%,%hei%

title {TAB} to QUIT

"%~F0" Controller >"%temp%\%~n0_signal.txt" | "%~F0" Engine <"%temp%\%~n0_signal.txt"
exit

:Engine
for /l %%# in () do (

	for /f "tokens=1-4 delims=:.," %%a in ("!time: =0!") do ( set /a "t1=((((1%%a-1000)*60+(1%%b-1000))*60+(1%%c-1000))*100)+(1%%d-1000)"   )
	if defined t2 ( set /a "deltaTime=(t1 - t2)"  )
	set /a "t2=t1"
	
	set "NewKey=" & set /p "NewKey="
	if /i "!newKey!" equ "quit" ( exit )
	
	set /a "angle+=rotationSpeed * deltaTime"
	
	for /l %%i in (0,1,7) do ( set /a ^
		       "px[%%i]=0", "py[%%i]=0",^
		       "x=x[%%i] * boxSize, y=y[%%i] * boxSize, z=z[%%i] * boxSize",^
		       "%rotY%", "x=ryx, y=ryy, z=ryz",^
		       "%rotX%", "x=rxx, y=rxy, z=rxz",^
		       "%rotZ%", "%projection:?=Z%",^
		       "px+=wid/2", "py+=hei/2",^
		       "px[%%i]+=px", "py[%%i]+=py"
	)

	for /l %%i in (0,1,3) do (
		set /a "i1=%%i", "i2=(%%i + 1) %% 4", "j=i1 + 1"
		for /f "tokens=1,2" %%1 in ("!i1! !i2!") do %line% !px[%%1]! !py[%%1]! !px[%%2]! !py[%%2]! !j!
		set "box=!box!!$line!"
		
		set /a "i1=%%i+4", "i2=((%%i + 1) %% 4) + 4", "j+=5"
		for /f "tokens=1,2" %%1 in ("!i1! !i2!") do %line% !px[%%1]! !py[%%1]! !px[%%2]! !py[%%2]! !j!
		set "box=!box!!$line!"
		
		set /a "i1=%%i", "i2=%%i + 4", "j+=5"
		for /f "tokens=1,2" %%1 in ("!i1! !i2!") do %line% !px[%%1]! !py[%%1]! !px[%%2]! !py[%%2]! !j!
		set "box=!box!!$line!"
	)

	echo %esc%[2J!box!
	set "box="
)

:macro

set "sin=(a=((x*31416/180)%%62832)+(((x*31416/180)%%62832)>>31&62832), b=(a-15708^a-47124)>>31,a=(-a&b)+(a&~b)+(31416&b)+(-62832&(47123-a>>31)),a-a*a/1875*a/320000+a*a/1875*a/15625*a/16000*a/2560000-a*a/1875*a/15360*a/15625*a/15625*a/16000*a/44800000) / 10000"
set "cos=(a=((15708-x*31416/180)%%62832)+(((15708-x*31416/180)%%62832)>>31&62832), b=(a-15708^a-47124)>>31,a=(-a&b)+(a&~b)+(31416&b)+(-62832&(47123-a>>31)),a-a*a/1875*a/320000+a*a/1875*a/15625*a/16000*a/2560000-a*a/1875*a/15360*a/15625*a/15625*a/16000*a/44800000) / 10000"
set "rotZ=  rZx=x*^!cos:x=angle^! + y*-^!sin:x=angle^! + z*0,     rZy=x*^!sin:x=angle^! + y*^!cos:x=angle^! + z*0,     rZz=x*0 + y*0 + z*1"
set "rotX=  rXx=x*1 + y*0 + z*0,     rXy=x*0 + y*^!cos:x=angle^! + z*-^!sin:x=angle^!,     rXz=x*0 + y*^!sin:x=angle^! + z*^!cos:x=angle^!"
set "rotY=  rYx=x*^!cos:x=angle^! + y*0 + z*^!sin:x=angle^!,     rYy=x*0 + y*1 + z*0,     rYz=x*-^!sin:x=angle^! + y*0 + z*^!cos:x=angle^!"
set "projection=  px=r?x*1 + r?y*0 + r?z*0,     py=r?x*0 + r?y*1 + r?z*0"

(set \n=^^^
%= This creates an escaped Line Feed - DO NOT ALTER =%
)

for /f "delims=" %%T in ('forfiles /p "%~dp0." /m "%~nx0" /c "cmd /c echo(0x09"') do set "TAB=%%T"
set "QUITKEY=!TAB!"

for /f %%a in ('echo prompt $E^| cmd') do set "esc=%%a"
<nul set /p "=%esc%[?25l"

set line=for %%# in (1 2) do if %%#==2 ( for /f "tokens=1-5" %%1 in ("^!args^!") do (%\n%
	if "%%~5" equ "" ( set "hue=15" ) else ( set "hue=%%~5")%\n%
	set "$line=%esc%[38;5;^!hue^!m"%\n%
	set /a "xa=%%~1", "ya=%%~2", "xb=%%~3", "yb=%%~4", "dx=%%~3 - %%~1", "dy=%%~4 - %%~2"%\n%
	if ^^!dy^^! lss 0 ( set /a "dy=-dy", "stepy=-1" ) else ( set "stepy=1" )%\n%
	if ^^!dx^^! lss 0 ( set /a "dx=-dx", "stepx=-1" ) else ( set "stepx=1" )%\n%
	set /a "dx<<=1", "dy<<=1"%\n%
	if ^^!dx^^! gtr ^^!dy^^! (%\n%
		set /a "fraction=dy - (dx >> 1)"%\n%
		for /l %%x in (^^!xa^^!,^^!stepx^^!,^^!xb^^!) do (%\n%
			if ^^!fraction^^! geq 0 set /a "ya+=stepy", "fraction-=dx"%\n%
			set /a "fraction+=dy"%\n%
			set "$line=^!$line^!%esc%[^!ya^!;%%xHÛ"%\n%
		)%\n%
	) else (%\n%
		set /a "fraction=dx - (dy >> 1)"%\n%
		for /l %%y in (^^!ya^^!,^^!stepy^^!,^^!yb^^!) do (%\n%
			if ^^!fraction^^! geq 0 set /a "xa+=stepx", "fraction-=dy"%\n%
			set /a "fraction+=dx"%\n%
			set "$line=^!$line^!%esc%[%%y;^!xa^!HÛ"%\n%
		)%\n%
	)%\n%
	set "$line=^!$line^!%esc%[0m"%\n%
)) else set args=
goto :eof

:Controller
Setlocal DISABLEdelayedExpansion
	REM Environment handling allows use of ! key
	For /l %%C in () do (
		for /f "delims=" %%A in ('C:\Windows\System32\xcopy.exe /w "%~f0" "%~f0" 2^>nul') do If not Defined Key (
	      	set "key=%%A"
			Setlocal ENABLEdelayedExpansion
	      	set key=^!KEY:~-1!
			If "!key!" == "!QUITKEY!" (
				<nul Set /P "=quit"
				EXIT
			)
			Endlocal
		)
	)
exit
Attachments
DYX5hnQefN.gif
DYX5hnQefN.gif (1.06 MiB) Viewed 24043 times
Last edited by IcarusLives on 22 Jan 2024 14:15, edited 3 times in total.

jeb
Expert
Posts: 1055
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

Re: 3D Cube Orthographic Projection

#2 Post by jeb » 22 Jan 2024 03:29

Hi IcarusLives,

nice picture, but currently the code on my WIN10 only produces:

Code: Select all

Fehlender Operand
Fehlender Operand
Fehlender Operand
[2J[38;5;1m[0;1H´┐¢[0m[38;5;6m[0;1H´┐¢[0m[38;5;11m[0;1H´┐¢[0m[38;5;2m[0;1H´┐¢[0m[38;5;7m[0
;1H´┐¢[0m[38;5;12m[0;1H´┐¢[0m[38;5;3m[0;1H´┐¢[0m[38;5;8m[0;1H´┐¢[0m[38;5;13m[0;1H´┐¢[0m[38
;5;4m[0;1H´┐¢[0m[38;5;9m[0;1H´┐¢[0m[38;5;14m[0;1H´┐¢[0m
Fehlender Operand
Fehlender Operand
Fehlender Operand
Fehlender Operand
Fehlender Operand
Fehlender Operand
Fehlender Operand
Fehlender Operand
[2J[38;5;1m[0;1H´┐¢[0m[38;5;6m[0;1H´┐¢[0m[38;5;11m[0;1H´┐¢[0m[38;5;2m[0;1H´┐¢[0m[38;5;7m[0
;1H´┐¢[0m[38;5;12m[0;1H´┐¢[0m[38;5;3m[0;1H´┐¢[0m[38;5;8m[0;1H´┐¢[0m[38;5;13m[0;1H´┐¢[0m[38
;5;4m[0;1H´┐¢[0m[38;5;9m[0;1H´┐¢[0m[38;5;14m[0;1H´┐¢[0m
Fehlender Operand
Fehlender Operand
Fehlender Operand
Fehlender Operand
Fehlender Operand

jfl
Posts: 226
Joined: 26 Oct 2012 06:40
Location: Saint Hilaire du Touvet, France
Contact:

Re: 3D Cube Orthographic Projection

#3 Post by jfl » 22 Jan 2024 04:44

Nice work!

The problem with your post above is that the ESC characters in your source code did not make it through to the web server.
This is a common problem with ASCII control characters. In the case of the ESC character, there's an easy workaround:
First change:

Code: Select all

set "esc="
<nul set /p "=[?25l"
to:

Code: Select all

for /f %%a in ('"echo prompt $E|cmd"') do set "esc=%%a"
<nul set /p "=%esc%[?25l"
Then prepend a %esc% before each of the other four [ in the following block beginning with: set line=

One request though:
To stop the test, I had to press Control-C. But this left the terminal in an unusable state, and I eventually had to kill it.
It would be nice to add a way to cleanly stop your script (maybe by pressing the ESC key?), and restore the terminal state.
Last edited by jfl on 22 Jan 2024 06:55, edited 1 time in total.

IcarusLives
Posts: 175
Joined: 17 Jan 2016 23:55

Re: 3D Cube Orthographic Projection

#4 Post by IcarusLives » 22 Jan 2024 06:26

Thank you for the suggestions! I will make an update accordingly, and republish soon. Thank you for your time and appreciation!

OP EDITED: Thanks for suggestions :)

IcarusLives
Posts: 175
Joined: 17 Jan 2016 23:55

Re: 3D Cube Orthographic Projection

#5 Post by IcarusLives » 06 Aug 2024 19:48

Update:

created %@box% for read/usability
angleX, angleY, and angleZ are now independent from each other
Uses DDALine instead of BresenhamLine now

This version you can change each angle by using keys QA, WS, ED,and size based on RF.

Press T to quit

Code: Select all

@echo off & setlocal enableDelayedExpansion

if "%~1" neq "" goto :%~1
del /f /q signal.txt

set /a "wid=hei=90"
mode %wid%,%hei%

call :macro

set /a "box.x=wid/2,box.y=hei/2,box.s=15,angle=0"

("%0" Controller >"signal.txt" | "%0" main <"signal.txt") & exit

:main
title T - QUIT
for /l %%# in () do (
	
	if defined key set "lastKey=!key!"
	set "key=" & set /p "key="
	
	       if /i "!key!" == "q" ( set /a "aR+=2"
	) else if /i "!key!" == "a" ( set /a "aR-=2"
	) else if /i "!key!" == "w" ( set /a "bR+=2"
	) else if /i "!key!" == "s" ( set /a "bR-=2"
	) else if /i "!key!" == "e" ( set /a "cR+=2"
	) else if /i "!key!" == "d" ( set /a "cR-=2"
	) else if /i "!key!" == "r" ( set /a "box.s+=1"
	) else if /i "!key!" == "f" ( if !box.s! gtr 3 set /a "box.s-=1"
	) else if /i "!key!" == "t" ( echo=.>"abort.txt" & exit )
	
	set /a "anglex=(anglex + aR) %% 360",^
	       "angley=(angley + bR) %% 360",^
	       "anglez=(anglez + cR) %% 360"
	
	%@box% box.x box.y box.s angleX angleY angleZ
	
	rem echo !$box!
	echo %\e%[2J!$box!%\e%[3;3H[Q,A] Angle X:!anglex!;	aR:!aR!%\e%[4;3H[W,S] Angle Y:!angley!;	bR:!bR!%\e%[5;3H[E,D] Angle Z:!anglez!;	cR:!cR!%\e%[6;3H[R,F] Size: !box.s!
)
exit

:Controller
For /l %%C in () do (
	if exist "abort.txt" (
		del /f /q "abort.txt"
		exit
	)
	for /f "delims=" %%A in ('choice /c:qawsedrft /n') do echo=%%~A
)
exit


:macro
(set \n=^^^
%= This creates an escaped Line Feed - DO NOT ALTER =%
)

(for /f %%a in ('echo prompt $E^| cmd') do set "\e=%%a") & echo=!\e![?25l

set "sin=(a=((x*31416/180)%%62832)+(((x*31416/180)%%62832)>>31&62832), b=(a-15708^a-47124)>>31,a=(-a&b)+(a&~b)+(31416&b)+(-62832&(47123-a>>31)),a-a*a/1875*a/320000+a*a/1875*a/15625*a/16000*a/2560000-a*a/1875*a/15360*a/15625*a/15625*a/16000*a/44800000) "
set "cos=(a=((15708-x*31416/180)%%62832)+(((15708-x*31416/180)%%62832)>>31&62832), b=(a-15708^a-47124)>>31,a=(-a&b)+(a&~b)+(31416&b)+(-62832&(47123-a>>31)),a-a*a/1875*a/320000+a*a/1875*a/15625*a/16000*a/2560000-a*a/1875*a/15360*a/15625*a/15625*a/16000*a/44800000) "


rem %@line% x0 y0 x1 y1 color <rtn> $line
set @line=for %%# in (1 2) do if %%#==2 ( for /f "tokens=1-5" %%1 in ("^!args^!") do (%\n%
	if "%%~5" neq "" ( set "$line=%\e%[48;5;%%~5m" ) else set "$line=%\e%[48;5;15m"%\n%
	set /a "$x0=%%~1, $y0=%%~2, $x1=%%~3, $y1=%%~4, dx=(((%%~3-%%~1)>>31|1)*(%%~3-%%~1)), dy=-($dy=(((%%~4-%%~2)>>31|1)*(%%~4-%%~2))), err=dx+dy, dist=dx, sx=sy=-1"%\n%
	if ^^!dx^^! lss ^^!$dy^^! set dist=^^!$dy^^!%\n%
	if ^^!$x0^^! lss ^^!$x1^^! set sx=1%\n%
	if ^^!$y0^^! lss ^^!$y1^^! set sy=1%\n%
	for /l %%i in (0,1,^^!dist^^!) do (%\n%
		set "$line=^!$line^!%\e%[^!$y0^!;^!$x0^!H "%\n%
		set /a "e2=2 * err"%\n%
		if ^^!e2^^! geq ^^!dy^^! set /a "err+=dy, $x0+=sx"%\n%
		if ^^!e2^^! leq ^^!dx^^! set /a "err+=dx, $y0+=sy"%\n%
	)%\n%
	set "$line=^!$line^!%\e%[0m"%\n%
)) else set args=


:_box
rem predefine points of %@box%
set "points=0" & for %%i in ("-1 -1 -1" " 1 -1 -1" " 1  1 -1" "-1  1 -1" "-1 -1  1" " 1 -1  1" " 1  1  1" "-1  1  1") do (
	for /f "tokens=1-3" %%x in ("%%~i") do set /a "x!points!=%%~x, y!points!=%%~y, z!points!=%%~z"
	set /a "points+=1"
)
set "points="
rem in=>x y z ; out=>$a $b
set "boxFormula(x,y,z)=rx= x *  coa/10000 +  z *  sia/10000, rz= x * -sia/10000 +  z *  coa/10000, ry= y *  cob/10000 + rz * -sib/10000, $a=rx *  coc/10000 + ry * -sic/10000, $b=rx *  sic/10000 + ry *  coc/10000"
set @box=for %%# in (1 2) do if %%#==2 ( for /f "tokens=1-6" %%A in ("^!args^!") do (%\n%
	set "$box="%\n%
	set /a "coa=^!cos:x=%%~D^!, sia=^!sin:x=%%~D^!, cob=^!cos:x=%%~E^!, sib=^!sin:x=%%~E^!, coc=^!cos:x=%%~F^!, sic=^!sin:x=%%~F^!"%\n%
	for /l %%i in (0,1,7) do set /a "x=x%%i * %%~C, y=y%%i * %%~C, z=z%%i * %%~C", "%boxFormula(x,y,z)%", "px[%%i]=$a + %%~A, py[%%i]=$b + %%~B"%\n%
	for /l %%i in (0,1,3) do ( set /a "i1=%%i, i2=(%%i + 1) %% 4, j1=i1 + 1, i3=%%i+4, i4=((%%i + 1) %% 4) + 4, j2=j1 + 5, i5=%%i + 4, j3=j2 + 5"%\n%
		for /f "tokens=1-6" %%1 in ("^!i1^! ^!i2^! ^!i3^! ^!i4^! ^!i5^!") do (%\n%
			^!@line^! ^^!px[%%1]^^! ^^!py[%%1]^^! ^^!px[%%2]^^! ^^!py[%%2]^^! ^^!j1^^!%\n%
			set "$box=^!$box^!^!$line^!"%\n%
			^!@line^! ^^!px[%%3]^^! ^^!py[%%3]^^! ^^!px[%%4]^^! ^^!py[%%4]^^! ^^!j2^^!%\n%
			set "$box=^!$box^!^!$line^!"%\n%
			^!@line^! ^^!px[%%1]^^! ^^!py[%%1]^^! ^^!px[%%5]^^! ^^!py[%%5]^^! ^^!j3^^!%\n%
			set "$box=^!$box^!^!$line^!"%\n%
		)%\n%
	)%\n%
)) else set args=
set "boxFormula(x,y,z)="
goto :eof

Post Reply