Compare commits
2855 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6675ae64cf | |||
| a015fa53e6 | |||
| e2360155a6 | |||
| 869792f88d | |||
| c22ccaffc4 | |||
| 583fe1d524 | |||
| c4a0bf2b2d | |||
| d3206d6883 | |||
| a7c13a61c3 | |||
| 52b503c99c | |||
| 7d65b1e5e1 | |||
| 5e4f412fd0 | |||
| 8f949caeb9 | |||
| 2bd17a5c8b | |||
| c6a2eb6c9d | |||
| eb449879b8 | |||
| 49b45b8ac5 | |||
| 35bc2efb61 | |||
| 9989145fb1 | |||
| 554c474cf0 | |||
| eded969ca1 | |||
| a28f93ff3b | |||
| 13345822bc | |||
| 9e6eba96fd | |||
| b3777d5317 | |||
| c48435407e | |||
| 3f577bd16c | |||
| dc9e175ac0 | |||
| 66b7e82b75 | |||
| 23398f9651 | |||
| 5bb7f5c8d2 | |||
| d2cca45511 | |||
| f503f99704 | |||
| 170f0a5021 | |||
| e12654ac3d | |||
| 274b7ee845 | |||
| 558a5a4948 | |||
| 27ebcf3325 | |||
| bc766093a3 | |||
| 3b54bb1614 | |||
| 648d81b2f7 | |||
| f9d964b790 | |||
| 16baa1f7f1 | |||
| 49553e867a | |||
| 5723ac469b | |||
| 2c7da91b39 | |||
| bc8fe1cea1 | |||
| e8d7e55640 | |||
| 021474ab2a | |||
| ea7dd5ae58 | |||
| 9219155104 | |||
| 5e7c4d47aa | |||
| a67a342bdf | |||
| 13431345cf | |||
| 78801bfcb5 | |||
| 1c0f4a4e30 | |||
| 7f90e34e38 | |||
| 38ab6a8dc0 | |||
| 48562916c3 | |||
| 67ed6cc430 | |||
| 35fd6c9458 | |||
| 68ada9e169 | |||
| 2e939bb9be | |||
| 55b20ea70d | |||
| 4d80e42219 | |||
| 4474896713 | |||
| 3604fae918 | |||
| 35d49085ae | |||
| 943d1b7db8 | |||
| 3a41f8ed03 | |||
| d8ad00673b | |||
| 08843f5845 | |||
| 20304ccc30 | |||
| 522f18d847 | |||
| 467e9cb170 | |||
| 9b505817b7 | |||
| 0c119ebab9 | |||
| ea9931bd05 | |||
| 0c29fb6595 | |||
| c8311132da | |||
| 657a87697e | |||
| c60698c24b | |||
| 58becbeb59 | |||
| 319cb3e15c | |||
| b4df1618ed | |||
| e23f2b7b7b | |||
| 1a0054ea48 | |||
| fa5ddc068d | |||
| 6279f8b33d | |||
| 6f9ef9c20e | |||
| 84e4b8f04f | |||
| b59770e8ca | |||
| 01cde02ea2 | |||
| 541222752a | |||
| fa9a2796be | |||
| 072c980c7d | |||
| 9a572e1993 | |||
| 6cb0d0cbfc | |||
| 7b120f21be | |||
| fa6ada69a6 | |||
| 5ec247663e | |||
| d85256bfa9 | |||
| ccb956b7d3 | |||
| 1aa6d7f0f0 | |||
| a4805cc99d | |||
| 9849f41b03 | |||
| 3bcb728c84 | |||
| 9d61f82f68 | |||
| 3b735771d8 | |||
| d8af04a5e3 | |||
| 39587ee1b7 | |||
| a48377bcee | |||
| 82303217af | |||
| f3e771ac1f | |||
| b813799334 | |||
| bc372564cf | |||
| 7155e3a9db | |||
| 5abb625ef5 | |||
| ff0ca7ee95 | |||
| cdcb10d8bc | |||
| 2c594c9b18 | |||
| d08f8ed62d | |||
| 20fc4a81b8 | |||
| ef7e71e93a | |||
| f092fac22e | |||
| eefeb7c0cf | |||
| 76c61e92f7 | |||
| a86387eec6 | |||
| 641e6398fd | |||
| 04c73b0ceb | |||
| d3afc86040 | |||
| 96131f64b4 | |||
| fcfc4210e8 | |||
| b5ae5f3f4d | |||
| 9cea792545 | |||
| 7d85ad55fb | |||
| 6961f9bca0 | |||
| d63547c7dd | |||
| 3605ab617c | |||
| 005708f30d | |||
| 5a3bf6c3d6 | |||
| bb9c11492c | |||
| 3d9d0247e7 | |||
| 50645cf465 | |||
| 6a58dc67e9 | |||
| 65d02e479a | |||
| e3ebd725cd | |||
| 288e89e0da | |||
| 4d955fda7e | |||
| ea06a99874 | |||
| f292a1db89 | |||
| 467d8b41f8 | |||
| 9f834561c3 | |||
| 1ab4fca573 | |||
| cd341cc301 | |||
| dfad6b79e6 | |||
| 4f83504d7b | |||
| 149e3cb2a3 | |||
| 5e266fc0bf | |||
| e3d7af1833 | |||
| 9f4da3732e | |||
| 8f45e1703c | |||
| ec6b251ef4 | |||
| 557311aad7 | |||
| b8d833a450 | |||
| 852f21a7dc | |||
| f1069929df | |||
| ead32f6885 | |||
| 249003e594 | |||
| 28497f10dd | |||
| 37adb11be5 | |||
| 63d4051059 | |||
| 7f27b30ac9 | |||
| 2bc0a44764 | |||
| fd480f6437 | |||
| 0011fd5166 | |||
| 88ec4fe02f | |||
| c5a14f28f1 | |||
| 056e3aede2 | |||
| 6a39ea5b43 | |||
| 05b91bcbfb | |||
| 4402c686d8 | |||
| 43ee7b1dc1 | |||
| 115124c528 | |||
| 470b7eddb3 | |||
| 0c65353c17 | |||
| c32443fe35 | |||
| 03c4145fa8 | |||
| 2459ed7320 | |||
| 23d150e618 | |||
| d7082b39bb | |||
| ed25a1593e | |||
| ca7d56cefd | |||
| 1bba172393 | |||
| 7e43e8e4dd | |||
| b5a8c2a2a0 | |||
| ac353fc037 | |||
| a340308dc1 | |||
| feaab95087 | |||
| 14c2469a3f | |||
| 14ed75b0a7 | |||
| 4e38c73586 | |||
| 3c4cb06644 | |||
| b7937c5c79 | |||
| aa56df75bd | |||
| 0f78123d69 | |||
| e4a4578b40 | |||
| 1c35e7d6f6 | |||
| 24b8d96709 | |||
| 1a3f7989df | |||
| 2249b3be12 | |||
| 289c4c2f9d | |||
| c5e84fe49a | |||
| 3d9d94c18a | |||
| 19f1adabea | |||
| c225dbbba2 | |||
| f599033a1a | |||
| 877928a57a | |||
| 8461a62c3a | |||
| 2b328721d4 | |||
| 31d231ed36 | |||
| cd4feed7de | |||
| ff4887b46c | |||
| 4c780e7074 | |||
| 34dc6da5ad | |||
| 030cee7ddf | |||
| 5bd06278d3 | |||
| dfb461307a | |||
| e179d215a7 | |||
| b1e4eeb2b5 | |||
| ed43e47115 | |||
| 1adc04caf6 | |||
| 6e5c404f94 | |||
| 7ae0fba8f1 | |||
| 52640fd5fd | |||
| 9a6ab4e64f | |||
| d5d4ae3305 | |||
| d5b2a3b007 | |||
| b588456d6a | |||
| f28484179d | |||
| c1804da8a2 | |||
| 0304286c2c | |||
| 33bad83ea7 | |||
| 0e35ad6329 | |||
| 1cbcc8dc25 | |||
| bf92b0103a | |||
| 9ad3180f6c | |||
| 0e270eec05 | |||
| 6e72301bd7 | |||
| a59d0f113b | |||
| 827fd67191 | |||
| 9b67ee04e6 | |||
| 5127237b40 | |||
| 2af184034b | |||
| 96e9942a9b | |||
| 603121f753 | |||
| b0020a904b | |||
| be2238411d | |||
| 939e3d589b | |||
| 6475d4496d | |||
| ef938bdf1f | |||
| 285ef4dab6 | |||
| bc2cb06a0e | |||
| 8715df4ab0 | |||
| 4d02c43189 | |||
| e962b9f4f6 | |||
| 93065de210 | |||
| 3b05177a3a | |||
| 6181ee494b | |||
| 8faf3f740f | |||
| 8ef7b23c04 | |||
| 36ea1e0b0f | |||
| edb2b3008c | |||
| 9330924636 | |||
| 2b6305ba48 | |||
| 1f38879fef | |||
| 630df1812f | |||
| 8137358e8e | |||
| 18f51a4dbe | |||
| 5eb4ecbf1c | |||
| e454408772 | |||
| eb36fb9280 | |||
| 3b48abba6d | |||
| 2b39b1e7ea | |||
| 84161768fa | |||
| b1a1b12e42 | |||
| 8b35a0a36f | |||
| ca969f0884 | |||
| 88489e4af6 | |||
| 884219fd90 | |||
| 60c0b8de0d | |||
| 25538205c9 | |||
| b34f6bcd0b | |||
| f0dfd89d26 | |||
| 46efeb0a46 | |||
| 1d804eba61 | |||
| 391d7df0b5 | |||
| 9020146df5 | |||
| 77f2287acc | |||
| e1ca953c40 | |||
| b857ba58ca | |||
| 140361e2c8 | |||
| 3aae81b307 | |||
| b361baae42 | |||
| d52568908f | |||
| 6b99cbe9a5 | |||
| df9c611f09 | |||
| 5dd03b4ecd | |||
| a3cd531e9e | |||
| 86f84b9ed0 | |||
| fc961993d5 | |||
| 8d7bcf4995 | |||
| 2a1bb84cf7 | |||
| 9134289303 | |||
| d19f57b0d5 | |||
| f8a0869314 | |||
| 85e2613f0b | |||
| 55c3fce790 | |||
| 42c0340880 | |||
| b5faf71be4 | |||
| 657ac76bbf | |||
| 3700ab0555 | |||
| c16837d3b6 | |||
| 0cb0a451a4 | |||
| d7efbd5044 | |||
| 1770e40aec | |||
| af7454b767 | |||
| 3e50e00f89 | |||
| e35647b25b | |||
| 70c62508a5 | |||
| f4f78722a7 | |||
| 9b1b505731 | |||
| babeea0c45 | |||
| fac1cab1d9 | |||
| 3f4ba31188 | |||
| 187f9ff0f4 | |||
| ba7cfecd5d | |||
| 7b706ee873 | |||
| 8809d5580e | |||
| e9aec03ce0 | |||
| bf9a7511f3 | |||
| 517c555d6a | |||
| edcf84a2a1 | |||
| 0fa01812eb | |||
| f610294d27 | |||
| 2ebd47c331 | |||
| 9d0b3649a1 | |||
| 699dbbf53f | |||
| b2ce20783e | |||
| 099f58a100 | |||
| 3029f762bf | |||
| 2bce2f96d8 | |||
| 8d38938da1 | |||
| 21d2c19333 | |||
| 4419ef42bb | |||
| 8461fc2f3b | |||
| eb8d78ea21 | |||
| f944c79269 | |||
| aa54a3e5a1 | |||
| 1d6357a76a | |||
| c66a3232ac | |||
| 7adb74699b | |||
| b31fede98e | |||
| cef8e05eb0 | |||
| e28ead71b6 | |||
| ccc11c8ed8 | |||
| c5f04753f9 | |||
| 9f4d338a02 | |||
| 96ca762543 | |||
| a1f80f20a7 | |||
| 8d8c72856d | |||
| 7d1c0ec4db | |||
| 16a68d8528 | |||
| 9c1f4efb6e | |||
| 41c4388d5c | |||
| f503ee945f | |||
| 125ef0a679 | |||
| 075283d9a8 | |||
| dbe19fc5f9 | |||
| 7fa70d1885 | |||
| d39cc2d65f | |||
| 9bdb0086b4 | |||
| eb25a2d42b | |||
| 476ec04b13 | |||
| 62a76f1ed2 | |||
| e063962ce7 | |||
| c1b7ced4e7 | |||
| 250b558878 | |||
| 374b15ff9e | |||
| de0e8bd519 | |||
| dd628646f2 | |||
| 0383f93aac | |||
| 7ae0d3960f | |||
| c0e8c155bd | |||
| 714fde2418 | |||
| 8479640252 | |||
| 649f8c2f7c | |||
| eee9670f82 | |||
| 07db739906 | |||
| 090eca72bc | |||
| be6dc9d0af | |||
| 81b610df16 | |||
| ee0b425538 | |||
| f4c1bac7a8 | |||
| f6fd93b67e | |||
| bad1183955 | |||
| 8590d7dbb8 | |||
| 808cc9195d | |||
| e4b2deed51 | |||
| 3dbb864e5e | |||
| a3e7b856b1 | |||
| 4cdd8e754a | |||
| 0d68df1d93 | |||
| 26fd1960e6 | |||
| af075c1cb2 | |||
| 19d3864a5d | |||
| f01b2502c8 | |||
| 0161fab1a3 | |||
| 364d0e0f02 | |||
| 7278716c65 | |||
| e79d47fed2 | |||
| 6348c77788 | |||
| ea87d8247e | |||
| af54a74a24 | |||
| 8123415163 | |||
| 45f64652ef | |||
| 79807dd948 | |||
| 6d3e691dd9 | |||
| 834dce571e | |||
| 8aef3b30fa | |||
| 4c9e2acb02 | |||
| 1c7cc3229c | |||
| 881b24c6e4 | |||
| b0aa561719 | |||
| 4abc6ea0cb | |||
| 33c07934b6 | |||
| 249de46078 | |||
| d19280aeb9 | |||
| 9a56467e13 | |||
| 1492f71d6c | |||
| 88bc292a37 | |||
| ff12d3d2e5 | |||
| 39de31f7b2 | |||
| 750cf6a26e | |||
| 7b754b723c | |||
| 7cddc08e1f | |||
| ddfdbb6ff0 | |||
| 3f05c57f61 | |||
| ddd39027e7 | |||
| 5a9d750f7d | |||
| b46b5352c4 | |||
| d6fcc48ed0 | |||
| a66758406e | |||
| 6c8b0ea59c | |||
| 59a56fc820 | |||
| 0eed6c360c | |||
| 46f3c2210d | |||
| 962a0e16c5 | |||
| 8feab0ad66 | |||
| 4eee9e18d5 | |||
| ae93328c21 | |||
| 0dac3077bd | |||
| 5491a468ba | |||
| b704410dd2 | |||
| aaf0c13838 | |||
| c795d04614 | |||
| b7d5bd5ab8 | |||
| b84ada1ab6 | |||
| 2451de0e1b | |||
| 373a5b5bb7 | |||
| a4fe76d2a7 | |||
| 1cacfffd5f | |||
| e88e8b1ed3 | |||
| 0c615f78a1 | |||
| 42aeed5421 | |||
| 669912ea9b | |||
| 6f6a79407b | |||
| b93146ab87 | |||
| 9583c522dd | |||
| 90c0e2e8f4 | |||
| aff1bdc853 | |||
| c0b0918c45 | |||
| 68a1b06674 | |||
| 09636c1a88 | |||
| 52e5d11d0a | |||
| 110507449c | |||
| da0e9c5299 | |||
| 109e628903 | |||
| d973165737 | |||
| 8ddba7a836 | |||
| 56c237410b | |||
| 5959e7c2ef | |||
| 9f18e6f152 | |||
| 171d3e1c88 | |||
| 9f5d968476 | |||
| 93483241ed | |||
| 34724c8d99 | |||
| 00ee7cd462 | |||
| 11fcf7ab6e | |||
| 3a25e108f5 | |||
| 5299e41ac4 | |||
| 37dc675b7a | |||
| 8718c57d41 | |||
| 6732726f13 | |||
| 9e4e5ddd03 | |||
| 96db0f38f7 | |||
| 793b144e3b | |||
| 9427ce29d1 | |||
| 6d6181cdfa | |||
| b3c5980e61 | |||
| c8c98753b5 | |||
| de0c476042 | |||
| cff1ea84ee | |||
| aff5e66ab8 | |||
| 4010a5709c | |||
| 82bfe0dbdf | |||
| 7e8b1906b2 | |||
| cf9e5417d0 | |||
| 3d849fd87c | |||
| 244be39ffa | |||
| 9ee9c93ef8 | |||
| 980e325ba1 | |||
| e954736b5d | |||
| 6e666b5d62 | |||
| 0833cd4b61 | |||
| 221b68d0b8 | |||
| 3a0f1c4126 | |||
| a792a0e7ea | |||
| cad85c8a7a | |||
| 51bf04932b | |||
| 8cfc8b0157 | |||
| c40d25df29 | |||
| 5d4eab87f8 | |||
| 7dc9eefc83 | |||
| d3ee4b1eda | |||
| 82838e6770 | |||
| f35e6412bd | |||
| 90e8aba660 | |||
| eb053cac2b | |||
| 5a6f259f2c | |||
| b331a3b3fd | |||
| 0ec0b63ad2 | |||
| 659c2184b3 | |||
| 6bbd4defaf | |||
| ea4867d5b1 | |||
| 8d14b4798e | |||
| 911ee57de6 | |||
| 2536bae624 | |||
| 27ecb2c930 | |||
| 9ba5058e66 | |||
| 7faf9fb9a4 | |||
| 63196b5a8a | |||
| 8d37c9122f | |||
| 7caeff6af9 | |||
| ecf6698d4f | |||
| 48c10f9e5b | |||
| 89463b0d2d | |||
| d2e865146b | |||
| 1283747b59 | |||
| a2df815ba6 | |||
| cd7d6d470b | |||
| e8ef3c14d4 | |||
| 3a8ca47fce | |||
| 4566d8717a | |||
| c2a12d903f | |||
| 2171fd0b18 | |||
| a051887971 | |||
| 6e28e5bdf0 | |||
| cd0d91a611 | |||
| 176607db25 | |||
| ea943ce605 | |||
| b114526b12 | |||
| 58f813b6e8 | |||
| c389c2f6e4 | |||
| 144de5dd78 | |||
| 139ca8f6ef | |||
| 741602c9cc | |||
| 04ff538d11 | |||
| 825561d6f4 | |||
| d932043905 | |||
| 68d613ef0d | |||
| 6ffcddcb87 | |||
| e9ece451af | |||
| 5d8db7fa96 | |||
| 608de9970b | |||
| 97de56756f | |||
| 854f882090 | |||
| 1119c1e68f | |||
| c5bc58ee46 | |||
| 0cd99fc3b3 | |||
| dadec3bd25 | |||
| 6ac1bae539 | |||
| 068076a2c2 | |||
| 51fe856360 | |||
| c719b4f3c3 | |||
| f7f45dc4c8 | |||
| dfbafdc3fb | |||
| 2d62eab4b4 | |||
| 4478c09544 | |||
| 438cdafd60 | |||
| 53b6c1f39a | |||
| d8ee9b8bca | |||
| 17027286bd | |||
| babd441b7e | |||
| 41e4379924 | |||
| d191e5038c | |||
| 8571e3608c | |||
| 08367867b9 | |||
| 0c540ebea6 | |||
| 269e88b18d | |||
| c39b56891e | |||
| 3c79ed375c | |||
| 9a86def109 | |||
| faa6582adc | |||
| f075166a21 | |||
| 77bba5e9f9 | |||
| bbfd2fb66c | |||
| ec37f295c7 | |||
| af44f2c720 | |||
| 913a9dcdc3 | |||
| 62b264f770 | |||
| edc2938fb8 | |||
| 2498414e91 | |||
| 3c5929258b | |||
| 810a01b779 | |||
| a49015a317 | |||
| 92816e4689 | |||
| 56cd826400 | |||
| aee4f33c09 | |||
| 3177f74540 | |||
| e8b7c6df54 | |||
| a22364f545 | |||
| 8626e906cb | |||
| 980dec08cf | |||
| ad2957d534 | |||
| 6742f54243 | |||
| e2e68aea74 | |||
| 5437f43790 | |||
| fc14556d43 | |||
| 4bd4c43d1a | |||
| f27e85eeb0 | |||
| 16a70dd267 | |||
| a53caab12b | |||
| 2cead53fc9 | |||
| 77defa69c6 | |||
| 8c540c8b83 | |||
| 0a415fad36 | |||
| 95bb3d6bb1 | |||
| 3142172cff | |||
| 074a265166 | |||
| ce3943446c | |||
| 6c0c2b4365 | |||
| 2fc8a05aec | |||
| 3eab6c5af2 | |||
| d1bd519e7c | |||
| 0b62184c51 | |||
| 7ae4bc208a | |||
| c28fbe566d | |||
| 5ae8d9b220 | |||
| 4d3ac11467 | |||
| 5777523b35 | |||
| e0eb666f6c | |||
| 19ebe3feb8 | |||
| b9e9480e5c | |||
| 70b7131ae7 | |||
| 7ec2c004a2 | |||
| 7e884e1eb1 | |||
| 7689d48632 | |||
| 514c6c11ae | |||
| e18828bed7 | |||
| 0d52d9aa52 | |||
| bf9db2148c | |||
| 768f7c0e45 | |||
| d160459f4a | |||
| 69b16484ec | |||
| 5f023e1e25 | |||
| b7996a4ad4 | |||
| 447bb98480 | |||
| 68d43a49df | |||
| 3353297858 | |||
| f56e4fe1a4 | |||
| 5a6e6b2733 | |||
| 58b96efe06 | |||
| 0328cfe83e | |||
| 4270fece64 | |||
| 9cba0c0b02 | |||
| 64201d49f0 | |||
| c801fcd835 | |||
| aac9946aef | |||
| 292a50f8c0 | |||
| ebdddf0bc0 | |||
| a8ac725564 | |||
| 342684587a | |||
| 9a532f2cda | |||
| 909b7fb425 | |||
| 2027222074 | |||
| 93c3a64839 | |||
| 0913c5e167 | |||
| 9abad0063e | |||
| 85aa4057f8 | |||
| 9cd30339e1 | |||
| 4b851f9b98 | |||
| 64c093109d | |||
| 667dd177ce | |||
| b67c568545 | |||
| 2fb36a9144 | |||
| f06c0dc463 | |||
| ce1541e915 | |||
| 212f004cad | |||
| a8339496e5 | |||
| 9a183196a2 | |||
| 5a12aa9e1b | |||
| 5c0d62ac2e | |||
| 3d511efbb9 | |||
| 05a159d648 | |||
| 5a9aa812e2 | |||
| 35a9deb301 | |||
| c0ed445918 | |||
| f954ace66b | |||
| 6776f8a79f | |||
| ba345cb823 | |||
| 39abd88a54 | |||
| ecccdf0279 | |||
| 095e4a8799 | |||
| a66ae2f51b | |||
| 781c6449d3 | |||
| eca952b8c5 | |||
| 13d4ee03b3 | |||
| 22f9af6bf3 | |||
| d01c071d25 | |||
| 3f4bf9062c | |||
| 92e0d7bab2 | |||
| d9174a110b | |||
| f9c92b7c78 | |||
| b73dc849a5 | |||
| 283788d91c | |||
| 9b4b5c931e | |||
| bb87cd5fba | |||
| 5d21c2d300 | |||
| da08a4129e | |||
| bff99dcf73 | |||
| 1d7538a557 | |||
| e483be7726 | |||
| 3b8a34bf25 | |||
| 0f6dfb782e | |||
| c8aada9941 | |||
| 3d4fa72b51 | |||
| 936ffcaabc | |||
| 84721d045e | |||
| 0443c73aab | |||
| d72ec51ccf | |||
| 5778d74fbb | |||
| b67faf780e | |||
| 3afbd8f2e1 | |||
| fb771bf797 | |||
| 46f42ba9c8 | |||
| bee41d9491 | |||
| f37fb67e5a | |||
| 940fc985e7 | |||
| 384abca49e | |||
| c04eb822b7 | |||
| 0a51662c0b | |||
| 84af2eb8e1 | |||
| df5b9a1df0 | |||
| 0ac6e0614f | |||
| f3ef0fcf57 | |||
| 59f450bcfd | |||
| 53db1d2c9b | |||
| 45291ef571 | |||
| 8cc9b69017 | |||
| 304d17dd32 | |||
| dc8997b1ac | |||
| e1bfcb1816 | |||
| af981b37fe | |||
| 4a4c0914bc | |||
| bc41f8298b | |||
| 12098fe113 | |||
| 53053d0693 | |||
| 829629d05f | |||
| 49233429e4 | |||
| 47b6dd34af | |||
| 4bd71d676f | |||
| a8bdd44cd1 | |||
| 9a860c355a | |||
| c42a473521 | |||
| 43eb124964 | |||
| a078fa6779 | |||
| 86a8bbee9a | |||
| 947a846d2e | |||
| 4897ea8c35 | |||
| fa2edf8547 | |||
| dcefaf675c | |||
| 4343c6a24f | |||
| fc7798b7d7 | |||
| 82b2558d96 | |||
| 466ecca932 | |||
| 96adde2d52 | |||
| b2a71b505b | |||
| ecafc030ef | |||
| 6007dca4d1 | |||
| 08ecc5005f | |||
| 7b70f2835c | |||
| d8b046a361 | |||
| 9ee683e971 | |||
| 0b01c898f0 | |||
| 08e6ef95ab | |||
| dd89260db3 | |||
| 534a04206b | |||
| 25eaf50586 | |||
| e259a150fb | |||
| 6bc8d6a231 | |||
| 8122846078 | |||
| 8fbdc6a50d | |||
| 2be3ebd401 | |||
| f114bed0d2 | |||
| 31deb4d25d | |||
| 413b776194 | |||
| af18baba7b | |||
| 527695bf53 | |||
| bcd3470b20 | |||
| fd86b347e6 | |||
| 801d72c55a | |||
| 6ea28cb69d | |||
| 19196bede7 | |||
| eed87fc699 | |||
| 6c1a67684e | |||
| e5b6055e7d | |||
| 3ea78d07b1 | |||
| c8c06ff230 | |||
| bbc596ad6c | |||
| 0930828a81 | |||
| 8c71406615 | |||
| 1b01dba827 | |||
| 4aa52ddd60 | |||
| b80de21136 | |||
| ca927e4227 | |||
| f2c17a64fb | |||
| c793624195 | |||
| 42d54163c5 | |||
| 5f2f80f480 | |||
| 88be1fee15 | |||
| 0a6a44522a | |||
| 0ba54b4b7c | |||
| 56b35ef6fb | |||
| 03855be6f9 | |||
| 39b55e20c0 | |||
| 24ab8e0b52 | |||
| a961938716 | |||
| 5c2b9d6011 | |||
| 66def25eab | |||
| 16b7338a59 | |||
| 5b89f42738 | |||
| 882a0bcb7d | |||
| 629d397508 | |||
| 346384f8fc | |||
| fe4af49759 | |||
| 5370236743 | |||
| ee289e4a30 | |||
| 83ccbc7add | |||
| aa633bf2c7 | |||
| 621b92cd5e | |||
| 0d549ae203 | |||
| d944e67a69 | |||
| e2b13be7a0 | |||
| 8750485c6d | |||
| 1f9c1e6627 | |||
| 050e782df5 | |||
| 732f4856c6 | |||
| 27863c0bc9 | |||
| f0215a7009 | |||
| 3a06962045 | |||
| 6fffba5bb2 | |||
| 2ace8e0a5e | |||
| 99e99e5b60 | |||
| fc19e7dfdb | |||
| 2398fa4044 | |||
| aedfb6e6fa | |||
| c760a1c545 | |||
| bcb30ce933 | |||
| a4c3485440 | |||
| e8e223630a | |||
| 7b68bdce5f | |||
| 8884e47051 | |||
| 7c352e2038 | |||
| 2b20d3ef64 | |||
| 0d5a7f3224 | |||
| 4bc0cdd8b3 | |||
| 3511c95836 | |||
| 5456ada1bd | |||
| 1fa3ef37c3 | |||
| a5d8c49d75 | |||
| 0e69125217 | |||
| 046ecb794d | |||
| d61ebcf446 | |||
| cfb3c942d7 | |||
| e49a3275e2 | |||
| 30964aec70 | |||
| 4e39d09d1d | |||
| 162b70ce5d | |||
| 4b49d5d355 | |||
| 3e18a46758 | |||
| d6edc898c5 | |||
| 1dcaf135e5 | |||
| 25919e8393 | |||
| 1080a4e6f9 | |||
| b97769bf5c | |||
| d17c1c57be | |||
| fd1fc0f1d1 | |||
| eeddfcbec2 | |||
| fe2b9bd444 | |||
| 5ebb4b54d9 | |||
| cdd2967087 | |||
| e61505149a | |||
| 8dbe249bf9 | |||
| 38a0857a69 | |||
| 2b1b586251 | |||
| f36cdde500 | |||
| 6de1bfb64c | |||
| a5e82117cb | |||
| 2b7d04368a | |||
| a9dbdbc822 | |||
| 6528829796 | |||
| 3ad682a898 | |||
| 7aca2ee5be | |||
| 1c99f118ff | |||
| b49be74501 | |||
| 55f69da613 | |||
| ae7966a20c | |||
| 2e92fdf272 | |||
| cf9a3cdc38 | |||
| 70951375c9 | |||
| 6329a0070d | |||
| 29fae88610 | |||
| ee0c0fa6ba | |||
| 33822213e6 | |||
| cb05bedf08 | |||
| 4cf328c50b | |||
| f44eb0f8ba | |||
| 76c9029ec3 | |||
| 68e3516075 | |||
| 19ff8e95e5 | |||
| 4bf49bf6a6 | |||
| 0e377e43cc | |||
| f9f23806ed | |||
| 3569e16519 | |||
| 2a40ddd5f9 | |||
| efcd8987d9 | |||
| e66a4ce337 | |||
| 6d19d7c257 | |||
| 988aee863c | |||
| 8253899a70 | |||
| 4edca43531 | |||
| a876fc788d | |||
| cc79e5ca83 | |||
| 8aeb204c8a | |||
| db73939504 | |||
| de90187eb0 | |||
| 8aa809d2bc | |||
| 9e28d91879 | |||
| 2e89516b6e | |||
| f690b8e505 | |||
| 5964e4c332 | |||
| 6033b200e6 | |||
| 0ee33d34f2 | |||
| 44cb99f663 | |||
| 99170bc25b | |||
| 07640b1961 | |||
| e5cb41601e | |||
| f9d8e64a31 | |||
| 7bfdb82225 | |||
| 04aefeae55 | |||
| d6cad30c9f | |||
| 28358306e1 | |||
| 5539a982b5 | |||
| ed22433178 | |||
| 127876bd1b | |||
| c5cae05683 | |||
| 2f3cbdd7c5 | |||
| 9c682e2cc0 | |||
| f31dfd49d9 | |||
| 731b356c95 | |||
| 6d48a01801 | |||
| 3ec06fa3cc | |||
| 5a1d4ad491 | |||
| 581d67177d | |||
| ac6347fece | |||
| ebb42aa419 | |||
| 8223f9742e | |||
| dfdacba649 | |||
| eeeffd1ad1 | |||
| 93fc797b2e | |||
| 094d6de8e0 | |||
| 3d9fc4c40f | |||
| 3cdc207b50 | |||
| 5acd895e0d | |||
| 3715af2172 | |||
| be4d7a6249 | |||
| 04db1ff7cb | |||
| 5f1a04cfa0 | |||
| 4783e22fdc | |||
| db4903cdc4 | |||
| 248e37c292 | |||
| 8a8ba43bde | |||
| 5c0bc4913e | |||
| ca84ed7e63 | |||
| a64fb40d7e | |||
| d11102c643 | |||
| 745b5328eb | |||
| 5fefc74da4 | |||
| a3a73426bf | |||
| 276d867ab2 | |||
| 49b6a1725f | |||
| 4c67f4cc26 | |||
| b369cc4afc | |||
| 52a7f3e2dc | |||
| 85d1048762 | |||
| 8b80c79feb | |||
| 9bef4cb797 | |||
| 39edd3bdcd | |||
| b4585ce13a | |||
| e47790c3f8 | |||
| 5098088237 | |||
| b1c0d614a3 | |||
| 66c9d29539 | |||
| 655c8e609d | |||
| 948a0713d5 | |||
| b43d883db6 | |||
| 73367a10ea | |||
| b9eba042c0 | |||
| 17a33166a4 | |||
| ffbaf87dc9 | |||
| 8ea74c38c3 | |||
| 5789f20794 | |||
| 133e60410c | |||
| 57a8622e9a | |||
| 634039d81a | |||
| b9c9990bdb | |||
| 1e31e737f5 | |||
| 5e3f579431 | |||
| e9e4df8d01 | |||
| a3cdc4fb83 | |||
| c034e5922f | |||
| 3d8d726a52 | |||
| 1b09ac4757 | |||
| f7012d8275 | |||
| e61950267b | |||
| 4c9ff08f4f | |||
| 8668488a20 | |||
| 31f8dc5cbf | |||
| a477129bc1 | |||
| c46b8aecbc | |||
| a010b6177c | |||
| d38b7012e9 | |||
| 6a6152eb0a | |||
| 15121e6d4e | |||
| a8e44d0093 | |||
| fd8f74cf43 | |||
| 472e4da100 | |||
| 607fe8ed4b | |||
| a0a479eb53 | |||
| 04cdb15ceb | |||
| 180e0a3645 | |||
| c931800642 | |||
| e839d1a129 | |||
| 1efec52b33 | |||
| 3799481c35 | |||
| c1025612d1 | |||
| e07a8fbe31 | |||
| 2d52cb1d55 | |||
| a1cdbe5762 | |||
| 2f3bbf1f59 | |||
| 7ceb13d041 | |||
| d04d93eb9b | |||
| f6a3bc9168 | |||
| dca79490da | |||
| abf37168de | |||
| 67fadf0c94 | |||
| 1b29805fc9 | |||
| fcd3bbecdf | |||
| 3d767ffcc7 | |||
| f88711ebf9 | |||
| 17cd564ba6 | |||
| 8bb3bba7e8 | |||
| 5d3dda7a9d | |||
| 5761c182ee | |||
| 0e23e23a7c | |||
| e2736f4db1 | |||
| 1ea78293d0 | |||
| df0a195f38 | |||
| b00d23c46c | |||
| ed4966a3ff | |||
| b03359a3db | |||
| d4e07e981a | |||
| 2d097d0fd7 | |||
| 278b4547f4 | |||
| ee84127892 | |||
| 3724c40afd | |||
| eaada4cf1f | |||
| 033b25de32 | |||
| 32a12d1d6f | |||
| fe27b0e2ba | |||
| 66fcd4c5a2 | |||
| ccdeb6dc0a | |||
| b579262869 | |||
| 11f1dd1623 | |||
| 6a9a25fc54 | |||
| ef47f6cfd2 | |||
| cecd75063e | |||
| 6dad482efa | |||
| 4aae4489b9 | |||
| 1b00dede02 | |||
| 5700075b7a | |||
| 5a461f5bb3 | |||
| a6cbdccadc | |||
| b662a577ea | |||
| 128b1a423f | |||
| 5e41599d13 | |||
| 2cab94f56c | |||
| eedd673d4c | |||
| 25ffde5a42 | |||
| a06134cd6c | |||
| fa57fee9bb | |||
| 404bfdcf30 | |||
| 87d81a6d92 | |||
| 7d41dc1616 | |||
| c1e1502d35 | |||
| 73949712f6 | |||
| 61778974a4 | |||
| c817deb652 | |||
| 802a0117a7 | |||
| 9b2a450133 | |||
| fcfbe920d5 | |||
| b57331f450 | |||
| 944a61100b | |||
| f8ae1a9997 | |||
| 8ea015aaab | |||
| e38019d74e | |||
| 7da892b49a | |||
| 60c84abfe4 | |||
| efa1ac3807 | |||
| f6b7ab7994 | |||
| c0b6d159fc | |||
| fa85685baa | |||
| d1883bdd9d | |||
| b4ff4df808 | |||
| 3254bfa619 | |||
| bf26cf175f | |||
| 2c287965fc | |||
| 4551ded37e | |||
| b4d05af28f | |||
| eac742e3db | |||
| 57a1201b11 | |||
| 85a8a71fc5 | |||
| bd6bb510f8 | |||
| 0cf8221e62 | |||
| 36d4e8fa62 | |||
| a384290356 | |||
| 8b9226d820 | |||
| 35e639c599 | |||
| 3a7f5fcf03 | |||
| 881cbd6d2f | |||
| b319b710df | |||
| dd1ad34cea | |||
| 9406893722 | |||
| cea4d89697 | |||
| 7bbd31fa2a | |||
| c6d9a04dba | |||
| 77fc1aecb2 | |||
| 24da541747 | |||
| 02f7e9c800 | |||
| cbbc2f42e8 | |||
| 7e73dad7b0 | |||
| bc67fc338e | |||
| 6054e7be0a | |||
| a7f31c59a8 | |||
| 345e97f296 | |||
| 7716d4592d | |||
| 7e4eba9eed | |||
| a1089c9dd6 | |||
| 9a032e7422 | |||
| 55dddb69f7 | |||
| 580d42a63e | |||
| 1a1416aaa4 | |||
| 1d74450216 | |||
| 446a0a174e | |||
| 6405273059 | |||
| bbd0a41191 | |||
| 7bc9003fb8 | |||
| 7c745cd9c6 | |||
| 202f7f9107 | |||
| 1e1fbb4ccf | |||
| 0b17e5d288 | |||
| 3b046c409b | |||
| 9eeb56fe3e | |||
| 3124f8133a | |||
| f99ca77461 | |||
| 0bc1c08d4f | |||
| 3fcf44ae32 | |||
| 4d1dc14b45 | |||
| e4710f54f8 | |||
| ce983ec34a | |||
| bf9b535f66 | |||
| a2f0110f3d | |||
| 367924e669 | |||
| 9c6998c6bc | |||
| 1bf848e418 | |||
| d62e474850 | |||
| 7546333fbc | |||
| 405bb0ad90 | |||
| b7e9f8ce1e | |||
| 00a2da7d18 | |||
| 86c29e23df | |||
| 8765d96c4b | |||
| ee6233b893 | |||
| cebdb43234 | |||
| f65da3d98f | |||
| e6e13b2609 | |||
| 96774bb98c | |||
| 681301ab9b | |||
| 0d68dfcbc1 | |||
| 0a17e9a236 | |||
| 8597d2c681 | |||
| eca53baf6f | |||
| b7bc4ea43e | |||
| 6ab2f35f74 | |||
| c015153e21 | |||
| 7a74418c39 | |||
| 6033b3599e | |||
| 37d98063f0 | |||
| 7fe85b44f9 | |||
| 68125a7f50 | |||
| 166879a1c8 | |||
| b518569674 | |||
| 6a25e05e3c | |||
| 179862b10a | |||
| 339cf51c0c | |||
| c8d06997f5 | |||
| 57979f3c9b | |||
| e70a0e4e0e | |||
| 6268fe957a | |||
| 49ce5eecdf | |||
| 4e1da2b6d0 | |||
| 3f7d24bccf | |||
| de0c051e51 | |||
| 1ef99e657f | |||
| 7cbe1c0a44 | |||
| 8c45f18409 | |||
| ae3c02abae | |||
| 543d4af682 | |||
| 19c49fa82b | |||
| a723b8de7a | |||
| 21c3926714 | |||
| 3d79bf82f4 | |||
| 6338f88db1 | |||
| fdfe60dd09 | |||
| cdff2d0d41 | |||
| eb290bf362 | |||
| 18618deea3 | |||
| 67b64f5ec6 | |||
| f394f2c57f | |||
| 46670c7eeb | |||
| eefc79b5b2 | |||
| 744dd4893d | |||
| 7eed86de38 | |||
| 1c04f5a03c | |||
| 9d9d74faad | |||
| c2342776e1 | |||
| 09aa89f3f9 | |||
| a8430e09f5 | |||
| 768b039cde | |||
| 3f1b9a6b4a | |||
| 638e29b5d6 | |||
| 5abc48269b | |||
| c81b17c1cb | |||
| c928bc8ce3 | |||
| f33a4975ef | |||
| 5920137968 | |||
| f636e1d45f | |||
| 7e6a243df9 | |||
| ad7ba8f029 | |||
| 3096a26b59 | |||
| ff2a719bf7 | |||
| b6c4aaac8e | |||
| f7ad4ca025 | |||
| 4666b7fb69 | |||
| 125ce48525 | |||
| 114d12b060 | |||
| bf1566884c | |||
| fa7b6a8cec | |||
| 9855104120 | |||
| 36f7125513 | |||
| 6ebd5ddc53 | |||
| 2bc4103ea9 | |||
| 01eab7dccb | |||
| a95dee3d09 | |||
| 891c85a2c1 | |||
| 386f9b2074 | |||
| 325d5a6bcd | |||
| f05d7f4176 | |||
| a8ea2e05a4 | |||
| 8bcb88d6fd | |||
| f9bd431d56 | |||
| 0c6e180937 | |||
| 2c5fcd7d2c | |||
| 1a19c761ae | |||
| 71b8823625 | |||
| 24cab0eabd | |||
| 3e5c236942 | |||
| a3f74b2f68 | |||
| 2d09237bd7 | |||
| d26b94db61 | |||
| 017c41bc5f | |||
| d7857dd026 | |||
| 7ac5a172fa | |||
| f44a64a705 | |||
| 490b630e2d | |||
| 1265dc6334 | |||
| 69f994e1b2 | |||
| 0f841f194f | |||
| db6aecda47 | |||
| 83ca78a5fb | |||
| 2f0ae47c8e | |||
| 11a2d81738 | |||
| bb4ea2db67 | |||
| 70a2321cc1 | |||
| 2331742384 | |||
| d41ea73765 | |||
| 5a5616f258 | |||
| bd3108a40c | |||
| 8c9a12e3a1 | |||
| fe45fa81fc | |||
| 3e30600f70 | |||
| 5c05ec5b98 | |||
| 7024117709 | |||
| fd38b708fb | |||
| 153020283c | |||
| b41d1e0eaf | |||
| fcbfd00b98 | |||
| 51edb08796 | |||
| bb087fdc45 | |||
| a4a2196cc2 | |||
| 8ab96afd5b | |||
| f5b230a2ef | |||
| 076defb0a5 | |||
| 76660ff15b | |||
| 60471ecc1e | |||
| 9e68ba1ea3 | |||
| 414dddbf59 | |||
| a0c61484d2 | |||
| 7f6787c8b8 | |||
| 8c74dcde28 | |||
| 27332a8a17 | |||
| 8733da346b | |||
| e644f5be05 | |||
| 7007601655 | |||
| b1fc1cd11e | |||
| 919edcf1e1 | |||
| d99260c614 | |||
| cf9d1ba541 | |||
| d6628419c9 | |||
| 75eb5491d5 | |||
| c32d8f38ed | |||
| 9f22c35519 | |||
| f775500932 | |||
| fdbdb76c39 | |||
| af26e17fa7 | |||
| 769bf51359 | |||
| c81c316a46 | |||
| e5192ceddd | |||
| 89ddf97fa0 | |||
| 79b2eb0ff7 | |||
| 0ab0c7b8ed | |||
| 1d582a515c | |||
| a4a6064316 | |||
| 910d95a7b6 | |||
| 3cedadd738 | |||
| 3ba2d4428b | |||
| 7a545df299 | |||
| 2b3d6075e2 | |||
| 1073a524b9 | |||
| 6dd9cb6fb8 | |||
| 6789755b06 | |||
| e7dae3a9c1 | |||
| 1f78a15db2 | |||
| 79a4f42ef9 | |||
| 8fdf3799a2 | |||
| 4b095ab61f | |||
| 757d617ef3 | |||
| 17923c0d9e | |||
| c9f9db9069 | |||
| 90d03c784c | |||
| ea436444f2 | |||
| 209bb4290f | |||
| 7d9d2e508d | |||
| 5bd8e7d4e8 | |||
| 30f19be555 | |||
| 3e140ddcfe | |||
| 81143324a5 | |||
| fabb646a0b | |||
| 85131e359e | |||
| 5a0f8019c7 | |||
| f067dc8b32 | |||
| 14110cdea8 | |||
| f885296fb2 | |||
| a6c5f46f2d | |||
| 145ea35ac3 | |||
| 1399ed198c | |||
| c2fb99ce49 | |||
| 53542a9d37 | |||
| e77690c268 | |||
| d8e45ef866 | |||
| ffc24ad518 | |||
| b79c17b43c | |||
| be415dab1d | |||
| d0278dad15 | |||
| 927ff2bca7 | |||
| fc7b9029c9 | |||
| 187b529dbb | |||
| 2061947138 | |||
| 04c24cb686 | |||
| f38935459b | |||
| a6ce907a4f | |||
| f1dbfffd82 | |||
| a46d344db2 | |||
| 5476a03799 | |||
| d4569d66ac | |||
| c4ce6d9ab1 | |||
| fa083142a7 | |||
| 8aa8451434 | |||
| a1f81bbe97 | |||
| e9669c6594 | |||
| 690e7144c1 | |||
| a53b3d496c | |||
| be7f436951 | |||
| 7708753ed3 | |||
| 95d5ab706a | |||
| 7afb4e68f1 | |||
| 4caad33c9a | |||
| 1ece12b907 | |||
| 88c2f8504e | |||
| 9137a9ec80 | |||
| fad35e7e00 | |||
| 009925724e | |||
| 8504f30594 | |||
| 96116659be | |||
| 1e7df3606a | |||
| 603029b106 | |||
| 4ca54b2f1d | |||
| 555e24dc59 | |||
| a651aaea00 | |||
| 258b804941 | |||
| dbb4e67737 | |||
| ec1a5d1318 | |||
| cdab6cfdbe | |||
| 33b3d5edfb | |||
| e1aa6f7e84 | |||
| bfc1665d87 | |||
| 9e937f8113 | |||
| d114d9e386 | |||
| 4e8d1366b6 | |||
| 8afb0255f0 | |||
| dac6c662c5 | |||
| 577229bb6e | |||
| b5fdf4f1da | |||
| bf7d383066 | |||
| 6e977b668c | |||
| fdc52d933a | |||
| 316f7309a1 | |||
| ff75a28080 | |||
| e7b5e816d0 | |||
| db41bc2870 | |||
| 585aeb7f91 | |||
| 1b644a164e | |||
| c4e42f46a9 | |||
| bff4d1239c | |||
| 8a89e160ed | |||
| 198052358e | |||
| 6730b7d656 | |||
| f917efd430 | |||
| 7d51fc7dfb | |||
| b192495bbc | |||
| 34a697fc37 | |||
| 2dda514cb0 | |||
| 82d667e30c | |||
| 29b0b9cfcd | |||
| ed7f92ebc7 | |||
| 93ae8f4066 | |||
| 6b030ac9be | |||
| 8470c44bb0 | |||
| 4c75540ca2 | |||
| 70f43b0003 | |||
| 91452f3b58 | |||
| daeb396fd8 | |||
| ad649d9670 | |||
| 0038722d0f | |||
| 6a00664b2a | |||
| 2956543d27 | |||
| 0fcf722af4 | |||
| ceebdbfdd3 | |||
| 1b05af7f8e | |||
| 123b7b5537 | |||
| 5fa1257e2c | |||
| 5c405a6f40 | |||
| 03b5d6125b | |||
| 2376811df8 | |||
| c48997608d | |||
| 8a5285db41 | |||
| c4d6fc943a | |||
| 3655df08ea | |||
| 7858e6aa7c | |||
| c909988aa5 | |||
| 5deaba9669 | |||
| f162b6662b | |||
| 2d5f342ee8 | |||
| 85a2aee79c | |||
| a4cc671c22 | |||
| 2912138ef2 | |||
| cdae489afa | |||
| 51ad0c18ff | |||
| 998255fb1b | |||
| edfb5811cf | |||
| c733b32672 | |||
| 38862c1a09 | |||
| 03161c81df | |||
| 264c73747a | |||
| 5e53e410ce | |||
| b42ec57f6f | |||
| 4d0f664f50 | |||
| 2ea3b8b068 | |||
| 0810492a2c | |||
| c5178979ce | |||
| 08bdaf07be | |||
| 832764aa3a | |||
| 43c87d0cb6 | |||
| 6a6b944c00 | |||
| 90eb83dcb2 | |||
| 31b722f9d3 | |||
| e3351a9686 | |||
| 19dea9095e | |||
| 3b023da602 | |||
| 33d0a72fce | |||
| 5136fc535f | |||
| 16a21ade8f | |||
| ec2b2dc291 | |||
| 2703a5aebd | |||
| 4bdd21b281 | |||
| 499d41206e | |||
| ece008e790 | |||
| d1cfa88bc0 | |||
| 0e28b55184 | |||
| afccbbe04d | |||
| a4cec09781 | |||
| 54d70ec738 | |||
| 39c3a38e2d | |||
| 699897ddf8 | |||
| 00d3af4816 | |||
| ceadbbcdc1 | |||
| e703b53b3a | |||
| f037cc3c74 | |||
| 7dec942ef7 | |||
| 1d0ca22572 | |||
| a6decc3cc7 | |||
| b58cc107e6 | |||
| a593306a06 | |||
| 0177590699 | |||
| 787fe28fd0 | |||
| 541568e09f | |||
| 5dd7ef6895 | |||
| 153df79699 | |||
| 4ad9af71f5 | |||
| d76671a601 | |||
| ea094a4fbc | |||
| cb11dad4de | |||
| 817cf192c8 | |||
| aec00ab96f | |||
| 48b288cdc2 | |||
| 66d257f620 | |||
| dd14218c34 | |||
| 918231795b | |||
| 9f71172437 | |||
| 69e3b23960 | |||
| 7b426e8103 | |||
| 27e1043fc4 | |||
| 76518712c4 | |||
| 64843d6b0a | |||
| 87fa661591 | |||
| 2ec6d22131 | |||
| f6ac92dc39 | |||
| be69f7ad20 | |||
| 9a7cc494f7 | |||
| 8c3d4d4eda | |||
| 636ca7a74b | |||
| c57c1e94d1 | |||
| 1e1c2cbb7d | |||
| 5399b6f438 | |||
| 41b6c8434a | |||
| 3031b9e6a5 | |||
| 0d5331df59 | |||
| bca75d4930 | |||
| a70965eb6d | |||
| ad21bfda4d | |||
| fef46ffacf | |||
| f803745fc6 | |||
| c36ab1c6ed | |||
| 28f9d7f28f | |||
| 5b225186c4 | |||
| 09bb2a6054 | |||
| e1ea1237b7 | |||
| fb65f5d1ae | |||
| ff439ecd7f | |||
| 4cc4df87ff | |||
| 56aabe20bc | |||
| 4b624381e0 | |||
| c5508f34b3 | |||
| 3c667d7652 | |||
| 4664427784 | |||
| c747ffef95 | |||
| b5b1777304 | |||
| 228004b472 | |||
| a1f91c08ad | |||
| 96dc27d9e6 | |||
| 11f9f15199 | |||
| 991a92429e | |||
| 4f17dc0716 | |||
| 37c7fa9fb4 | |||
| fd2f700390 | |||
| 97255b2b7f | |||
| 8d32141b8f | |||
| 7700779e2c | |||
| 1cc9d2ce5a | |||
| b9980df1b7 | |||
| af8b256a00 | |||
| 324c39931c | |||
| 113325673f | |||
| 857b02706e | |||
| 1e0f1b39b0 | |||
| 6a429facb6 | |||
| 8663a6c7a0 | |||
| b6ec124ceb | |||
| 85a3b72c71 | |||
| d9b489d471 | |||
| 3289c6c305 | |||
| ec83adde3f | |||
| 206c8e1189 | |||
| 07545ba49c | |||
| 8312497d6c | |||
| eed2bed0bd | |||
| 49045cf08c | |||
| 55f7a99d1b | |||
| 98addf78b4 | |||
| 4b42ec3218 | |||
| e469d9d1f9 | |||
| d53d9d88fb | |||
| ed484deec6 | |||
| df9502dd06 | |||
| 6001254160 | |||
| 2b0c4ba215 | |||
| 1e9088f7d2 | |||
| ec9e283d34 | |||
| 20e7d431a6 | |||
| 6c745e6e9b | |||
| d1635e17f6 | |||
| f9e5881b45 | |||
| 869505a659 | |||
| 895d265603 | |||
| e5e60c6bed | |||
| 568e6c8093 | |||
| cf01f1a264 | |||
| be7de02a1d | |||
| b8d88f0dc5 | |||
| 698bc0cdac | |||
| 48a7a863ae | |||
| f2c4fa2b46 | |||
| f996d6cc7a | |||
| 0dbf3ef30a | |||
| 76b558c831 | |||
| c10bb66b12 | |||
| 89a391d001 | |||
| 0fef63956f | |||
| 63c2af4fa4 | |||
| 3ff7ddbea7 | |||
| 21733e7bda | |||
| 3fa60aaed8 | |||
| 9422e37c45 | |||
| c074c8c9d4 | |||
| 27c4956046 | |||
| ebbd7c48d3 | |||
| 079edee146 | |||
| 87f9452bbe | |||
| 9c0c64e87b | |||
| 3b65c120e8 | |||
| 3289835b53 | |||
| 7745d37d6c | |||
| 37e440b093 | |||
| 7792364e8c | |||
| 3a4ad03492 | |||
| cac7dbc607 | |||
| 7326c9cb73 | |||
| beb8e76bb4 | |||
| 43e37caf46 | |||
| a985798a86 | |||
| d09cca948f | |||
| 3f52031b86 | |||
| 7448116f37 | |||
| 4e0d54fe21 | |||
| 10d8275962 | |||
| 157cbc2f68 | |||
| 7d64d2e92a | |||
| f86261c812 | |||
| e1eb33a320 | |||
| cadcc20ea6 | |||
| 56ad7642c9 | |||
| d1695d3408 | |||
| b51fbe5c50 | |||
| 04c0ba65d2 | |||
| c2f5e7d88c | |||
| f456a92f08 | |||
| 48419d8fd9 | |||
| 0ef5dbac4a | |||
| 8014e0d993 | |||
| 739238659e | |||
| 6de593c771 | |||
| 4e9fd3ee9d | |||
| 900056be44 | |||
| 221cb6d5b2 | |||
| 83e693c78a | |||
| 8db5848e91 | |||
| 27807f02c5 | |||
| 30e31ff164 | |||
| ee0fe85cd0 | |||
| b2270b2f4f | |||
| 141252b73f | |||
| 7c4ac2e3a4 | |||
| 46b731b2d3 | |||
| bd76e47976 | |||
| bd2c878b35 | |||
| 84ee9591d1 | |||
| 15b27fa35f | |||
| e41536484b | |||
| d3004fc833 | |||
| 395c5fc922 | |||
| c20de314cc | |||
| 4881e6477f | |||
| 93609837dd | |||
| a8b3c20e66 | |||
| db2fba1faa | |||
| bf9cbb4491 | |||
| 18f32cfbd6 | |||
| a5a3ef17b8 | |||
| 326b827cc6 | |||
| 961efac8e2 | |||
| 418d26d250 | |||
| 07fb2a3e93 | |||
| 5006cca67b | |||
| 735e3b71d6 | |||
| d9da8228d4 | |||
| b5a7e66134 | |||
| 00bc96a2b7 | |||
| 5dd66771fb | |||
| 6f19a7deac | |||
| 811585b00f | |||
| f610377363 | |||
| 8c549a28df | |||
| cab22ffeac | |||
| 60c9f576f6 | |||
| b619c2069f | |||
| 3efdcb95cd | |||
| 4b11862ecc | |||
| c5e9b187ae | |||
| 04fc574229 | |||
| f6b6665fed | |||
| 0da9086397 | |||
| c5852c1237 | |||
| 5bbd7cb013 | |||
| a3b4a09fd2 | |||
| bf783c42bd | |||
| 57e832dc65 | |||
| ab2d301968 | |||
| f1f961a43e | |||
| 8e345bd09c | |||
| 0996c307ac | |||
| fb8e505590 | |||
| ec2804a78a | |||
| 29d2ee3273 | |||
| 6e3e6a1944 | |||
| 1005fd2872 | |||
| ab666cc267 | |||
| e79df21353 | |||
| ff0ddbcac0 | |||
| d1604137cc | |||
| 969efff611 | |||
| 293f7cca28 | |||
| 45a48cfcb2 | |||
| 822cc6a781 | |||
| 658f02a6b9 | |||
| 8d675d9bc0 | |||
| fdf135d877 | |||
| a2bb144556 | |||
| c867ed9de4 | |||
| 39ef596bdc | |||
| a9bcaa1493 | |||
| f05163fbeb | |||
| 7ad3e0c544 | |||
| 24882a9324 | |||
| 9bb6ead2b1 | |||
| d6bcbc5cdf | |||
| dc4b261c68 | |||
| 9262f13eef | |||
| 82998d0cc0 | |||
| 8949cfe584 | |||
| c10d1fe279 | |||
| 9ed5ee8310 | |||
| 7b266ef475 | |||
| 09f1a4fbb8 | |||
| c7f55381a5 | |||
| 81f35ffe73 | |||
| 597b362603 | |||
| 0163e4b4e4 | |||
| 98a77ee649 | |||
| c9edd2c8de | |||
| 379ad3a8e7 | |||
| aca64b5dda | |||
| d34639b79b | |||
| 0d4b157207 | |||
| 58160d9624 | |||
| 57e34dfb3c | |||
| 67ab19289d | |||
| 7718bf6858 | |||
| ee467d0203 | |||
| 9b7265810b | |||
| 24dc1092b1 | |||
| ab953f1381 | |||
| 83174e996e | |||
| 38069048fd | |||
| 9fda651595 | |||
| cb13ae57bc | |||
| 6a45d30715 | |||
| a43f24617d | |||
| f11a148d2d | |||
| 73cf4c0e49 | |||
| 8ea3cd1cb5 | |||
| 62979ae06d | |||
| 5e998288d6 | |||
| e01b851e1c | |||
| 2e6a40be96 | |||
| 02c1ec5efc | |||
| 78a6ba31d8 | |||
| 1ae23df0ba | |||
| 36ba9a7309 | |||
| 7ee129b21a | |||
| b3d4123007 | |||
| 5bfd330692 | |||
| 49125d1a7d | |||
| 6050ef41a9 | |||
| 0d809688ee | |||
| da20e80de6 | |||
| 1f46bf2e28 | |||
| f345dbe7e4 | |||
| 490c8d856e | |||
| 897a5b8de6 | |||
| 155cb4f158 | |||
| 445cf5860a | |||
| 6cb1bae032 | |||
| c0c9d667cd | |||
| b946032f56 | |||
| df8826240f | |||
| 5dda4f95a6 | |||
| f3822e6ffa | |||
| 084ad26b73 | |||
| fafecb491e | |||
| 0e6a590305 | |||
| 0e8c9fda5e | |||
| d2ac283570 | |||
| 69bdc16751 | |||
| b8325a38a1 | |||
| 403a1a7e1f | |||
| cf481d2fc4 | |||
| c3e3fc4dba | |||
| 254ad1b26b | |||
| 2c642afd04 | |||
| e43fab7c01 | |||
| 55f2914163 | |||
| 96d7ac7c6a | |||
| c9be096e88 | |||
| e18b8642c4 | |||
| dad83c9004 | |||
| f0a86c360c | |||
| c6444b7d05 | |||
| 6b81b6931f | |||
| b391fb3faf | |||
| 2649c38bf7 | |||
| 81266f2f71 | |||
| 05189f9ff5 | |||
| a3f8783dca | |||
| c20d23a552 | |||
| d2ed926077 | |||
| c0b3ad8253 | |||
| 30495f780a | |||
| a2114c44ad | |||
| 0f06a927ff | |||
| c5c41b8ab5 | |||
| 1f4ca54938 | |||
| 720e3e9272 | |||
| a42400272d | |||
| 19558b48c1 | |||
| 744d875838 | |||
| 59d2523c49 | |||
| 13fdde5e5d | |||
| 86e73c1bae | |||
| 6cd558fd5c | |||
| 8f45c7d27e | |||
| 3518b18351 | |||
| 6dea106650 | |||
| 123a29d126 | |||
| 9a8383de24 | |||
| 2453201d7b | |||
| 14deef3adf | |||
| 8c191e5ba8 | |||
| 20fc4a2efe | |||
| 49a577dd59 | |||
| 8b8f5d45c9 | |||
| cec687bad2 | |||
| 9891e2d986 | |||
| 24b23e2383 | |||
| 413aa106a2 | |||
| 097dcd724f | |||
| 1454880fb7 | |||
| c6a712dec3 | |||
| 2c888b86f5 | |||
| 7481dcf520 | |||
| 435a34cd60 | |||
| 23ffcf8f89 | |||
| 89d6a09401 | |||
| b8fce6a8e1 | |||
| 523e7eb397 | |||
| 30a3668779 | |||
| d95ea479c4 | |||
| baf18a6379 | |||
| 92831ee7d4 | |||
| de823996b5 | |||
| 936974f12c | |||
| 0c88507dcf | |||
| 9184095b34 | |||
| f1eea58b6b | |||
| 49f2206ef0 | |||
| 8f94a14063 | |||
| 9843e0c436 | |||
| e3149cd2b0 | |||
| 7c5d2ab029 | |||
| 6422be116b | |||
| 50eef193ff | |||
| 8092d98ea3 | |||
| ed42891509 | |||
| 6124226428 | |||
| 6c22590d4a | |||
| 950d9ae23a | |||
| a12ff75fee | |||
| 681413bb97 | |||
| 1ebe2c8728 | |||
| 41dd21ac7b | |||
| 6b6d9706bd | |||
| 1b57a79636 | |||
| a1f3b7d53f | |||
| 1118ef8f19 | |||
| 4b9526adb1 | |||
| ef3f42dfab | |||
| 6f018668c2 | |||
| f20d6e8d05 | |||
| 0574bf8aba | |||
| 7ea9f8ddcc | |||
| e4d9cb77fc | |||
| 7eee33a6a0 | |||
| 3bbafe14f5 | |||
| 1dc048662b | |||
| 7546651a30 | |||
| 6d16131b03 | |||
| 7eb196b4d1 | |||
| 1e8f7f7ba8 | |||
| eefbd1610e | |||
| 0f8af51da6 | |||
| c14dad91b2 | |||
| 2538262531 | |||
| 453a135a3e | |||
| 0cfa6d8097 | |||
| 7e77f3b902 | |||
| 71d2467963 | |||
| a6140c799d | |||
| bd7217b090 | |||
| cc45f4f212 | |||
| d95710f8e0 | |||
| b3703f1f91 | |||
| 104d63fd7c | |||
| df994764a5 | |||
| 764ef2dcc9 | |||
| 1dddc22a9b | |||
| ebac5c4a70 | |||
| 59a3715e40 | |||
| 86bb2f325e | |||
| eb370afe4a | |||
| fc06b1762f | |||
| a1fed86b28 | |||
| a96a265a7b | |||
| a2d65bb523 | |||
| 7c966fa775 | |||
| 8042d6f892 | |||
| d4c8c0bb52 | |||
| 148d567aa4 | |||
| 85e96c92ed | |||
| b25e440ba9 | |||
| c4d874cdb1 | |||
| 4e96cc4bbb | |||
| 78f928544f | |||
| 0edbe77903 | |||
| ccf8c3bd83 | |||
| f8020f4728 | |||
| 23bded5697 | |||
| 9df7292af6 | |||
| bcb05fbc14 | |||
| 7adc495692 | |||
| 69f8ee8ee2 | |||
| 4acb97e02e | |||
| 7cd840bf83 | |||
| 9577736788 | |||
| f7ec499ee9 | |||
| a64e1b3397 | |||
| abeba63ed5 | |||
| 0dd05887d2 | |||
| f8b3873b83 | |||
| 63362c97f5 | |||
| b07b214293 | |||
| e368ae3230 | |||
| 9cf627a656 | |||
| 5d383f1885 | |||
| f9b7ede7ff | |||
| a2a44bb7ef | |||
| 1f37ca437b | |||
| ac77e047f4 | |||
| 02a6baad8a | |||
| 799ef3bc0d | |||
| b337dccd0c | |||
| 8867bf262b | |||
| 0543670734 | |||
| 9c66afb6fe | |||
| 0dc8241605 | |||
| 7ca5c4099e | |||
| e40c8fa164 | |||
| df88d0cbea | |||
| f73e785662 | |||
| 1bb685cc57 | |||
| 5d4da5ede9 | |||
| fe295788e7 | |||
| f8b3eaedb5 | |||
| e5e83eba05 | |||
| 28a35c9883 | |||
| d8a6c7c1bf | |||
| c8f6806287 | |||
| 8bf57814a4 | |||
| c2d4338024 | |||
| 6410862b15 | |||
| 4845668a4a | |||
| 146adbf831 | |||
| d1f291acb8 | |||
| 4b7c3010e0 | |||
| 4039f66530 | |||
| 4ce6362f4c | |||
| 5765ebef08 | |||
| a3eb501225 | |||
| 82706bf152 | |||
| 5e852ba1fd | |||
| d49cdb2ded | |||
| a8ad1f8097 | |||
| 2ea3c4acac | |||
| d1e3bad24f | |||
| 06f46e4b14 | |||
| 54714fd989 | |||
| 912d308b9d | |||
| 0b71e4a98a | |||
| 900bef9ccf | |||
| 7106d1e605 | |||
| 6840ec0d09 | |||
| 0e8e811b14 | |||
| 3dc986bbf6 | |||
| 34813dc07c | |||
| f79d75076c | |||
| 57b5ce84a5 | |||
| 395338f46a | |||
| c33cd27626 | |||
| 2ca4512443 | |||
| 76b4dc7346 | |||
| 53609d2ecd | |||
| d24054ac00 | |||
| 2c0619f69d | |||
| f039aeb4c8 | |||
| ab0e47d402 | |||
| 03128b7530 | |||
| ed3e79325f | |||
| c4c715fcd0 | |||
| 86b83ddbc9 | |||
| 62c43eaf53 | |||
| 33cf2243a8 | |||
| 02a1c2f096 | |||
| b841150c23 | |||
| 3db19ba2eb | |||
| 22d1f50455 | |||
| baee140518 | |||
| deaa4529ae | |||
| bed29749f2 | |||
| e57cbd3348 | |||
| 2f788445a9 | |||
| d4e55c69c1 | |||
| d07351c8ba | |||
| 2412caf494 | |||
| 9b6f75afd3 | |||
| a4b2a6537c | |||
| cfaa7d9e54 | |||
| 0ca3012c67 | |||
| 42ebece808 | |||
| 0d7510c129 | |||
| ebe697f62a | |||
| 29240fd14b | |||
| 97f4d18a13 | |||
| 8ef0dd69da | |||
| 30d41b33d1 | |||
| 2ce06cfe08 | |||
| 3b1a1125d2 | |||
| 93cdfb566b | |||
| b61ac2069d | |||
| 6e8a71ec34 | |||
| 3b3fc0151e | |||
| f5643f2332 | |||
| 38e5d961f6 | |||
| 5be15bed82 | |||
| deb6aa8cc5 | |||
| 3b3e19ee8a | |||
| a713e47713 | |||
| abbc83bd51 | |||
| 7d4aaa8cdb | |||
| 06b3172333 | |||
| 2062cf8fe4 | |||
| 3e15da5bcc | |||
| 520eace689 | |||
| 9ed3c5dc46 | |||
| 7db3834f0b | |||
| 5979b1a1b6 | |||
| d283a8c878 | |||
| 3f2a258930 | |||
| 550d36dc33 | |||
| 46b9d9e359 | |||
| 3e084a3b0e | |||
| 391a663360 | |||
| 068ae2f344 | |||
| 64dfea78b8 | |||
| 3bbcd30396 | |||
| 09bfd3311c | |||
| fdd0e02c35 | |||
| 10b5322b87 | |||
| f01feef636 | |||
| 1aed2b3114 | |||
| adc9b70d72 | |||
| 5f86a70891 | |||
| ea9a84b748 | |||
| c73ca9a6da | |||
| e467e58857 | |||
| bb73777a4a | |||
| a63a62f827 | |||
| 1c6574e69d | |||
| 313785b421 | |||
| b6261f3d80 | |||
| 3dc4de85b5 | |||
| bb0711eb3f | |||
| 0cb647ee1e | |||
| 5a0c37e2b9 | |||
| 4a3ddd5b2c | |||
| e6095e6fd8 | |||
| 33d1d0f8e4 | |||
| d02025b0ed | |||
| 28af99d95d | |||
| 619c8e689a | |||
| c03355d67f | |||
| 417572f3c5 | |||
| c5ed76f104 | |||
| 5721a279c8 | |||
| 0cf8553b2e | |||
| 6d5b865741 | |||
| 7b08e81991 | |||
| 6d4e0ff665 | |||
| bd6ea96ed6 | |||
| 9feccc625b | |||
| 65949662f6 | |||
| 22defb9ad4 | |||
| 37cb4d00df | |||
| a48c0ece4b | |||
| b8c77dc417 | |||
| ed42ae5a79 | |||
| 20f83297ce | |||
| 896dc0fcf6 | |||
| f8a238e670 | |||
| 3b8f2a551b | |||
| 2263633df8 | |||
| 59b7a8ff8f | |||
| 9e6b63e3da | |||
| 5eb63c42f1 | |||
| 1bba1c5ee0 | |||
| f7047d3cfa | |||
| cb16951519 | |||
| 14dc5709ee | |||
| 7d03b0af33 | |||
| 33f7d83c71 | |||
| e469a6b3d8 | |||
| 2971ea6564 | |||
| 02ced9a339 | |||
| 1960a8768e | |||
| f4c8abb1b4 | |||
| ab9630b825 | |||
| e79d6ae971 | |||
| 0348e13258 | |||
| 40c7c7dae8 | |||
| 396695c866 | |||
| a07ae76bcc | |||
| 0221700226 | |||
| d8f3424554 | |||
| 623234c7c2 | |||
| 49aff4eba3 | |||
| 9281d15c70 | |||
| e482826ac3 | |||
| 49e2e292dd | |||
| d721f176f8 | |||
| 58532cd8c5 | |||
| 37fe3ca01a | |||
| 1a01535313 | |||
| 2ba0f5d807 | |||
| 48fa8fd20b | |||
| eeb179fc9a | |||
| 76d1abb9ca | |||
| 68d2aed8af | |||
| dfdecb7e0b | |||
| 2b54414e60 | |||
| 2f03f95e9d | |||
| a828d714c6 | |||
| e36a3dd460 | |||
| b60fda3fec | |||
| 590b237338 | |||
| 237592fbda | |||
| 9a6a301c4f | |||
| 064c057200 | |||
| d1077e6171 | |||
| b90e483117 | |||
| ad25f4c43a | |||
| de22ae4a99 | |||
| d166463bca | |||
| ef326260c2 | |||
| a969e87f13 | |||
| 532fb73c43 | |||
| 0c79aa30ab | |||
| cd68572df5 | |||
| a37cc75bd7 | |||
| 3b8118ac0b | |||
| bdf725f86b | |||
| c8866b7d4c | |||
| 552b211124 | |||
| 680fe999b2 | |||
| 1e380374eb | |||
| 25705ad61b | |||
| 6351d5a283 | |||
| 1666e12db2 | |||
| 728cbcdff4 | |||
| bd047624e5 | |||
| 0e8f5b8147 | |||
| 45d4353cf4 | |||
| c7455ca776 | |||
| 5def0c2eea | |||
| 9e4090f601 | |||
| d1a8ecca70 | |||
| 69415616f8 | |||
| 7eec35e4ea | |||
| f76bf37229 | |||
| 5c335f3acc | |||
| 98f91f8b0a | |||
| 93e568b254 | |||
| e86579b576 | |||
| 672ffefb5f | |||
| c500a6704e | |||
| 3e0c355d7b | |||
| 87da1b2d0c | |||
| 0d45084914 | |||
| 9097433898 | |||
| 0b704e356f | |||
| d847d5b942 | |||
| 694c900cd4 | |||
| 9204086f41 | |||
| d8395dfeb6 | |||
| 39f84d7fe4 | |||
| bbc8c1121f | |||
| 383ffdfe0a | |||
| 8c89c1daf5 | |||
| 706337b8ea | |||
| 9f67477858 | |||
| b703d81561 | |||
| 9e8be6cd28 | |||
| 250960f771 | |||
| bbfb0d669c | |||
| ad14802227 | |||
| d5b1087fb8 | |||
| 150b7cd4e2 | |||
| 20fc8ee3cc | |||
| 47877ec70c | |||
| 91e8aca0a9 | |||
| f809cc2db7 | |||
| b07caa93c9 | |||
| a65c42b7d8 | |||
| 583006b599 | |||
| 29b5837a91 | |||
| 26eadad611 | |||
| 0aafa5a591 | |||
| 0a42863bd1 | |||
| a1f23f3a4c | |||
| badef10f41 | |||
| f1284bd73c | |||
| d2926d2edf | |||
| da45f02f6a | |||
| 67a3a7521f | |||
| 699f87c617 | |||
| a568ed2bd8 | |||
| 6b4366a0a4 | |||
| 5aa957bcff | |||
| f22b5abfac | |||
| 8811f5053d | |||
| b16571bb86 | |||
| d12cf29322 | |||
| 7c8c7984a1 | |||
| a35ddcd0e1 | |||
| ddc95bc7f7 | |||
| ce99a71a52 | |||
| 9882eef93a | |||
| 140667308d | |||
| f50859fd09 | |||
| 86267bd8d6 | |||
| e5f6738280 | |||
| d6acc8debe | |||
| 84c562de1c | |||
| ddd6bb632a | |||
| 85b69b8689 | |||
| b2837d38b8 | |||
| 06582b4cf9 | |||
| f5d0863b2e | |||
| f05c0cd6ce | |||
| 223642904f | |||
| 8317e918d9 | |||
| d497b62fb3 | |||
| 014ba087a8 | |||
| dfa1f480b5 | |||
| 9ce8fcd268 | |||
| 6bd07d3d63 | |||
| 125d820dac | |||
| f77f7e645b | |||
| 82bee848a1 | |||
| 41aa30c93f | |||
| 594c4102f6 | |||
| cf1ae599f1 | |||
| 9fbc499361 | |||
| 3d747571d6 | |||
| 036e02e052 | |||
| d03a9188ae | |||
| a07e6e4013 | |||
| ea0562c124 | |||
| 215b6cc634 | |||
| f7460dfa9c | |||
| 92a285378a | |||
| d033f2235f | |||
| 29016a1fe4 | |||
| d75596c9b8 | |||
| 8ef3f8ade3 | |||
| cdce807375 | |||
| 4c9cf84dff | |||
| f878e38d12 | |||
| 24c572b806 | |||
| abb05eae40 | |||
| 934271b272 | |||
| a3366e6c95 | |||
| 8971bf7546 | |||
| 3a673cc06e | |||
| 8bf09f65cf | |||
| b7f5699b3e | |||
| 7d01550649 | |||
| 05aedc7c57 | |||
| 9af5367aee | |||
| 3c1015942d | |||
| 98329144a0 | |||
| dc990a5309 | |||
| c28dc2bb13 | |||
| c3fa406d60 | |||
| 3c84312ac5 | |||
| a88656ea5a | |||
| 86ad0d2c62 | |||
| 5512567d74 | |||
| d14d7f67b3 | |||
| f6b8a150bb | |||
| ba8ab188d8 | |||
| b188f76b65 | |||
| 48a745e934 | |||
| e1c9cbedd7 | |||
| c53c5b47ea | |||
| 487ac04a1b | |||
| c98771f683 | |||
| 9f990349ff | |||
| 3aed6de76e | |||
| 1be7a45f18 | |||
| 531228f3c0 | |||
| 15a53269d2 | |||
| 7187639286 | |||
| fd72c74184 | |||
| 9912fce370 | |||
| 063850bc20 | |||
| fb8c1ad75b | |||
| 805c6b9711 | |||
| e3fbd46a79 | |||
| 9fc9ca3265 | |||
| 40aee428b5 | |||
| b7fe42a545 | |||
| 5cbd311e80 | |||
| 4f74bf88f1 | |||
| 4df999cbe2 | |||
| 039fe4bddf | |||
| 833bbc5b88 | |||
| c0dfc5bb89 | |||
| b1866205ed | |||
| 50067840c7 | |||
| aa6c9e7f21 | |||
| cf4991979d | |||
| 09cfdfd756 | |||
| 72970d8c7d | |||
| c3d320aa8c | |||
| 3fcbc847a9 | |||
| 151fc3065b | |||
| 7eeb8a2c0c | |||
| 93437e3539 | |||
| ae81396710 | |||
| 7a61b1f4b9 | |||
| 6fd2e6ced0 | |||
| f3ddaf5dce | |||
| 961b408f10 | |||
| 18c5a9aef4 | |||
| 880844d178 | |||
| f55cf6f90d | |||
| ea90b73781 | |||
| e81576b74e | |||
| 4de3380ca5 | |||
| 7f2ecfe721 | |||
| 62c00ba871 | |||
| d55c34f662 | |||
| 76821902c8 | |||
| 504fd3e282 | |||
| 86da74e0bc | |||
| 484bbcbfba | |||
| 500e3b9d85 | |||
| b299c85f98 | |||
| 6a39f5bd1c | |||
| 2cecd66a50 | |||
| ca15df807c | |||
| ce4d8d902d | |||
| 0f83413a8f | |||
| 12a5a2da41 | |||
| 15f53f6d97 | |||
| 40d78f97e6 | |||
| cbe9446e50 | |||
| 890e7beb26 | |||
| 72926fd4ee | |||
| 0d62f4706a | |||
| da20193852 | |||
| cdc07b5d4e | |||
| df0d018b40 | |||
| d02e5ecdc5 | |||
| 7ee96336d7 | |||
| 89ce14bfee | |||
| b5b6e9997d | |||
| 9ea12cf091 | |||
| 5d6ca51ea8 | |||
| 2d0a80bcbb | |||
| a2eea79ea8 | |||
| fe52062f04 | |||
| 6c4f5c78d0 | |||
| d7a65ae09f | |||
| e97a630235 | |||
| f66f15ce90 | |||
| 7b6b9a6e22 | |||
| 4d471306f4 | |||
| e3dbc609d1 | |||
| 67bb18921b | |||
| 83c75f9291 | |||
| fce606ed94 | |||
| 24a9663db4 | |||
| b7dba5f72b | |||
| 60d245e968 | |||
| 689324ad24 | |||
| 5a2d655c4a | |||
| a6b258c953 | |||
| 765df72a6e | |||
| 2b5b1b2a40 | |||
| 55b3776f42 | |||
| f36217fb92 | |||
| 6881dae3bc | |||
| 02c7630bbb | |||
| d80207d69e | |||
| 09a999c8a1 | |||
| e3dd66ddb4 | |||
| f36ffece70 | |||
| d6d74ef77f | |||
| 279c944628 | |||
| ff624c35e3 | |||
| a6deca4da8 | |||
| 14d5685528 | |||
| cb13201fd5 | |||
| e56b50474a | |||
| 83b94092b6 | |||
| fe8318d336 | |||
| 898c009f50 | |||
| b8bdc638bf | |||
| 3537b47ba8 | |||
| 9bde5a6482 | |||
| f8b7583de5 | |||
| d484fbd93c | |||
| 214e5cc6e3 | |||
| a6c123d4e4 | |||
| 363a438fc6 | |||
| 2c4975c5b5 | |||
| f8d96846d5 | |||
| a57fd395fe | |||
| 9feea24516 | |||
| 41f2b5ec8d | |||
| a8e9046c6c | |||
| 67b1db7123 | |||
| 2a59f5ce00 | |||
| 14cf2d9532 | |||
| c10d526385 | |||
| 32efce9f86 | |||
| 533d885923 | |||
| 9903dd5ad9 | |||
| ad5a85ed51 | |||
| f25e5a1012 | |||
| acb7148ac4 | |||
| 585c87a8c6 | |||
| 9d651f85f1 | |||
| ddef0a729d | |||
| 7a0b449ac3 | |||
| f8bcc9966d | |||
| f300ddcada | |||
| c28013930e | |||
| 45b820abe2 | |||
| 034177f0c0 | |||
| 5edbac54d3 | |||
| 09bf5ca5a0 | |||
| 814f9ebc5b | |||
| 6680975105 | |||
| dfdbcd8325 | |||
| 2820371a00 | |||
| 5f1d1869e3 | |||
| a60a4405c8 | |||
| 24d596ee53 | |||
| 0c37fcebe8 | |||
| 1ca7408701 | |||
| eceaf3bfb4 | |||
| 68f8d44e0d | |||
| ab5f27c5af | |||
| f7d074d64c | |||
| 6ad9366be0 | |||
| 32cea2e656 | |||
| 17cf16dd19 | |||
| f533541b67 | |||
| f4ccffc754 | |||
| 6a51e74319 | |||
| eb99d460a3 | |||
| 25a92406ce | |||
| e2f76ff8e3 | |||
| a7cfb276a6 | |||
| a26ea8134c | |||
| 892cf8be29 | |||
| 4880bc49e1 | |||
| 068eb252c5 | |||
| e784171e11 | |||
| 98db29d939 | |||
| 6fddeb89bc | |||
| e51810cb65 | |||
| 27ae0785c1 | |||
| 1dabea71da | |||
| e6fe79daca | |||
| dd54429ff6 | |||
| 47c9866131 | |||
| c39e8b142e | |||
| 1b54306b2f | |||
| 1a193d24ef | |||
| d27bdd02ef | |||
| 9474623ff0 | |||
| caf2439116 | |||
| 4ad507b4e9 | |||
| 9e61e71cb1 | |||
| 1176351701 | |||
| ed835a4973 | |||
| 641c7a6d57 | |||
| 8bfbdc8cf5 | |||
| eae27b0baa | |||
| 6281f981fa | |||
| ee08bfb6aa | |||
| 6a07109e10 | |||
| 28d18a4f70 | |||
| 14e81fca0e | |||
| 6d0cb74b64 | |||
| 29b40bc75f | |||
| d78bf5a93c | |||
| f37b21bf6c | |||
| 7309784487 | |||
| 55426fb047 | |||
| a1172b6211 | |||
| 271a865d01 | |||
| 5050dd13f4 | |||
| 5ce81bf386 | |||
| 40fd3e9ae2 | |||
| d8bffe12d7 | |||
| 7566aa2824 | |||
| c97ede5c34 | |||
| a2416f0b3f | |||
| 89eefbdc6a | |||
| 44f64a852b | |||
| 11ecb09eab | |||
| e6f686533f | |||
| c8dd7d95de | |||
| 81a7af5704 | |||
| e0dd754995 | |||
| 178e024721 | |||
| 99877adb39 | |||
| 5d8779fac2 | |||
| 34e07ef245 | |||
| c2f006f37a | |||
| f19506c3ce | |||
| 313a40875a | |||
| c49acaddf4 | |||
| e2487270e5 | |||
| 2a29b56b12 | |||
| 746c533c3c | |||
| 3ddd2445e5 | |||
| a682132503 | |||
| 00bee0fa54 | |||
| 4d25d2ffcc | |||
| 1db4a96c2c | |||
| 8fef15cd56 | |||
| 64396d15c8 | |||
| 5d209f798a | |||
| 811006ed8f | |||
| 555e9ed5fe | |||
| 49eb11e135 | |||
| a40cc0d9fc | |||
| 23078fe9c4 | |||
| 254c6dc993 | |||
| 66d0b809da | |||
| d0223dc1a0 | |||
| 876b58cebc | |||
| a21c2b4144 | |||
| b38bde7e12 | |||
| 5cce143273 | |||
| 75b97c9e0d | |||
| 91d3e9d924 | |||
| b6819aa8dd | |||
| 60cb12c062 | |||
| 8ea57a4b36 | |||
| dd96425a72 | |||
| 1bdcac1aac | |||
| 70443d06a2 | |||
| e23512d815 | |||
| 8db20a6589 | |||
| e7787b18d3 | |||
| 7f7bbbcfb4 | |||
| 6a966bdb61 | |||
| 702ac16d12 | |||
| 8c9150c223 | |||
| af4e13e528 | |||
| 8951032d07 | |||
| a5a64daf75 | |||
| b3e7510d31 | |||
| 4bc6b69a96 | |||
| 00b0d03dee | |||
| 1c24f3b14a | |||
| 65383f28a2 | |||
| ef1c63169e | |||
| 7cf1f011ef | |||
| 4aeeaed4c7 | |||
| ebe2f2b950 | |||
| 9998946886 | |||
| 0b16a37675 | |||
| f860b5a058 | |||
| 4f982ee3d1 | |||
| 5f4acdee0e | |||
| e640cc187b | |||
| d52fa9bcfc | |||
| 3029f0dd16 | |||
| 9f69d80b12 | |||
| 573e154c18 | |||
| ad49eea20d | |||
| 1dfb8ee3ce | |||
| bca57a4330 | |||
| ea483333f4 | |||
| 9f2d83c148 | |||
| 4a59e203cb | |||
| 697137585e | |||
| 8031ec9d89 | |||
| 54310ba2bc | |||
| 60a894bded | |||
| f40cbb06d6 | |||
| 01576229fe | |||
| 6ad505b6e4 | |||
| 9c79b55078 | |||
| aac231c39a | |||
| 6b577e1516 | |||
| 79b4503d01 | |||
| 1673a59a65 | |||
| ae395070d9 | |||
| eced38791a | |||
| 7d3c3cc1e3 | |||
| a26fdf3b54 | |||
| b162585beb | |||
| 77fb880f2d | |||
| 46222d488e | |||
| c0abe47d87 | |||
| d6321ab2a1 | |||
| ca1cc1c76e | |||
| 92593c3ea9 | |||
| 4b2a89683a | |||
| a830db6d86 | |||
| 7fb62aedc7 | |||
| c7fa954449 | |||
| a002e04838 | |||
| fe38bab63e | |||
| 86e0c29c25 | |||
| e554792ea5 | |||
| a82f60e302 | |||
| 072a7ac84a | |||
| 8dcfd7be61 | |||
| a401afe52e | |||
| f2ccc83a29 | |||
| b0ccf97226 | |||
| 77cccbc405 | |||
| 6370db0587 | |||
| b5c71915c7 | |||
| c96777369d | |||
| 9d663c5819 | |||
| 218eaf92ec | |||
| bbc31e07e9 | |||
| db889737be | |||
| d16ddf42cb | |||
| fa0f0bfad9 | |||
| 23e28fdd93 | |||
| cb62a3b039 | |||
| 0cb15dba0a | |||
| 48112f1a50 | |||
| b99290a060 | |||
| ce013119b9 | |||
| 851643110f | |||
| 45d9f292f9 | |||
| b3723ae020 | |||
| 498bb81c0a | |||
| cfbc1d6b70 | |||
| 7355272818 | |||
| 3c49b63a6b | |||
| db7b0a2272 | |||
| 42e99ac2eb | |||
| 6f86b4ec95 | |||
| 574b492479 | |||
| c9cf188e08 | |||
| b459a204a4 | |||
| a8ca4dbc3a | |||
| 21c4e4940b | |||
| ee6e44669f | |||
| b84cab3fc0 | |||
| a9edcb5f10 | |||
| ee207e2249 | |||
| 28f06953fc | |||
| 90e3024517 | |||
| 6222a3a8f7 | |||
| 14482a174b | |||
| a2395a0417 | |||
| fb2fc2f43f | |||
| dccd6a0499 | |||
| 01ffe94974 | |||
| 67f51b6e69 | |||
| 105eec0693 | |||
| ea4dd30143 | |||
| abfa841a98 | |||
| 1003c372bf | |||
| ff99823130 | |||
| fe431f1e8e | |||
| 2ee49802a9 | |||
| 2ab46f7fa3 | |||
| 77e721f7ce | |||
| d4d1491a81 | |||
| b2b86d2e04 | |||
| 3f3e7fd9f5 | |||
| deec9e9ac8 | |||
| 5634eaaf7a | |||
| 05f8a7bfb7 | |||
| c1aa4fc1d0 | |||
| 51570c73e1 | |||
| 6afafe1114 | |||
| c431a1e701 | |||
| 177103021e | |||
| 5dd4e8ff47 | |||
| 8b36b16b03 | |||
| b04ea483a8 | |||
| 55bb147862 | |||
| f2ba32a950 | |||
| 35c893e84f | |||
| cca9777064 | |||
| 2f386b6be2 | |||
| 6d19312f51 | |||
| a16b8a5474 | |||
| 27b72c4c89 | |||
| dbdce87679 | |||
| 2fd37df46a | |||
| 32a55c5c6e | |||
| 481a3f1ba1 | |||
| 74f6c56d27 | |||
| bcaf8c7e70 | |||
| d1f4eecc3a | |||
| 7f5fef431a | |||
| f6a0f2743e | |||
| 9b49ee6208 | |||
| 198e472ba3 | |||
| 4226ac02dc | |||
| 4606630f5a | |||
| 5d8d561565 | |||
| 6a6ac8b47b | |||
| 6417d7f882 | |||
| 93ee368556 | |||
| d89171768b | |||
| b73037a282 | |||
| 1888ac386f | |||
| 535958a274 | |||
| 35e1f2abed | |||
| 6e5cfde4b1 | |||
| 52828730cb | |||
| e3eae253df | |||
| 104123aa88 | |||
| 71224984bb | |||
| 181f4ab54c | |||
| 5d1f303a16 | |||
| 6a48348831 | |||
| 33be36f175 | |||
| 1a63b68990 | |||
| 1e3963b75d | |||
| ca290eeb97 | |||
| dbe7934931 | |||
| ca12278e90 | |||
| db0e93fa8e | |||
| c8a041fbeb | |||
| 273d14d8a0 | |||
| 024592281f | |||
| 5dbcca1543 | |||
| b57b079c9b |
+47
@@ -0,0 +1,47 @@
|
||||
boost_root
|
||||
.downloads-by-cmake
|
||||
Build
|
||||
common/netlist_keywords.*
|
||||
common/netlist_lexer.h
|
||||
common/pcb_plot_params_lexer.h
|
||||
common/page_layout/page_layout_reader_keywords.cpp
|
||||
common/fp_lib_table_keywords.*
|
||||
common/gal/opengl/shader_src.h
|
||||
include/fp_lib_table_lexer.h
|
||||
include/netlist_lexer.h
|
||||
include/page_layout_reader_lexer.h
|
||||
eeschema/cmp_library_lexer.h
|
||||
eeschema/cmp_library_keywords.*
|
||||
eeschema/dialogs/dialog_bom_cfg_keywords.cpp
|
||||
eeschema/dialogs/dialog_bom_cfg_lexer.h
|
||||
eeschema/dialogs/dialog_bom_help_html.h
|
||||
eeschema/template_fieldnames_keywords.*
|
||||
eeschema/template_fieldnames_lexer.h
|
||||
pcbnew/dialogs/dialog_freeroute_exchange_help_html.h
|
||||
pcbnew/pcb_plot_params_keywords.cpp
|
||||
pcbnew/pcb_plot_params_lexer.h
|
||||
Makefile
|
||||
CMakeCache.txt
|
||||
auto_renamed_to_cpp
|
||||
Testing
|
||||
version.h
|
||||
config.h
|
||||
install_manifest.txt
|
||||
Documentation/doxygen
|
||||
Documentation/development/doxygen
|
||||
*.bak
|
||||
common/pcb_plot_params_keywords.cpp
|
||||
include/pcb_plot_params_lexer.h
|
||||
pcbnew/specctra_keywords.cpp
|
||||
pcbnew/specctra_lexer.h
|
||||
pcb_calculator/pcb_calculator_datafile_keywords.cpp
|
||||
pcb_calculator/pcb_calculator_datafile_lexer.h
|
||||
new/html
|
||||
new/sch_lib_table_keywords.cpp
|
||||
new/sch_lib_table_lexer.h
|
||||
new/sweet_keywords.cpp
|
||||
new/sweet_lexer.h
|
||||
bitmaps_png/png*
|
||||
bitmaps_png/tmp
|
||||
common/pcb_keywords.cpp
|
||||
include/pcb_lexer.h
|
||||
@@ -1,31 +0,0 @@
|
||||
|
||||
# Custom attribute to mark source files using KiCad C++ formatting
|
||||
[attr]kicad-cpp-source whitepace=tab-in-indent format.clang-format-kicad
|
||||
|
||||
# Custom attribute to mark KiCad's own CMake files
|
||||
[attr]kicad-cmake-source whitespace=tab-in-indent
|
||||
|
||||
# Custom attribute for auto-generated sources:
|
||||
# * Do not perform whitespace checking
|
||||
# * Do not format
|
||||
[attr]generated whitespace=-tab-in-indent,-indent-with-non-tab -format.clang-format-kicad
|
||||
|
||||
# By default, all C and C++ files conform to KiCad formatting,
|
||||
# unless overridden
|
||||
*.c kicad-cpp-source
|
||||
*.cpp kicad-cpp-source
|
||||
*.h kicad-cpp-source
|
||||
|
||||
*.cmake kicad-cmake-source
|
||||
*.txt kicad-cmake-source
|
||||
|
||||
# Compiled bitmap sources
|
||||
bitmaps_png/cpp_*/*.cpp generated
|
||||
|
||||
# wxFormBuilder-generated files
|
||||
**/dialog*/*_base.cpp generated
|
||||
**/dialog*/*_base.h generated
|
||||
|
||||
# Lemon grammars
|
||||
common/libeval/grammar.c generated
|
||||
common/libeval/grammar.h generated
|
||||
@@ -1,49 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Git "hook chain", used to execute multiple scripts per hook.
|
||||
# To use:
|
||||
# * create a directory called <hookname>.d
|
||||
# * add scripts to this directory (executable)
|
||||
# * ln -s hook-chain <hookname>
|
||||
#
|
||||
# Now the scripts in that directory should be called in order.
|
||||
#
|
||||
# Set $HOOKCHAIN_DEBUG to see the names of invoked scripts.
|
||||
#
|
||||
# Based on script by Oliver Reflalo:
|
||||
# https://stackoverflow.com/questions/8730514/chaining-git-hooks
|
||||
#
|
||||
|
||||
hookname=`basename $0`
|
||||
|
||||
# Temp file for stdin, cleared at exit
|
||||
FILE=`mktemp`
|
||||
trap 'rm -f $FILE' EXIT
|
||||
cat - > $FILE
|
||||
|
||||
# Git hooks directory (this dir)
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
|
||||
|
||||
# Execute hooks in the directory one by one
|
||||
for hook in $DIR/$hookname.d/*;
|
||||
do
|
||||
if [ -x "$hook" ]; then
|
||||
|
||||
if [ "$HOOKCHAIN_DEBUG" ]; then
|
||||
echo "Running hook $hook"
|
||||
fi
|
||||
|
||||
cat $FILE | $hook "$@"
|
||||
status=$?
|
||||
|
||||
if [ $status -ne 0 ]; then
|
||||
echo "Hook $hook failed with error code $status"
|
||||
echo "To commit anyway, use --no-verify"
|
||||
exit $status
|
||||
else
|
||||
if [ "$HOOKCHAIN_DEBUG" ]; then
|
||||
echo "Hook passed: $hook"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
@@ -1 +0,0 @@
|
||||
hook-chain
|
||||
@@ -1,91 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Runs clang-format on changed regions before commit.
|
||||
#
|
||||
# Remaining installation checks/instructions will be printed when you commit.
|
||||
#
|
||||
# Based on clang-format pre-commit hook by Alex Eagle
|
||||
# https://gist.github.com/alexeagle/c8ed91b14a407342d9a8e112b5ac7dab
|
||||
|
||||
# Set kicad.check-format to allow this hook to run
|
||||
# If not set, the hook always succeeds.
|
||||
|
||||
do_format=false
|
||||
|
||||
# Check if formatting is configured
|
||||
if [ "$(git config --get kicad.check-format)" = true ]; then
|
||||
do_format=true
|
||||
fi
|
||||
|
||||
# Older env variable method
|
||||
if [ ! -z "$KICAD_CHECK_FORMAT" ]; then
|
||||
do_format=true
|
||||
fi
|
||||
|
||||
if [ ! ${do_format} = true ]; then
|
||||
# No formatting required
|
||||
exit 0;
|
||||
fi
|
||||
|
||||
check_clang_format() {
|
||||
if hash git-clang-format 2>/dev/null; then
|
||||
return
|
||||
else
|
||||
echo "SETUP ERROR: no git-clang-format executable found, or it is not executable"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_git_config() {
|
||||
if [[ "$(git config --get clangFormat.style)" != "file" ]]; then
|
||||
echo "SETUP ERROR: git config clangFormat.style is wrong (should be 'file'). Fix this with:"
|
||||
echo "git config clangFormat.style file"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
get_filtered_filenames()
|
||||
{
|
||||
format_attr='clang-format-kicad'
|
||||
|
||||
# command to get list of candidate files
|
||||
git_list_files='git diff --cached --name-only --diff-filter=ACM'
|
||||
|
||||
files=$(${git_list_files} |
|
||||
|
||||
# Filter for format-controlled files
|
||||
git check-attr --stdin format.${format_attr} |
|
||||
|
||||
# output only the file names
|
||||
grep ": set$" |
|
||||
cut -d: -f1)
|
||||
|
||||
echo ${files}
|
||||
}
|
||||
|
||||
check_clang_format
|
||||
check_git_config
|
||||
|
||||
files_to_check=$(get_filtered_filenames)
|
||||
|
||||
if [ -z "${files_to_check}" ]; then
|
||||
# No controlled files to check
|
||||
exit 0;
|
||||
fi
|
||||
|
||||
git_clang_format_cmd="git clang-format -v --diff -- ${files_to_check}"
|
||||
|
||||
readonly out=$(${git_clang_format_cmd})
|
||||
|
||||
# In these cases, there is no formatting issues, so we succeed
|
||||
if [[ "$out" == *"no modified files to format"* ]]; then exit 0; fi
|
||||
if [[ "$out" == *"clang-format did not modify any files"* ]]; then exit 0; fi
|
||||
|
||||
# Any other case implies formatting results
|
||||
echo "ERROR: you need to run clang-format (e.g. using tools/check_coding.sh) on your commit"
|
||||
|
||||
# print the errors to show what's the issue
|
||||
${git_clang_format_cmd}
|
||||
|
||||
# fail the pre-commit
|
||||
exit 1
|
||||
-97
@@ -1,97 +0,0 @@
|
||||
boost_root
|
||||
.downloads-by-cmake
|
||||
Build*
|
||||
build*
|
||||
common/fp_lib_table_keywords.cpp
|
||||
common/netlist_keywords.*
|
||||
common/netlist_lexer.h
|
||||
common/pcb_plot_params_lexer.h
|
||||
common/page_layout/page_layout_reader_keywords.cpp
|
||||
common/lib_table_keywords.*
|
||||
common/gal/opengl/shader_src.h
|
||||
include/fp_lib_table_lexer.h
|
||||
include/lib_table_lexer.h
|
||||
include/netlist_lexer.h
|
||||
include/page_layout_reader_lexer.h
|
||||
eeschema/cmp_library_lexer.h
|
||||
eeschema/cmp_library_keywords.*
|
||||
eeschema/dialogs/dialog_bom_cfg_keywords.cpp
|
||||
eeschema/dialogs/dialog_bom_cfg_lexer.h
|
||||
eeschema/dialogs/dialog_bom_help_html.h
|
||||
eeschema/template_fieldnames_keywords.*
|
||||
eeschema/template_fieldnames_lexer.h
|
||||
pcbnew/pcb_plot_params_keywords.cpp
|
||||
pcbnew/pcb_plot_params_lexer.h
|
||||
pcb_calculator/attenuators/bridget_tee_formula.h
|
||||
pcb_calculator/attenuators/pi_formula.h
|
||||
pcb_calculator/attenuators/splitter_formula.h
|
||||
pcb_calculator/attenuators/tee_formula.h
|
||||
Makefile
|
||||
CMakeCache.txt
|
||||
auto_renamed_to_cpp
|
||||
Testing
|
||||
version.h
|
||||
config.h
|
||||
install_manifest.txt
|
||||
Documentation/doxygen
|
||||
Documentation/development/doxygen
|
||||
*.bak
|
||||
*.pyc
|
||||
common/pcb_plot_params_keywords.cpp
|
||||
include/pcb_plot_params_lexer.h
|
||||
pcbnew/specctra_import_export/specctra_keywords.cpp
|
||||
pcbnew/specctra_import_export/specctra_lexer.h
|
||||
pcb_calculator/pcb_calculator_datafile_keywords.cpp
|
||||
pcb_calculator/pcb_calculator_datafile_lexer.h
|
||||
new/html
|
||||
new/sch_lib_table_keywords.cpp
|
||||
new/sch_lib_table_lexer.h
|
||||
new/sweet_keywords.cpp
|
||||
new/sweet_lexer.h
|
||||
bitmaps_png/png*
|
||||
bitmaps_png/tmp
|
||||
common/pcb_keywords.cpp
|
||||
include/pcb_lexer.h
|
||||
fp-info-cache
|
||||
|
||||
# demo project auxillary files
|
||||
demos/**/*-bak
|
||||
demos/**/_autosave-*
|
||||
demos/**/fp-info-cache
|
||||
|
||||
# MacOS package info created by CMake
|
||||
bitmap2component/Info.plist
|
||||
cvpcb/Info.plist
|
||||
eeschema/Info.plist
|
||||
gerbview/Info.plist
|
||||
kicad/Info.plist
|
||||
pagelayout_editor/Info.plist
|
||||
pcb_calculator/Info.plist
|
||||
pcbnew/Info.plist
|
||||
|
||||
# editor/OS fluff
|
||||
.*.swp
|
||||
*~
|
||||
.idea
|
||||
.DS_Store
|
||||
*.png
|
||||
*.kiface
|
||||
*.o
|
||||
*.a
|
||||
*.cmake
|
||||
*.orig
|
||||
*.rej
|
||||
*.so
|
||||
*.old
|
||||
*.gch
|
||||
*.orig
|
||||
*.patch
|
||||
|
||||
# These CMake files are wanted
|
||||
!CMakeModules/*.cmake
|
||||
|
||||
# Eclipse IDE
|
||||
.project
|
||||
.cproject
|
||||
.pydevproject
|
||||
__pycache__
|
||||
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2012 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2012 Wayne Stambaugh <stambaughw@verizon.net>
|
||||
* Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_aux.cpp
|
||||
*/
|
||||
|
||||
#include <fctsys.h>
|
||||
|
||||
#include <common.h>
|
||||
#include <trigo.h>
|
||||
#include <wxBasePcbFrame.h>
|
||||
|
||||
#include <class_board_design_settings.h>
|
||||
#include <class_zone.h>
|
||||
#include <class_text_mod.h>
|
||||
#include <class_module.h>
|
||||
#include <class_drawsegment.h>
|
||||
#include <class_pcb_text.h>
|
||||
|
||||
#include <3d_viewer.h>
|
||||
#include <3d_canvas.h>
|
||||
#include <info3d_visu.h>
|
||||
#include <trackball.h>
|
||||
|
||||
|
||||
void S3D_MASTER::ObjectCoordsTo3DUnits( std::vector< S3D_VERTEX >& aVertices )
|
||||
{
|
||||
/* adjust object scale, rotation and offset position */
|
||||
for( unsigned ii = 0; ii < aVertices.size(); ii++ )
|
||||
{
|
||||
aVertices[ii].x *= m_MatScale.x;
|
||||
aVertices[ii].y *= m_MatScale.y;
|
||||
aVertices[ii].z *= m_MatScale.z;
|
||||
|
||||
// adjust rotation
|
||||
if( m_MatRotation.x )
|
||||
RotatePoint( &aVertices[ii].y, &aVertices[ii].z, m_MatRotation.x * 10 );
|
||||
|
||||
if( m_MatRotation.y )
|
||||
RotatePoint( &aVertices[ii].z, &aVertices[ii].x, m_MatRotation.y * 10 );
|
||||
|
||||
if( m_MatRotation.z )
|
||||
RotatePoint( &aVertices[ii].x, &aVertices[ii].y, m_MatRotation.z * 10 );
|
||||
|
||||
/* adjust offset position (offset is given in UNIT 3D (0.1 inch) */
|
||||
#define SCALE_3D_CONV ((IU_PER_MILS * 1000) / UNITS3D_TO_UNITSPCB)
|
||||
aVertices[ii].x += m_MatPosition.x * SCALE_3D_CONV;
|
||||
aVertices[ii].y += m_MatPosition.y * SCALE_3D_CONV;
|
||||
aVertices[ii].z += m_MatPosition.z * SCALE_3D_CONV;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TransfertToGLlist( std::vector< S3D_VERTEX >& aVertices, double aBiuTo3DUnits )
|
||||
{
|
||||
unsigned ii;
|
||||
GLfloat ax, ay, az, bx, by, bz, nx, ny, nz, r;
|
||||
|
||||
/* ignore faces with less than 3 points */
|
||||
if( aVertices.size() < 3 )
|
||||
return;
|
||||
|
||||
/* calculate normal direction */
|
||||
ax = aVertices[1].x - aVertices[0].x;
|
||||
ay = aVertices[1].y - aVertices[0].y;
|
||||
az = aVertices[1].z - aVertices[0].z;
|
||||
|
||||
bx = aVertices[aVertices.size() - 1].x - aVertices[0].x;
|
||||
by = aVertices[aVertices.size() - 1].y - aVertices[0].y;
|
||||
bz = aVertices[aVertices.size() - 1].z - aVertices[0].z;
|
||||
|
||||
nx = ay * bz - az * by;
|
||||
ny = az * bx - ax * bz;
|
||||
nz = ax * by - ay * bx;
|
||||
|
||||
r = sqrt( nx * nx + ny * ny + nz * nz );
|
||||
|
||||
if( r >= 0.000001 ) /* avoid division by zero */
|
||||
{
|
||||
nx /= r;
|
||||
ny /= r;
|
||||
nz /= r;
|
||||
glNormal3f( nx, ny, nz );
|
||||
}
|
||||
|
||||
/* glBegin/glEnd */
|
||||
switch( aVertices.size() )
|
||||
{
|
||||
case 3:
|
||||
glBegin( GL_TRIANGLES );
|
||||
break;
|
||||
|
||||
case 4:
|
||||
glBegin( GL_QUADS );
|
||||
break;
|
||||
|
||||
default:
|
||||
glBegin( GL_POLYGON );
|
||||
break;
|
||||
}
|
||||
|
||||
/* draw polygon/triangle/quad */
|
||||
for( ii = 0; ii < aVertices.size(); ii++ )
|
||||
{
|
||||
glVertex3d( aVertices[ii].x * aBiuTo3DUnits,
|
||||
aVertices[ii].y * aBiuTo3DUnits,
|
||||
aVertices[ii].z * aBiuTo3DUnits );
|
||||
}
|
||||
|
||||
glEnd();
|
||||
}
|
||||
|
||||
VERTEX_VALUE_CTRL::VERTEX_VALUE_CTRL( wxWindow* aParent, wxBoxSizer* aBoxSizer )
|
||||
{
|
||||
wxString text;
|
||||
|
||||
wxFlexGridSizer* gridSizer = new wxFlexGridSizer( 0, 2, 0, 0 );
|
||||
gridSizer->AddGrowableCol( 1 );
|
||||
gridSizer->SetFlexibleDirection( wxHORIZONTAL );
|
||||
gridSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
aBoxSizer->Add( gridSizer, 0, wxEXPAND, 5 );
|
||||
|
||||
wxStaticText* msgtitle = new wxStaticText( aParent, wxID_ANY, wxT( "X:" ) );
|
||||
gridSizer->Add( msgtitle, 0, wxALL , 5 );
|
||||
|
||||
m_XValueCtrl = new wxTextCtrl( aParent, wxID_ANY, wxEmptyString,
|
||||
wxDefaultPosition,wxDefaultSize, 0 );
|
||||
gridSizer->Add( m_XValueCtrl, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
msgtitle = new wxStaticText( aParent, wxID_ANY, wxT( "Y:" ), wxDefaultPosition,
|
||||
wxDefaultSize, 0 );
|
||||
gridSizer->Add( msgtitle, 0, wxALL, 5 );
|
||||
|
||||
m_YValueCtrl = new wxTextCtrl( aParent, wxID_ANY, wxEmptyString,
|
||||
wxDefaultPosition, wxDefaultSize, 0 );
|
||||
gridSizer->Add( m_YValueCtrl, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
msgtitle = new wxStaticText( aParent, wxID_ANY, wxT( "Z:" ), wxDefaultPosition,
|
||||
wxDefaultSize, 0 );
|
||||
gridSizer->Add( msgtitle, 0, wxALL, 5 );
|
||||
|
||||
m_ZValueCtrl = new wxTextCtrl( aParent, wxID_ANY, wxEmptyString,
|
||||
wxDefaultPosition, wxDefaultSize, 0 );
|
||||
gridSizer->Add( m_ZValueCtrl, 0, wxALL|wxEXPAND, 5 );
|
||||
}
|
||||
|
||||
|
||||
VERTEX_VALUE_CTRL::~VERTEX_VALUE_CTRL()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
S3D_VERTEX VERTEX_VALUE_CTRL::GetValue()
|
||||
{
|
||||
S3D_VERTEX value;
|
||||
double dtmp;
|
||||
|
||||
m_XValueCtrl->GetValue().ToDouble( &dtmp );
|
||||
value.x = dtmp;
|
||||
m_YValueCtrl->GetValue().ToDouble( &dtmp );
|
||||
value.y = dtmp;
|
||||
m_ZValueCtrl->GetValue().ToDouble( &dtmp );
|
||||
value.z = dtmp;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
void VERTEX_VALUE_CTRL::SetValue( S3D_VERTEX vertex )
|
||||
{
|
||||
wxString text;
|
||||
|
||||
text.Printf( wxT( "%f" ), vertex.x );
|
||||
m_XValueCtrl->Clear();
|
||||
m_XValueCtrl->AppendText( text );
|
||||
|
||||
text.Printf( wxT( "%f" ), vertex.y );
|
||||
m_YValueCtrl->Clear();
|
||||
m_YValueCtrl->AppendText( text );
|
||||
|
||||
text.Printf( wxT( "%f" ), vertex.z );
|
||||
m_ZValueCtrl->Clear();
|
||||
m_ZValueCtrl->AppendText( text );
|
||||
}
|
||||
|
||||
|
||||
void VERTEX_VALUE_CTRL::Enable( bool onoff )
|
||||
{
|
||||
m_XValueCtrl->Enable( onoff );
|
||||
m_YValueCtrl->Enable( onoff );
|
||||
m_ZValueCtrl->Enable( onoff );
|
||||
}
|
||||
@@ -1,774 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2018 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#define GLM_FORCE_RADIANS
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <utility>
|
||||
#include <iterator>
|
||||
|
||||
#include <wx/datetime.h>
|
||||
#include <wx/filename.h>
|
||||
#include <wx/log.h>
|
||||
#include <wx/stdpaths.h>
|
||||
|
||||
#include <boost/version.hpp>
|
||||
|
||||
#if BOOST_VERSION >= 106800
|
||||
#include <boost/uuid/detail/sha1.hpp>
|
||||
#else
|
||||
#include <boost/uuid/sha1.hpp>
|
||||
#endif
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/ext.hpp>
|
||||
|
||||
#include "common.h"
|
||||
#include "3d_cache.h"
|
||||
#include "3d_info.h"
|
||||
#include "sg/scenegraph.h"
|
||||
#include "filename_resolver.h"
|
||||
#include "3d_plugin_manager.h"
|
||||
#include "plugins/3dapi/ifsg_api.h"
|
||||
|
||||
|
||||
#define MASK_3D_CACHE "3D_CACHE"
|
||||
|
||||
static wxCriticalSection lock3D_cache;
|
||||
|
||||
|
||||
static bool isSHA1Same( const unsigned char* shaA, const unsigned char* shaB )
|
||||
{
|
||||
for( int i = 0; i < 20; ++i )
|
||||
if( shaA[i] != shaB[i] )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool checkTag( const char* aTag, void* aPluginMgrPtr )
|
||||
{
|
||||
if( NULL == aTag || NULL == aPluginMgrPtr )
|
||||
return false;
|
||||
|
||||
S3D_PLUGIN_MANAGER *pp = (S3D_PLUGIN_MANAGER*) aPluginMgrPtr;
|
||||
|
||||
return pp->CheckTag( aTag );
|
||||
}
|
||||
|
||||
|
||||
static const wxString sha1ToWXString( const unsigned char* aSHA1Sum )
|
||||
{
|
||||
unsigned char uc;
|
||||
unsigned char tmp;
|
||||
char sha1[41];
|
||||
int j = 0;
|
||||
|
||||
for( int i = 0; i < 20; ++i )
|
||||
{
|
||||
uc = aSHA1Sum[i];
|
||||
tmp = uc / 16;
|
||||
|
||||
if( tmp > 9 )
|
||||
tmp += 87;
|
||||
else
|
||||
tmp += 48;
|
||||
|
||||
sha1[j++] = tmp;
|
||||
tmp = uc % 16;
|
||||
|
||||
if( tmp > 9 )
|
||||
tmp += 87;
|
||||
else
|
||||
tmp += 48;
|
||||
|
||||
sha1[j++] = tmp;
|
||||
}
|
||||
|
||||
sha1[j] = 0;
|
||||
|
||||
return wxString::FromUTF8Unchecked( sha1 );
|
||||
}
|
||||
|
||||
|
||||
class S3D_CACHE_ENTRY
|
||||
{
|
||||
private:
|
||||
// prohibit assignment and default copy constructor
|
||||
S3D_CACHE_ENTRY( const S3D_CACHE_ENTRY& source );
|
||||
S3D_CACHE_ENTRY& operator=( const S3D_CACHE_ENTRY& source );
|
||||
|
||||
wxString m_CacheBaseName; // base name of cache file (a SHA1 digest)
|
||||
|
||||
public:
|
||||
S3D_CACHE_ENTRY();
|
||||
~S3D_CACHE_ENTRY();
|
||||
|
||||
void SetSHA1( const unsigned char* aSHA1Sum );
|
||||
const wxString GetCacheBaseName( void );
|
||||
|
||||
wxDateTime modTime; // file modification time
|
||||
unsigned char sha1sum[20];
|
||||
std::string pluginInfo; // PluginName:Version string
|
||||
SCENEGRAPH* sceneData;
|
||||
S3DMODEL* renderData;
|
||||
};
|
||||
|
||||
|
||||
S3D_CACHE_ENTRY::S3D_CACHE_ENTRY()
|
||||
{
|
||||
sceneData = NULL;
|
||||
renderData = NULL;
|
||||
memset( sha1sum, 0, 20 );
|
||||
}
|
||||
|
||||
|
||||
S3D_CACHE_ENTRY::~S3D_CACHE_ENTRY()
|
||||
{
|
||||
if( NULL != sceneData )
|
||||
delete sceneData;
|
||||
|
||||
if( NULL != renderData )
|
||||
S3D::Destroy3DModel( &renderData );
|
||||
}
|
||||
|
||||
|
||||
void S3D_CACHE_ENTRY::SetSHA1( const unsigned char* aSHA1Sum )
|
||||
{
|
||||
if( NULL == aSHA1Sum )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * [BUG] NULL passed for aSHA1Sum",
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy( sha1sum, aSHA1Sum, 20 );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const wxString S3D_CACHE_ENTRY::GetCacheBaseName( void )
|
||||
{
|
||||
if( m_CacheBaseName.empty() )
|
||||
m_CacheBaseName = sha1ToWXString( sha1sum );
|
||||
|
||||
return m_CacheBaseName;
|
||||
}
|
||||
|
||||
|
||||
S3D_CACHE::S3D_CACHE()
|
||||
{
|
||||
m_DirtyCache = false;
|
||||
m_FNResolver = new FILENAME_RESOLVER;
|
||||
m_Plugins = new S3D_PLUGIN_MANAGER;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
S3D_CACHE::~S3D_CACHE()
|
||||
{
|
||||
FlushCache();
|
||||
|
||||
if( m_FNResolver )
|
||||
delete m_FNResolver;
|
||||
|
||||
if( m_Plugins )
|
||||
delete m_Plugins;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SCENEGRAPH* S3D_CACHE::load( const wxString& aModelFile, S3D_CACHE_ENTRY** aCachePtr )
|
||||
{
|
||||
if( aCachePtr )
|
||||
*aCachePtr = NULL;
|
||||
|
||||
wxString full3Dpath = m_FNResolver->ResolvePath( aModelFile );
|
||||
|
||||
if( full3Dpath.empty() )
|
||||
{
|
||||
// the model cannot be found; we cannot proceed
|
||||
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * [3D model] could not find model '%s'\n",
|
||||
__FILE__, __FUNCTION__, __LINE__, aModelFile );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// check cache if file is already loaded
|
||||
wxCriticalSectionLocker lock( lock3D_cache );
|
||||
std::map< wxString, S3D_CACHE_ENTRY*, rsort_wxString >::iterator mi;
|
||||
mi = m_CacheMap.find( full3Dpath );
|
||||
|
||||
if( mi != m_CacheMap.end() )
|
||||
{
|
||||
wxFileName fname( full3Dpath );
|
||||
|
||||
if( fname.FileExists() ) // Only check if file exists. If not, it will
|
||||
{ // use the same model in cache.
|
||||
bool reload = false;
|
||||
wxDateTime fmdate = fname.GetModificationTime();
|
||||
|
||||
if( fmdate != mi->second->modTime )
|
||||
{
|
||||
unsigned char hashSum[20];
|
||||
getSHA1( full3Dpath, hashSum );
|
||||
mi->second->modTime = fmdate;
|
||||
|
||||
if( !isSHA1Same( hashSum, mi->second->sha1sum ) )
|
||||
{
|
||||
mi->second->SetSHA1( hashSum );
|
||||
reload = true;
|
||||
}
|
||||
}
|
||||
|
||||
if( reload )
|
||||
{
|
||||
if( NULL != mi->second->sceneData )
|
||||
{
|
||||
S3D::DestroyNode( mi->second->sceneData );
|
||||
mi->second->sceneData = NULL;
|
||||
}
|
||||
|
||||
if( NULL != mi->second->renderData )
|
||||
S3D::Destroy3DModel( &mi->second->renderData );
|
||||
|
||||
mi->second->sceneData = m_Plugins->Load3DModel( full3Dpath, mi->second->pluginInfo );
|
||||
}
|
||||
}
|
||||
|
||||
if( NULL != aCachePtr )
|
||||
*aCachePtr = mi->second;
|
||||
|
||||
return mi->second->sceneData;
|
||||
}
|
||||
|
||||
// a cache item does not exist; search the Filename->Cachename map
|
||||
return checkCache( full3Dpath, aCachePtr );
|
||||
}
|
||||
|
||||
|
||||
SCENEGRAPH* S3D_CACHE::Load( const wxString& aModelFile )
|
||||
{
|
||||
return load( aModelFile );
|
||||
}
|
||||
|
||||
|
||||
SCENEGRAPH* S3D_CACHE::checkCache( const wxString& aFileName, S3D_CACHE_ENTRY** aCachePtr )
|
||||
{
|
||||
if( aCachePtr )
|
||||
*aCachePtr = NULL;
|
||||
|
||||
unsigned char sha1sum[20];
|
||||
|
||||
if( !getSHA1( aFileName, sha1sum ) || m_CacheDir.empty() )
|
||||
{
|
||||
// just in case we can't get a hash digest (for example, on access issues)
|
||||
// or we do not have a configured cache file directory, we create an
|
||||
// entry to prevent further attempts at loading the file
|
||||
S3D_CACHE_ENTRY* ep = new S3D_CACHE_ENTRY;
|
||||
m_CacheList.push_back( ep );
|
||||
wxFileName fname( aFileName );
|
||||
ep->modTime = fname.GetModificationTime();
|
||||
|
||||
if( m_CacheMap.insert( std::pair< wxString, S3D_CACHE_ENTRY* >
|
||||
( aFileName, ep ) ).second == false )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * [BUG] duplicate entry in map file; key = '%s'",
|
||||
__FILE__, __FUNCTION__, __LINE__, aFileName );
|
||||
|
||||
m_CacheList.pop_back();
|
||||
delete ep;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( aCachePtr )
|
||||
*aCachePtr = ep;
|
||||
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
S3D_CACHE_ENTRY* ep = new S3D_CACHE_ENTRY;
|
||||
m_CacheList.push_back( ep );
|
||||
wxFileName fname( aFileName );
|
||||
ep->modTime = fname.GetModificationTime();
|
||||
|
||||
if( m_CacheMap.insert( std::pair< wxString, S3D_CACHE_ENTRY* >
|
||||
( aFileName, ep ) ).second == false )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * [BUG] duplicate entry in map file; key = '%s'",
|
||||
__FILE__, __FUNCTION__, __LINE__, aFileName );
|
||||
|
||||
m_CacheList.pop_back();
|
||||
delete ep;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( aCachePtr )
|
||||
*aCachePtr = ep;
|
||||
|
||||
ep->SetSHA1( sha1sum );
|
||||
|
||||
wxString bname = ep->GetCacheBaseName();
|
||||
wxString cachename = m_CacheDir + bname + wxT( ".3dc" );
|
||||
|
||||
if( wxFileName::FileExists( cachename ) && loadCacheData( ep ) )
|
||||
return ep->sceneData;
|
||||
|
||||
ep->sceneData = m_Plugins->Load3DModel( aFileName, ep->pluginInfo );
|
||||
|
||||
if( NULL != ep->sceneData )
|
||||
saveCacheData( ep );
|
||||
|
||||
return ep->sceneData;
|
||||
}
|
||||
|
||||
|
||||
bool S3D_CACHE::getSHA1( const wxString& aFileName, unsigned char* aSHA1Sum )
|
||||
{
|
||||
if( aFileName.empty() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * [BUG] empty filename",
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( NULL == aSHA1Sum )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, "%s\n * [BUG] NULL pointer passed for aMD5Sum",
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
FILE* fp = _wfopen( aFileName.wc_str(), L"rb" );
|
||||
#else
|
||||
FILE* fp = fopen( aFileName.ToUTF8(), "rb" );
|
||||
#endif
|
||||
|
||||
if( NULL == fp )
|
||||
return false;
|
||||
|
||||
boost::uuids::detail::sha1 dblock;
|
||||
unsigned char block[4096];
|
||||
size_t bsize = 0;
|
||||
|
||||
while( ( bsize = fread( &block, 1, 4096, fp ) ) > 0 )
|
||||
dblock.process_bytes( block, bsize );
|
||||
|
||||
fclose( fp );
|
||||
unsigned int digest[5];
|
||||
dblock.get_digest( digest );
|
||||
|
||||
// ensure MSB order
|
||||
for( int i = 0; i < 5; ++i )
|
||||
{
|
||||
int idx = i << 2;
|
||||
unsigned int tmp = digest[i];
|
||||
aSHA1Sum[idx+3] = tmp & 0xff;
|
||||
tmp >>= 8;
|
||||
aSHA1Sum[idx+2] = tmp & 0xff;
|
||||
tmp >>= 8;
|
||||
aSHA1Sum[idx+1] = tmp & 0xff;
|
||||
tmp >>= 8;
|
||||
aSHA1Sum[idx] = tmp & 0xff;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool S3D_CACHE::loadCacheData( S3D_CACHE_ENTRY* aCacheItem )
|
||||
{
|
||||
wxString bname = aCacheItem->GetCacheBaseName();
|
||||
|
||||
if( bname.empty() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
" * [3D model] cannot load cached model; no file hash available" );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( m_CacheDir.empty() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
" * [3D model] cannot load cached model; config directory unknown" );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
wxString fname = m_CacheDir + bname + wxT( ".3dc" );
|
||||
|
||||
if( !wxFileName::FileExists( fname ) )
|
||||
{
|
||||
wxString errmsg = "cannot open file";
|
||||
wxLogTrace( MASK_3D_CACHE, " * [3D model] %s '%s'", errmsg.GetData(), fname.GetData() );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( NULL != aCacheItem->sceneData )
|
||||
S3D::DestroyNode( (SGNODE*) aCacheItem->sceneData );
|
||||
|
||||
aCacheItem->sceneData = (SCENEGRAPH*)S3D::ReadCache( fname.ToUTF8(), m_Plugins, checkTag );
|
||||
|
||||
if( NULL == aCacheItem->sceneData )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool S3D_CACHE::saveCacheData( S3D_CACHE_ENTRY* aCacheItem )
|
||||
{
|
||||
if( NULL == aCacheItem )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * NULL passed for aCacheItem",
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( NULL == aCacheItem->sceneData )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * aCacheItem has no valid scene data",
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
wxString bname = aCacheItem->GetCacheBaseName();
|
||||
|
||||
if( bname.empty() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
" * [3D model] cannot load cached model; no file hash available" );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( m_CacheDir.empty() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
" * [3D model] cannot load cached model; config directory unknown" );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
wxString fname = m_CacheDir + bname + wxT( ".3dc" );
|
||||
|
||||
if( wxFileName::Exists( fname ) )
|
||||
{
|
||||
if( !wxFileName::FileExists( fname ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, " * [3D model] path exists but is not a regular file '%s'",
|
||||
fname );
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return S3D::WriteCache( fname.ToUTF8(), true, (SGNODE*)aCacheItem->sceneData,
|
||||
aCacheItem->pluginInfo.c_str() );
|
||||
}
|
||||
|
||||
|
||||
bool S3D_CACHE::Set3DConfigDir( const wxString& aConfigDir )
|
||||
{
|
||||
if( !m_ConfigDir.empty() )
|
||||
return false;
|
||||
|
||||
wxFileName cfgdir;
|
||||
|
||||
if( aConfigDir.StartsWith( "${" ) || aConfigDir.StartsWith( "$(" ) )
|
||||
cfgdir.Assign( ExpandEnvVarSubstitutions( aConfigDir ), "" );
|
||||
else
|
||||
cfgdir.Assign( aConfigDir, "" );
|
||||
|
||||
cfgdir.Normalize();
|
||||
|
||||
if( !cfgdir.DirExists() )
|
||||
{
|
||||
cfgdir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
|
||||
|
||||
if( !cfgdir.DirExists() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
"%s:%s:%d\n * failed to create 3D configuration directory '%s'",
|
||||
__FILE__, __FUNCTION__, __LINE__, cfgdir.GetPath() );
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_ConfigDir = cfgdir.GetPath();
|
||||
|
||||
// inform the file resolver of the config directory
|
||||
if( !m_FNResolver->Set3DConfigDir( m_ConfigDir ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
"%s:%s:%d\n * could not set 3D Config Directory on filename resolver\n"
|
||||
" * config directory: '%s'",
|
||||
__FILE__, __FUNCTION__, __LINE__, m_ConfigDir );
|
||||
}
|
||||
|
||||
// 3D cache data must go to a user's cache directory;
|
||||
// unfortunately wxWidgets doesn't seem to provide
|
||||
// functions to retrieve such a directory.
|
||||
//
|
||||
// 1. OSX: ~/Library/Caches/kicad/3d/
|
||||
// 2. Linux: ${XDG_CACHE_HOME}/kicad/3d ~/.cache/kicad/3d/
|
||||
// 3. MSWin: AppData\Local\kicad\3d
|
||||
wxString cacheDir;
|
||||
|
||||
#if defined(_WIN32)
|
||||
wxStandardPaths::Get().UseAppInfo( wxStandardPaths::AppInfo_None );
|
||||
cacheDir = wxStandardPaths::Get().GetUserLocalDataDir();
|
||||
cacheDir.append( "\\kicad\\3d" );
|
||||
#elif defined(__APPLE)
|
||||
cacheDir = "${HOME}/Library/Caches/kicad/3d";
|
||||
#else // assume Linux
|
||||
cacheDir = ExpandEnvVarSubstitutions( "${XDG_CACHE_HOME}" );
|
||||
|
||||
if( cacheDir.empty() || cacheDir == "${XDG_CACHE_HOME}" )
|
||||
cacheDir = "${HOME}/.cache";
|
||||
|
||||
cacheDir.append( "/kicad/3d" );
|
||||
#endif
|
||||
|
||||
cacheDir = ExpandEnvVarSubstitutions( cacheDir );
|
||||
cfgdir.Assign( cacheDir, "" );
|
||||
|
||||
if( !cfgdir.DirExists() )
|
||||
{
|
||||
cfgdir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
|
||||
|
||||
if( !cfgdir.DirExists() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * failed to create 3D cache directory '%s'",
|
||||
__FILE__, __FUNCTION__, __LINE__, cfgdir.GetPath() );
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_CacheDir = cfgdir.GetPathWithSep();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
wxString S3D_CACHE::Get3DConfigDir( bool createDefault )
|
||||
{
|
||||
if( !m_ConfigDir.empty() || !createDefault )
|
||||
return m_ConfigDir;
|
||||
|
||||
// note: duplicated from common/common.cpp GetKicadConfigPath() to avoid
|
||||
// code coupling; ideally the instantiating code should call
|
||||
// Set3DConfigDir() to set the directory rather than relying on this
|
||||
// directory remaining the same in future KiCad releases.
|
||||
wxFileName cfgpath;
|
||||
|
||||
// From the wxWidgets wxStandardPaths::GetUserConfigDir() help:
|
||||
// Unix: ~ (the home directory)
|
||||
// Windows: "C:\Documents and Settings\username\Application Data"
|
||||
// Mac: ~/Library/Preferences
|
||||
cfgpath.AssignDir( wxStandardPaths::Get().GetUserConfigDir() );
|
||||
|
||||
#if !defined( __WINDOWS__ ) && !defined( __WXMAC__ )
|
||||
wxString envstr = ExpandEnvVarSubstitutions( "${XDG_CONFIG_HOME}" );
|
||||
|
||||
if( envstr.IsEmpty() || envstr == "${XDG_CONFIG_HOME}" )
|
||||
{
|
||||
// XDG_CONFIG_HOME is not set, so use the fallback
|
||||
cfgpath.AppendDir( wxT( ".config" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Override the assignment above with XDG_CONFIG_HOME
|
||||
cfgpath.AssignDir( envstr );
|
||||
}
|
||||
#endif
|
||||
|
||||
cfgpath.AppendDir( wxT( "kicad" ) );
|
||||
cfgpath.AppendDir( wxT( "3d" ) );
|
||||
|
||||
if( !cfgpath.DirExists() )
|
||||
{
|
||||
cfgpath.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
|
||||
}
|
||||
|
||||
if( !cfgpath.DirExists() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * failed to create 3D configuration directory '%s'",
|
||||
__FILE__, __FUNCTION__, __LINE__, cfgpath.GetPath() );
|
||||
|
||||
return wxT( "" );
|
||||
}
|
||||
|
||||
if( Set3DConfigDir( cfgpath.GetPath() ) )
|
||||
return m_ConfigDir;
|
||||
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
|
||||
bool S3D_CACHE::SetProjectDir( const wxString& aProjDir )
|
||||
{
|
||||
bool hasChanged = false;
|
||||
|
||||
if( m_FNResolver->SetProjectDir( aProjDir, &hasChanged ) && hasChanged )
|
||||
{
|
||||
m_CacheMap.clear();
|
||||
|
||||
std::list< S3D_CACHE_ENTRY* >::iterator sL = m_CacheList.begin();
|
||||
std::list< S3D_CACHE_ENTRY* >::iterator eL = m_CacheList.end();
|
||||
|
||||
while( sL != eL )
|
||||
{
|
||||
delete *sL;
|
||||
++sL;
|
||||
}
|
||||
|
||||
m_CacheList.clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void S3D_CACHE::SetProgramBase( PGM_BASE* aBase )
|
||||
{
|
||||
m_FNResolver->SetProgramBase( aBase );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
wxString S3D_CACHE::GetProjectDir( void )
|
||||
{
|
||||
return m_FNResolver->GetProjectDir();
|
||||
}
|
||||
|
||||
|
||||
FILENAME_RESOLVER* S3D_CACHE::GetResolver( void )
|
||||
{
|
||||
return m_FNResolver;
|
||||
}
|
||||
|
||||
|
||||
std::list< wxString > const* S3D_CACHE::GetFileFilters( void ) const
|
||||
{
|
||||
return m_Plugins->GetFileFilters();
|
||||
}
|
||||
|
||||
|
||||
void S3D_CACHE::FlushCache( bool closePlugins )
|
||||
{
|
||||
std::list< S3D_CACHE_ENTRY* >::iterator sCL = m_CacheList.begin();
|
||||
std::list< S3D_CACHE_ENTRY* >::iterator eCL = m_CacheList.end();
|
||||
|
||||
while( sCL != eCL )
|
||||
{
|
||||
delete *sCL;
|
||||
++sCL;
|
||||
}
|
||||
|
||||
m_CacheList.clear();
|
||||
m_CacheMap.clear();
|
||||
|
||||
if( closePlugins )
|
||||
ClosePlugins();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D_CACHE::ClosePlugins( void )
|
||||
{
|
||||
if( NULL != m_Plugins )
|
||||
m_Plugins->ClosePlugins();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
S3DMODEL* S3D_CACHE::GetModel( const wxString& aModelFileName )
|
||||
{
|
||||
S3D_CACHE_ENTRY* cp = NULL;
|
||||
SCENEGRAPH* sp = load( aModelFileName, &cp );
|
||||
|
||||
if( !sp )
|
||||
return NULL;
|
||||
|
||||
if( !cp )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
"%s:%s:%d\n * [BUG] model loaded with no associated S3D_CACHE_ENTRY",
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( cp->renderData )
|
||||
return cp->renderData;
|
||||
|
||||
S3DMODEL* mp = S3D::GetModel( sp );
|
||||
cp->renderData = mp;
|
||||
|
||||
return mp;
|
||||
}
|
||||
|
||||
|
||||
wxString S3D_CACHE::GetModelHash( const wxString& aModelFileName )
|
||||
{
|
||||
wxString full3Dpath = m_FNResolver->ResolvePath( aModelFileName );
|
||||
|
||||
if( full3Dpath.empty() || !wxFileName::FileExists( full3Dpath ) )
|
||||
return wxEmptyString;
|
||||
|
||||
// check cache if file is already loaded
|
||||
std::map< wxString, S3D_CACHE_ENTRY*, rsort_wxString >::iterator mi;
|
||||
mi = m_CacheMap.find( full3Dpath );
|
||||
|
||||
if( mi != m_CacheMap.end() )
|
||||
return mi->second->GetCacheBaseName();
|
||||
|
||||
// a cache item does not exist; search the Filename->Cachename map
|
||||
S3D_CACHE_ENTRY* cp = NULL;
|
||||
checkCache( full3Dpath, &cp );
|
||||
|
||||
if( NULL != cp )
|
||||
return cp->GetCacheBaseName();
|
||||
|
||||
return wxEmptyString;
|
||||
}
|
||||
@@ -1,206 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_cache.h
|
||||
* defines the display data cache manager for 3D models
|
||||
*/
|
||||
|
||||
#ifndef CACHE_3D_H
|
||||
#define CACHE_3D_H
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <wx/string.h>
|
||||
#include "kicad_string.h"
|
||||
#include "filename_resolver.h"
|
||||
#include "3d_info.h"
|
||||
#include "plugins/3dapi/c3dmodel.h"
|
||||
|
||||
|
||||
class PGM_BASE;
|
||||
class S3D_CACHE;
|
||||
class S3D_CACHE_ENTRY;
|
||||
class SCENEGRAPH;
|
||||
class FILENAME_RESOLVER;
|
||||
class S3D_PLUGIN_MANAGER;
|
||||
|
||||
|
||||
class S3D_CACHE
|
||||
{
|
||||
private:
|
||||
/// cache entries
|
||||
std::list< S3D_CACHE_ENTRY* > m_CacheList;
|
||||
|
||||
/// mapping of file names to cache names and data
|
||||
std::map< wxString, S3D_CACHE_ENTRY*, rsort_wxString > m_CacheMap;
|
||||
|
||||
/// object to resolve file names
|
||||
FILENAME_RESOLVER* m_FNResolver;
|
||||
|
||||
/// plugin manager
|
||||
S3D_PLUGIN_MANAGER* m_Plugins;
|
||||
|
||||
/// set true if the cache needs to be updated
|
||||
bool m_DirtyCache;
|
||||
|
||||
/// 3D cache directory
|
||||
wxString m_CacheDir;
|
||||
|
||||
/// base configuration path for 3D items
|
||||
wxString m_ConfigDir;
|
||||
|
||||
/// current KiCad project dir
|
||||
wxString m_ProjDir;
|
||||
|
||||
/** Find or create cache entry for file name
|
||||
*
|
||||
* Searches the cache list for the given filename and retrieves
|
||||
* the cache data; a cache entry is created if one does not
|
||||
* already exist.
|
||||
*
|
||||
* @param[in] aFileName file name (full or partial path)
|
||||
* @param[out] aCachePtr optional return address for cache entry pointer
|
||||
* @return SCENEGRAPH object associated with file name
|
||||
* @retval NULL on error
|
||||
*/
|
||||
SCENEGRAPH* checkCache( const wxString& aFileName, S3D_CACHE_ENTRY** aCachePtr = NULL );
|
||||
|
||||
/**
|
||||
* Function getSHA1
|
||||
* calculates the SHA1 hash of the given file
|
||||
*
|
||||
* @param[in] aFileName file name (full path)
|
||||
* @param[out] aSHA1Sum a 20 byte character array to hold the SHA1 hash
|
||||
* @retval true success
|
||||
* @retval false failure
|
||||
*/
|
||||
bool getSHA1( const wxString& aFileName, unsigned char* aSHA1Sum );
|
||||
|
||||
// load scene data from a cache file
|
||||
bool loadCacheData( S3D_CACHE_ENTRY* aCacheItem );
|
||||
|
||||
// save scene data to a cache file
|
||||
bool saveCacheData( S3D_CACHE_ENTRY* aCacheItem );
|
||||
|
||||
// the real load function (can supply a cache entry pointer to member functions)
|
||||
SCENEGRAPH* load( const wxString& aModelFile, S3D_CACHE_ENTRY** aCachePtr = NULL );
|
||||
|
||||
public:
|
||||
S3D_CACHE();
|
||||
virtual ~S3D_CACHE();
|
||||
|
||||
/**
|
||||
* Function Set3DConfigDir
|
||||
* Sets the configuration directory to be used by the
|
||||
* model manager for storing 3D model manager configuration
|
||||
* data and the model cache. The config directory may only be
|
||||
* set once in the lifetime of the object.
|
||||
*
|
||||
* @param aConfigDir is the configuration directory to use
|
||||
* for 3D model manager data
|
||||
* @return true on success
|
||||
*/
|
||||
bool Set3DConfigDir( const wxString& aConfigDir );
|
||||
|
||||
/**
|
||||
* Function Get3DConfigDir
|
||||
* returns the current 3D configuration directory on
|
||||
* success, otherwise it returns wxEmptyString. If the
|
||||
* directory was not previously set via Set3DConfigDir()
|
||||
* then a default is used which is based on kicad's
|
||||
* configuration directory code as of September 2015.
|
||||
*/
|
||||
wxString Get3DConfigDir( bool createDefault = false );
|
||||
|
||||
/**
|
||||
* Function SetProjectDir
|
||||
* sets the current project's working directory; this
|
||||
* affects the model search path
|
||||
*/
|
||||
bool SetProjectDir( const wxString& aProjDir );
|
||||
|
||||
/**
|
||||
* Function SetProgramBase
|
||||
* sets the filename resolver's pointer to the application's
|
||||
* PGM_BASE instance; the pointer is used to extract the
|
||||
* local env vars.
|
||||
*/
|
||||
void SetProgramBase( PGM_BASE* aBase );
|
||||
|
||||
/**
|
||||
* Function GetProjectDir
|
||||
* returns the current project's working directory
|
||||
*/
|
||||
wxString GetProjectDir( void );
|
||||
|
||||
/**
|
||||
* Function Load
|
||||
* attempts to load the scene data for a model; it will consult the
|
||||
* internal cache list and load from cache if possible before invoking
|
||||
* the load() function of the available plugins.
|
||||
*
|
||||
* @param aModelFile [in] is the partial or full path to the model to be loaded
|
||||
* @return true if the model was successfully loaded, otherwise false.
|
||||
* The model may fail to load if, for example, the plugin does not
|
||||
* support rendering of the 3D model.
|
||||
*/
|
||||
SCENEGRAPH* Load( const wxString& aModelFile );
|
||||
|
||||
FILENAME_RESOLVER* GetResolver( void );
|
||||
|
||||
/**
|
||||
* Function GetFileFilters
|
||||
* returns the list of file filters retrieved from the plugins;
|
||||
* this will contain at least the default "All Files (*.*)|*.*"
|
||||
*
|
||||
* @return a pointer to the filter list
|
||||
*/
|
||||
std::list< wxString > const* GetFileFilters( void ) const;
|
||||
|
||||
/**
|
||||
* Function FlushCache
|
||||
* frees all data in the cache and by default closes all plugins
|
||||
*/
|
||||
void FlushCache( bool closePlugins = true );
|
||||
|
||||
/**
|
||||
* Function ClosePlugins
|
||||
* unloads plugins to free memory
|
||||
*/
|
||||
void ClosePlugins( void );
|
||||
|
||||
/**
|
||||
* Function GetModel
|
||||
* attempts to load the scene data for a model and to translate it
|
||||
* into an S3D_MODEL structure for display by a renderer
|
||||
*
|
||||
* @param aModelFileName is the full path to the model to be loaded
|
||||
* @return is a pointer to the render data or NULL if not available
|
||||
*/
|
||||
S3DMODEL* GetModel( const wxString& aModelFileName );
|
||||
|
||||
wxString GetModelHash( const wxString& aModelFileName );
|
||||
};
|
||||
|
||||
#endif // CACHE_3D_H
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <common.h>
|
||||
#include <pgm_base.h>
|
||||
#include "3d_cache_wrapper.h"
|
||||
|
||||
static wxCriticalSection lock3D_wrapper;
|
||||
|
||||
CACHE_WRAPPER::CACHE_WRAPPER()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
CACHE_WRAPPER::~CACHE_WRAPPER()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
S3D_CACHE* PROJECT::Get3DCacheManager( bool updateProjDir )
|
||||
{
|
||||
wxCriticalSectionLocker lock( lock3D_wrapper );
|
||||
CACHE_WRAPPER* cw = (CACHE_WRAPPER*) GetElem( ELEM_3DCACHE );
|
||||
S3D_CACHE* cache = dynamic_cast<S3D_CACHE*>( cw );
|
||||
|
||||
// check that we get the expected type of object or NULL
|
||||
wxASSERT( !cw || cache );
|
||||
|
||||
if( !cw )
|
||||
{
|
||||
cw = new CACHE_WRAPPER;
|
||||
cache = dynamic_cast<S3D_CACHE*>( cw );
|
||||
|
||||
wxFileName cfgpath;
|
||||
cfgpath.AssignDir( GetKicadConfigPath() );
|
||||
cfgpath.AppendDir( wxT( "3d" ) );
|
||||
cache->SetProgramBase( &Pgm() );
|
||||
cache->Set3DConfigDir( cfgpath.GetFullPath() );
|
||||
SetElem( ELEM_3DCACHE, cw );
|
||||
updateProjDir = true;
|
||||
}
|
||||
|
||||
if( updateProjDir )
|
||||
cache->SetProjectDir( GetProjectPath() );
|
||||
|
||||
return cache;
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef CACHE_WRAPPER_3D_H
|
||||
#define CACHE_WRAPPER_3D_H
|
||||
|
||||
#include <project.h>
|
||||
#include "3d_cache.h"
|
||||
|
||||
class CACHE_WRAPPER : public S3D_CACHE, public PROJECT::_ELEM
|
||||
{
|
||||
public:
|
||||
KICAD_T Type() override { return CACHE_WRAPPER_T; }
|
||||
|
||||
CACHE_WRAPPER();
|
||||
virtual ~CACHE_WRAPPER();
|
||||
};
|
||||
|
||||
#endif // CACHE_WRAPPER_3D_H
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
|
||||
* Copyright (C) 2004 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_info.h
|
||||
* defines the basic data associated with a single 3D model.
|
||||
*/
|
||||
|
||||
#ifndef INFO_3D_H
|
||||
#define INFO_3D_H
|
||||
|
||||
#include <wx/string.h>
|
||||
#include <plugins/3dapi/sg_base.h>
|
||||
|
||||
class MODULE_3D_SETTINGS;
|
||||
|
||||
struct S3D_INFO
|
||||
{
|
||||
S3D_INFO();
|
||||
S3D_INFO( const MODULE_3D_SETTINGS& aModel );
|
||||
|
||||
SGPOINT m_Scale; ///< scaling factors for the 3D footprint shape
|
||||
SGPOINT m_Rotation; ///< an X,Y,Z rotation (unit = degrees) for the 3D shape
|
||||
SGPOINT m_Offset; ///< an offset (unit = inch) for the 3D shape
|
||||
wxString m_Filename; ///< The 3D shape filename in 3D library
|
||||
};
|
||||
|
||||
#endif // INFO_3D_H
|
||||
@@ -1,584 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <utility>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include <wx/config.h>
|
||||
#include <wx/dir.h>
|
||||
#include <wx/dynlib.h>
|
||||
#include <wx/filename.h>
|
||||
#include <wx/log.h>
|
||||
#include <wx/stdpaths.h>
|
||||
#include <wx/string.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "pgm_base.h"
|
||||
#include "3d_plugin_dir.h"
|
||||
#include "3d_plugin_manager.h"
|
||||
#include "plugins/3d/3d_plugin.h"
|
||||
#include "3d_cache/sg/scenegraph.h"
|
||||
#include "plugins/ldr/3d/pluginldr3D.h"
|
||||
|
||||
#define MASK_3D_PLUGINMGR "3D_PLUGIN_MANAGER"
|
||||
|
||||
|
||||
S3D_PLUGIN_MANAGER::S3D_PLUGIN_MANAGER()
|
||||
{
|
||||
// create the initial file filter list entry
|
||||
m_FileFilters.push_back( _( "All Files (*.*)|*.*" ) );
|
||||
|
||||
// discover and load plugins
|
||||
loadPlugins();
|
||||
|
||||
#ifdef DEBUG
|
||||
if( !m_ExtMap.empty() )
|
||||
{
|
||||
std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* >::const_iterator sM = m_ExtMap.begin();
|
||||
std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* >::const_iterator eM = m_ExtMap.end();
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " * Extension [plugin name]:\n" );
|
||||
|
||||
while( sM != eM )
|
||||
{
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " + '%s' [%s]\n", sM->first.GetData(),
|
||||
sM->second->GetKicadPluginName() );
|
||||
++sM;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " * No plugins available\n" );
|
||||
}
|
||||
|
||||
|
||||
if( !m_FileFilters.empty() )
|
||||
{
|
||||
/// list of file filters
|
||||
std::list< wxString >::const_iterator sFF = m_FileFilters.begin();
|
||||
std::list< wxString >::const_iterator eFF = m_FileFilters.end();
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " * File filters:\n" );
|
||||
|
||||
while( sFF != eFF )
|
||||
{
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " + '%s'\n", (*sFF).GetData() );
|
||||
++sFF;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " * No file filters available\n" );
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
S3D_PLUGIN_MANAGER::~S3D_PLUGIN_MANAGER()
|
||||
{
|
||||
std::list< KICAD_PLUGIN_LDR_3D* >::iterator sP = m_Plugins.begin();
|
||||
std::list< KICAD_PLUGIN_LDR_3D* >::iterator eP = m_Plugins.end();
|
||||
|
||||
while( sP != eP )
|
||||
{
|
||||
(*sP)->Close();
|
||||
delete *sP;
|
||||
++sP;
|
||||
}
|
||||
|
||||
m_Plugins.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D_PLUGIN_MANAGER::loadPlugins( void )
|
||||
{
|
||||
std::list< wxString > searchpaths;
|
||||
std::list< wxString > pluginlist;
|
||||
wxFileName fn;
|
||||
|
||||
#ifndef __WXMAC__
|
||||
|
||||
#ifdef DEBUG
|
||||
// set up to work from the build directory
|
||||
fn.Assign( wxStandardPaths::Get().GetExecutablePath() );
|
||||
fn.AppendDir( wxT("..") );
|
||||
fn.AppendDir( wxT("plugins") );
|
||||
fn.AppendDir( wxT("3d") );
|
||||
|
||||
std::string testpath = std::string( fn.GetPathWithSep().ToUTF8() );
|
||||
checkPluginPath( testpath, searchpaths );
|
||||
|
||||
// add subdirectories too
|
||||
wxDir debugPluginDir;
|
||||
wxString subdir;
|
||||
|
||||
debugPluginDir.Open( testpath );
|
||||
|
||||
if( debugPluginDir.IsOpened() &&
|
||||
debugPluginDir.GetFirst( &subdir, wxEmptyString, wxDIR_DIRS ) )
|
||||
{
|
||||
checkPluginPath( testpath + subdir, searchpaths );
|
||||
|
||||
while( debugPluginDir.GetNext( &subdir ) )
|
||||
checkPluginPath( testpath + subdir, searchpaths );
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
// PLUGINDIR = CMAKE_INSTALL_FULL_LIBDIR path is the absolute path
|
||||
// corresponding to the install path used for constructing KICAD_USER_PLUGIN
|
||||
|
||||
wxString tfname = wxString::FromUTF8Unchecked( PLUGINDIR );
|
||||
fn.Assign( tfname, "");
|
||||
fn.AppendDir( "kicad" );
|
||||
#else
|
||||
// on windows the plugins directory is within the executable's directory
|
||||
fn.Assign( wxStandardPaths::Get().GetExecutablePath() );
|
||||
#endif
|
||||
|
||||
fn.AppendDir( wxT( "plugins" ) );
|
||||
fn.AppendDir( wxT( "3d" ) );
|
||||
|
||||
// checks plugin directory relative to executable path
|
||||
checkPluginPath( std::string( fn.GetPathWithSep().ToUTF8() ), searchpaths );
|
||||
|
||||
// check for per-user third party plugins
|
||||
// note: GetUserDataDir() gives '.pcbnew' rather than '.kicad' since it uses the exe name;
|
||||
fn.Assign( wxStandardPaths::Get().GetUserDataDir(), "" );
|
||||
fn.RemoveLastDir();
|
||||
#ifdef _WIN32
|
||||
fn.AppendDir( wxT( "kicad" ) );
|
||||
#else
|
||||
fn.AppendDir( wxT( ".kicad" ) );
|
||||
#endif
|
||||
fn.AppendDir( wxT( "plugins" ) );
|
||||
fn.AppendDir( wxT( "3d" ) );
|
||||
checkPluginPath( fn.GetPathWithSep(), searchpaths );
|
||||
|
||||
#else
|
||||
|
||||
// Search path on OS X is
|
||||
// (1) User ~/Library/Application Support/kicad/PlugIns/3d
|
||||
checkPluginPath( GetOSXKicadUserDataDir() + wxT( "/PlugIns/3d" ), searchpaths );
|
||||
// (2) Machine /Library/Application Support/kicad/PlugIns/3d
|
||||
checkPluginPath( GetOSXKicadMachineDataDir() + wxT( "/PlugIns/3d" ), searchpaths );
|
||||
// (3) Bundle kicad.app/Contents/PlugIns/3d
|
||||
fn.Assign( Pgm().GetExecutablePath() );
|
||||
fn.AppendDir( wxT( "Contents" ) );
|
||||
fn.AppendDir( wxT( "PlugIns" ) );
|
||||
fn.AppendDir( wxT( "3d" ) );
|
||||
checkPluginPath( fn.GetPathWithSep(), searchpaths );
|
||||
|
||||
#endif
|
||||
|
||||
std::list< wxString >::iterator sPL = searchpaths.begin();
|
||||
std::list< wxString >::iterator ePL = searchpaths.end();
|
||||
|
||||
while( sPL != ePL )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << ":\n";
|
||||
ostr << " * [DEBUG] searching path: '" << (*sPL).ToUTF8() << "'";
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
listPlugins( *sPL, pluginlist );
|
||||
++sPL;
|
||||
}
|
||||
|
||||
if( pluginlist.empty() )
|
||||
return;
|
||||
|
||||
sPL = pluginlist.begin();
|
||||
ePL = pluginlist.end();
|
||||
|
||||
while( sPL != ePL )
|
||||
{
|
||||
KICAD_PLUGIN_LDR_3D* pp = new KICAD_PLUGIN_LDR_3D;
|
||||
|
||||
if( pp->Open( sPL->ToUTF8() ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << ":\n";
|
||||
ostr << "* [DEBUG] adding plugin";
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
m_Plugins.push_back( pp );
|
||||
int nf = pp->GetNFilters();
|
||||
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] adding " << nf << " filters";
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
for( int i = 0; i < nf; ++i )
|
||||
{
|
||||
char const* cp = pp->GetFileFilter( i );
|
||||
|
||||
if( cp )
|
||||
addFilterString( wxString::FromUTF8Unchecked( cp ) );
|
||||
}
|
||||
|
||||
addExtensionMap( pp );
|
||||
|
||||
// close the loaded library
|
||||
pp->Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << ":\n";
|
||||
ostr << "* [DEBUG] deleting plugin";
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
delete pp;
|
||||
}
|
||||
|
||||
++sPL;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << ":\n";
|
||||
ostr << "* [DEBUG] plugins loaded";
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D_PLUGIN_MANAGER::listPlugins( const wxString& aPath,
|
||||
std::list< wxString >& aPluginList )
|
||||
{
|
||||
// list potential plugins given a search path
|
||||
|
||||
wxString nameFilter; // filter for user-loadable libraries (aka modules)
|
||||
wxString lName; // stores name of enumerated files
|
||||
wxString fName; // full name of file
|
||||
wxDir wd;
|
||||
wd.Open( aPath );
|
||||
|
||||
if( !wd.IsOpened() )
|
||||
return;
|
||||
|
||||
nameFilter = wxT( "*" );
|
||||
|
||||
#ifndef __WXMAC__
|
||||
nameFilter.Append( wxDynamicLibrary::GetDllExt( wxDL_MODULE ) );
|
||||
#else
|
||||
// wxDynamicLibrary::GetDllExt( wxDL_MODULE ) will return ".bundle" on OS X.
|
||||
// This might be correct, but cmake builds a ".so" for a library MODULE.
|
||||
// Per definition a loadable "xxx.bundle" is similar to an "xxx.app" app
|
||||
// bundle being a folder with some special content in it. We obviously don't
|
||||
// want to have that here for our loadable module, so just use ".so".
|
||||
nameFilter.Append( ".so" );
|
||||
#endif
|
||||
|
||||
wxString lp = wd.GetNameWithSep();
|
||||
|
||||
if( wd.GetFirst( &lName, nameFilter, wxDIR_FILES ) )
|
||||
{
|
||||
fName = lp + lName;
|
||||
checkPluginName( fName, aPluginList );
|
||||
|
||||
while( wd.GetNext( &lName ) )
|
||||
{
|
||||
fName = lp + lName;
|
||||
checkPluginName( fName, aPluginList );
|
||||
}
|
||||
}
|
||||
|
||||
wd.Close();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D_PLUGIN_MANAGER::checkPluginName( const wxString& aPath,
|
||||
std::list< wxString >& aPluginList )
|
||||
{
|
||||
// check the existence of a plugin name and add it to the list
|
||||
|
||||
if( aPath.empty() || !wxFileName::FileExists( aPath ) )
|
||||
return;
|
||||
|
||||
wxFileName path;
|
||||
|
||||
if( aPath.StartsWith( "${" ) || aPath.StartsWith( "$(" ) )
|
||||
path.Assign( ExpandEnvVarSubstitutions( aPath ) );
|
||||
else
|
||||
path.Assign( aPath );
|
||||
|
||||
path.Normalize();
|
||||
|
||||
// determine if the path is already in the list
|
||||
wxString wxpath = path.GetFullPath();
|
||||
std::list< wxString >::iterator bl = aPluginList.begin();
|
||||
std::list< wxString >::iterator el = aPluginList.end();
|
||||
|
||||
while( bl != el )
|
||||
{
|
||||
if( 0 == (*bl).Cmp( wxpath ) )
|
||||
return;
|
||||
|
||||
++bl;
|
||||
}
|
||||
|
||||
aPluginList.push_back( wxpath );
|
||||
|
||||
#ifdef DEBUG
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " * [INFO] found 3D plugin '%s'\n",
|
||||
wxpath.GetData() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D_PLUGIN_MANAGER::checkPluginPath( const wxString& aPath,
|
||||
std::list< wxString >& aSearchList )
|
||||
{
|
||||
// check the existence of a path and add it to the path search list
|
||||
if( aPath.empty() )
|
||||
return;
|
||||
|
||||
#ifdef DEBUG
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " * [INFO] checking for 3D plugins in '%s'\n",
|
||||
aPath.GetData() );
|
||||
#endif
|
||||
|
||||
wxFileName path;
|
||||
|
||||
if( aPath.StartsWith( "${" ) || aPath.StartsWith( "$(" ) )
|
||||
path.Assign( ExpandEnvVarSubstitutions( aPath ), "" );
|
||||
else
|
||||
path.Assign( aPath, "" );
|
||||
|
||||
path.Normalize();
|
||||
|
||||
if( !wxFileName::DirExists( path.GetFullPath() ) )
|
||||
return;
|
||||
|
||||
// determine if the directory is already in the list
|
||||
wxString wxpath = path.GetFullPath();
|
||||
std::list< wxString >::iterator bl = aSearchList.begin();
|
||||
std::list< wxString >::iterator el = aSearchList.end();
|
||||
|
||||
while( bl != el )
|
||||
{
|
||||
if( 0 == (*bl).Cmp( wxpath ) )
|
||||
return;
|
||||
|
||||
++bl;
|
||||
}
|
||||
|
||||
aSearchList.push_back( wxpath );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D_PLUGIN_MANAGER::addFilterString( const wxString& aFilterString )
|
||||
{
|
||||
// add an entry to the file filter list
|
||||
if( aFilterString.empty() )
|
||||
return;
|
||||
|
||||
std::list< wxString >::iterator sFF = m_FileFilters.begin();
|
||||
std::list< wxString >::iterator eFF = m_FileFilters.end();
|
||||
|
||||
while( sFF != eFF )
|
||||
{
|
||||
if( 0 == (*sFF).Cmp( aFilterString ) )
|
||||
return;
|
||||
|
||||
++sFF;
|
||||
}
|
||||
|
||||
m_FileFilters.push_back( aFilterString );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D_PLUGIN_MANAGER::addExtensionMap( KICAD_PLUGIN_LDR_3D* aPlugin )
|
||||
{
|
||||
// add entries to the extension map
|
||||
if( NULL == aPlugin )
|
||||
return;
|
||||
|
||||
int nExt = aPlugin->GetNExtensions();
|
||||
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] adding " << nExt << " extensions";
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
for( int i = 0; i < nExt; ++i )
|
||||
{
|
||||
char const* cp = aPlugin->GetModelExtension( i );
|
||||
wxString ws;
|
||||
|
||||
if( cp )
|
||||
ws = wxString::FromUTF8Unchecked( cp );
|
||||
|
||||
if( !ws.empty() )
|
||||
{
|
||||
m_ExtMap.insert( std::pair< const wxString, KICAD_PLUGIN_LDR_3D* >( ws, aPlugin ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
std::list< wxString > const* S3D_PLUGIN_MANAGER::GetFileFilters( void ) const
|
||||
{
|
||||
return &m_FileFilters;
|
||||
}
|
||||
|
||||
|
||||
SCENEGRAPH* S3D_PLUGIN_MANAGER::Load3DModel( const wxString& aFileName, std::string& aPluginInfo )
|
||||
{
|
||||
wxFileName raw( aFileName );
|
||||
wxString ext = raw.GetExt();
|
||||
|
||||
#ifdef _WIN32
|
||||
// note: plugins only have a lowercase filter within Windows; including an uppercase
|
||||
// filter will result in duplicate file entries and should be avoided.
|
||||
ext.LowerCase();
|
||||
#endif
|
||||
|
||||
std::pair < std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* >::iterator,
|
||||
std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* >::iterator > items;
|
||||
|
||||
items = m_ExtMap.equal_range( ext );
|
||||
std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* >::iterator sL = items.first;
|
||||
|
||||
while( sL != items.second )
|
||||
{
|
||||
if( sL->second->CanRender() )
|
||||
{
|
||||
SCENEGRAPH* sp = sL->second->Load( aFileName.ToUTF8() );
|
||||
|
||||
if( NULL != sp )
|
||||
{
|
||||
sL->second->GetPluginInfo( aPluginInfo );
|
||||
return sp;
|
||||
}
|
||||
}
|
||||
|
||||
++sL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void S3D_PLUGIN_MANAGER::ClosePlugins( void )
|
||||
{
|
||||
std::list< KICAD_PLUGIN_LDR_3D* >::iterator sP = m_Plugins.begin();
|
||||
std::list< KICAD_PLUGIN_LDR_3D* >::iterator eP = m_Plugins.end();
|
||||
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] closing " << m_Plugins.size() << " plugins";
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
while( sP != eP )
|
||||
{
|
||||
(*sP)->Close();
|
||||
++sP;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool S3D_PLUGIN_MANAGER::CheckTag( const char* aTag )
|
||||
{
|
||||
if( NULL == aTag || aTag[0] == 0 || m_Plugins.empty() )
|
||||
return false;
|
||||
|
||||
std::string tname = aTag;
|
||||
std::string pname; // plugin name
|
||||
|
||||
size_t cpos = tname.find( ':' );
|
||||
|
||||
// if there is no colon or plugin name then the tag is bad
|
||||
if( cpos == std::string::npos || cpos == 0 )
|
||||
return false;
|
||||
|
||||
pname = tname.substr( 0, cpos );
|
||||
std::string ptag; // tag from the plugin
|
||||
|
||||
std::list< KICAD_PLUGIN_LDR_3D* >::iterator pS = m_Plugins.begin();
|
||||
std::list< KICAD_PLUGIN_LDR_3D* >::iterator pE = m_Plugins.end();
|
||||
|
||||
while( pS != pE )
|
||||
{
|
||||
ptag.clear();
|
||||
(*pS)->GetPluginInfo( ptag );
|
||||
|
||||
// if the plugin name matches then the version
|
||||
// must also match
|
||||
if( !ptag.compare( 0, pname.size(), pname ) )
|
||||
{
|
||||
if( ptag.compare( tname ) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
++pS;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_plugin_manager.h
|
||||
* manages 3D model plugins
|
||||
*/
|
||||
|
||||
#ifndef PLUGIN_MANAGER_3D_H
|
||||
#define PLUGIN_MANAGER_3D_H
|
||||
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <wx/string.h>
|
||||
|
||||
class wxWindow;
|
||||
class KICAD_PLUGIN_LDR_3D;
|
||||
class SCENEGRAPH;
|
||||
|
||||
class S3D_PLUGIN_MANAGER
|
||||
{
|
||||
private:
|
||||
/// list of discovered plugins
|
||||
std::list< KICAD_PLUGIN_LDR_3D* > m_Plugins;
|
||||
|
||||
/// mapping of extensions to available plugins
|
||||
std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* > m_ExtMap;
|
||||
|
||||
/// list of file filters
|
||||
std::list< wxString > m_FileFilters;
|
||||
|
||||
/// load plugins
|
||||
void loadPlugins( void );
|
||||
|
||||
/// list potential plugins
|
||||
void listPlugins( const wxString& aPath, std::list< wxString >& aPluginList );
|
||||
|
||||
/// check the existence of a plugin name and add it to the list
|
||||
void checkPluginName( const wxString& aPath, std::list< wxString >& aPluginList );
|
||||
|
||||
/// check the existence of a path and add it to the path search list
|
||||
void checkPluginPath( const wxString& aPath, std::list< wxString >& aSearchList );
|
||||
|
||||
/// add an entry to the file filter list
|
||||
void addFilterString( const wxString& aFilterString );
|
||||
|
||||
/// add entries to the extension map
|
||||
void addExtensionMap( KICAD_PLUGIN_LDR_3D* aPlugin );
|
||||
|
||||
public:
|
||||
S3D_PLUGIN_MANAGER();
|
||||
virtual ~S3D_PLUGIN_MANAGER();
|
||||
|
||||
/**
|
||||
* Function GetFileFilters
|
||||
* returns the list of file filters; this will contain at least
|
||||
* the default "All Files (*.*)|*.*" and the file filters supported
|
||||
* by any available plugins
|
||||
*
|
||||
* @return a pointer to the internal filter list
|
||||
*/
|
||||
std::list< wxString > const* GetFileFilters( void ) const;
|
||||
|
||||
SCENEGRAPH* Load3DModel( const wxString& aFileName, std::string& aPluginInfo );
|
||||
|
||||
/**
|
||||
* Function ClosePlugins
|
||||
* iterates through all discovered plugins and closes them to
|
||||
* reclaim memory. The individual plugins will be automatically
|
||||
* reloaded as calls are made to load specific models.
|
||||
*/
|
||||
void ClosePlugins( void );
|
||||
|
||||
/**
|
||||
* Function CheckTag
|
||||
* checks the given tag and returns true if the plugin named in the tag
|
||||
* is not loaded or the plugin is loaded and the version matches
|
||||
*/
|
||||
bool CheckTag( const char* aTag );
|
||||
};
|
||||
|
||||
#endif // PLUGIN_MANAGER_3D_H
|
||||
@@ -1 +0,0 @@
|
||||
add_subdirectory( sg )
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <wx/filename.h>
|
||||
|
||||
#include "3d_info.h"
|
||||
#include "3d_cache.h"
|
||||
#include "plugins/3dapi/ifsg_api.h"
|
||||
#include "3d_cache_dialogs.h"
|
||||
#include "dialog_configure_paths.h"
|
||||
#include "dlg_select_3dmodel.h"
|
||||
|
||||
|
||||
bool S3D::Select3DModel( wxWindow* aParent, S3D_CACHE* aCache,
|
||||
wxString& prevModelSelectDir, int& prevModelWildcard, MODULE_3D_SETTINGS* aModel )
|
||||
{
|
||||
if( NULL == aModel )
|
||||
return false;
|
||||
|
||||
DLG_SELECT_3DMODEL* dm = new DLG_SELECT_3DMODEL( aParent, aCache, aModel,
|
||||
prevModelSelectDir, prevModelWildcard );
|
||||
|
||||
if( wxID_OK == dm->ShowModal() )
|
||||
{
|
||||
delete dm;
|
||||
return true;
|
||||
}
|
||||
|
||||
delete dm;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::Configure3DPaths( wxWindow* aParent, FILENAME_RESOLVER* aResolver )
|
||||
{
|
||||
DIALOG_CONFIGURE_PATHS dlg( aParent, aResolver );
|
||||
|
||||
return( dlg.ShowModal() == wxID_OK );
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef CACHE_DIALOGS_3D_H
|
||||
#define CACHE_DIALOGS_3D_H
|
||||
|
||||
#include <wx/window.h>
|
||||
|
||||
class S3D_CACHE;
|
||||
class FILENAME_RESOLVER;
|
||||
|
||||
namespace S3D
|
||||
{
|
||||
bool Select3DModel( wxWindow* aParent, S3D_CACHE* aCache,
|
||||
wxString& prevModelSelectDir, int& prevModelWildcard, MODULE_3D_SETTINGS* aModel );
|
||||
|
||||
bool Configure3DPaths( wxWindow* aParent, FILENAME_RESOLVER* aResolver );
|
||||
}
|
||||
|
||||
#endif // CACHE_DIALOGS_3D_H
|
||||
@@ -1,294 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2017-2018 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <set>
|
||||
#include "dlg_select_3dmodel.h"
|
||||
#include "project.h"
|
||||
#include "3d_cache/3d_info.h"
|
||||
#include "3d_cache/3d_cache.h"
|
||||
#include "3d_cache_dialogs.h"
|
||||
#include <3d_model_viewer/c3d_model_viewer.h>
|
||||
#include <common_ogl/cogl_att_list.h>
|
||||
#include <pcbnew/class_module.h>
|
||||
|
||||
#define ID_FILE_TREE ( wxID_LAST + 1 )
|
||||
#define ID_SET_DIR ( ID_FILE_TREE + 1 )
|
||||
#define ID_CFG_PATHS ( ID_SET_DIR + 1 )
|
||||
|
||||
|
||||
wxBEGIN_EVENT_TABLE( DLG_SELECT_3DMODEL, DIALOG_SHIM )
|
||||
EVT_DIRCTRL_SELECTIONCHANGED( ID_FILE_TREE, DLG_SELECT_3DMODEL::OnSelectionChanged )
|
||||
EVT_DIRCTRL_FILEACTIVATED( ID_FILE_TREE, DLG_SELECT_3DMODEL::OnFileActivated )
|
||||
EVT_CHOICE( ID_SET_DIR, DLG_SELECT_3DMODEL::SetRootDir )
|
||||
EVT_BUTTON( ID_CFG_PATHS, DLG_SELECT_3DMODEL::Cfg3DPaths )
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
|
||||
DLG_SELECT_3DMODEL::DLG_SELECT_3DMODEL( wxWindow* aParent, S3D_CACHE* aCacheManager,
|
||||
MODULE_3D_SETTINGS* aModelItem, wxString& prevModelSelectDir, int& prevModelWildcard ) :
|
||||
DIALOG_SHIM( aParent, wxID_ANY, _( "Select 3D Model" ), wxDefaultPosition,
|
||||
wxSize( 500,200 ), wxCAPTION | wxRESIZE_BORDER | wxCLOSE_BOX
|
||||
| wxMINIMIZE_BOX | wxMAXIMIZE_BOX | wxSYSTEM_MENU ),
|
||||
m_model( aModelItem ), m_cache( aCacheManager ), m_previousDir( prevModelSelectDir ),
|
||||
m_previousFilterIndex( prevModelWildcard )
|
||||
{
|
||||
SetSizeHints( wxSize( 500,200 ), wxDefaultSize );
|
||||
|
||||
if( NULL != m_cache )
|
||||
m_resolver = m_cache->GetResolver();
|
||||
else
|
||||
m_resolver = NULL;
|
||||
|
||||
wxBoxSizer* bSizer0 = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxBoxSizer* bSizer1 = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
wxBoxSizer* bSizer2 = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
// set to NULL to avoid segfaults when m_FileTree is instantiated
|
||||
// and wxGenericDirCtrl events are posted
|
||||
m_modelViewer = NULL;
|
||||
dirChoices = NULL;
|
||||
|
||||
m_FileTree = new wxGenericDirCtrl( this, ID_FILE_TREE, prevModelSelectDir, wxDefaultPosition,
|
||||
wxSize( 300,100 ), wxDIRCTRL_3D_INTERNAL | wxDIRCTRL_EDIT_LABELS
|
||||
| wxDIRCTRL_SELECT_FIRST | wxDIRCTRL_SHOW_FILTERS | wxBORDER_SIMPLE, wxEmptyString, 0 );
|
||||
|
||||
|
||||
m_FileTree->ShowHidden( false );
|
||||
m_FileTree->SetMinSize( wxSize( 300, 400 ) );
|
||||
m_FileTree->SetLabel( wxT( "3D_MODEL_SELECTOR" ) );
|
||||
|
||||
bSizer2->Add( m_FileTree, 1, wxEXPAND | wxALL, 5 );
|
||||
bSizer1->Add( bSizer2, 3, wxEXPAND, 5 );
|
||||
|
||||
m_modelViewer = new C3D_MODEL_VIEWER( this, COGL_ATT_LIST::GetAttributesList( true ), m_cache );
|
||||
m_modelViewer->SetMinSize( wxSize( 500, 400 ) );
|
||||
|
||||
bSizer1->Add( m_modelViewer, 5, wxEXPAND | wxALL | wxCENTER, 5 );
|
||||
|
||||
// create the filter list
|
||||
if( NULL != m_cache )
|
||||
{
|
||||
std::list< wxString > const* fl = m_cache->GetFileFilters();
|
||||
std::list< wxString >::const_iterator sL = fl->begin();
|
||||
std::list< wxString >::const_iterator eL = fl->end();
|
||||
wxString filter;
|
||||
|
||||
while( sL != eL )
|
||||
{
|
||||
filter.Append( *sL );
|
||||
|
||||
++sL;
|
||||
|
||||
if( sL != eL )
|
||||
filter.Append( wxT( "|" ) );
|
||||
}
|
||||
|
||||
if( !filter.empty() )
|
||||
m_FileTree->SetFilter( filter );
|
||||
else
|
||||
m_FileTree->SetFilter( wxFileSelectorDefaultWildcardStr );
|
||||
|
||||
if( prevModelWildcard >= 0 && prevModelWildcard < (int)fl->size() )
|
||||
m_FileTree->SetFilterIndex( prevModelWildcard );
|
||||
else
|
||||
{
|
||||
prevModelWildcard = 0;
|
||||
m_FileTree->SetFilterIndex( 0 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_FileTree->SetFilter( wxFileSelectorDefaultWildcardStr );
|
||||
prevModelWildcard = 0;
|
||||
m_FileTree->SetFilterIndex( 0 );
|
||||
}
|
||||
|
||||
// Add the path choice box and config button
|
||||
wxBoxSizer* hboxDirChoice = new wxBoxSizer( wxHORIZONTAL );
|
||||
dirChoices = new wxChoice( this, ID_SET_DIR, wxDefaultPosition, wxSize( 320, 20 ) );
|
||||
dirChoices->SetMinSize( wxSize( 320, 12 ) );
|
||||
|
||||
wxStaticText* stDirChoice = new wxStaticText( this, -1, _( "Paths:" ) );
|
||||
wxButton* cfgPaths = new wxButton( this, ID_CFG_PATHS, _( "Configure Paths" ) );
|
||||
hboxDirChoice->Add( stDirChoice, 0, wxALL | wxCENTER, 5 );
|
||||
hboxDirChoice->Add( dirChoices, 1, wxEXPAND | wxALL, 5 );
|
||||
hboxDirChoice->Add( cfgPaths, 0, wxALL, 5 );
|
||||
|
||||
wxButton* btn_OK = new wxButton( this, wxID_OK, _( "OK" ) );
|
||||
wxButton* btn_Cancel = new wxButton( this, wxID_CANCEL, _( "Cancel" ) );
|
||||
|
||||
wxStdDialogButtonSizer* hSizer1 = new wxStdDialogButtonSizer();
|
||||
hSizer1->AddButton( btn_OK );
|
||||
hSizer1->AddButton( btn_Cancel );
|
||||
hSizer1->Realize();
|
||||
|
||||
bSizer0->Add( bSizer1, 1, wxALL | wxEXPAND, 5 );
|
||||
bSizer0->Add( hboxDirChoice, 0, wxALL | wxEXPAND, 5 );
|
||||
bSizer0->Add( hSizer1, 0, wxALL | wxEXPAND, 5 );
|
||||
|
||||
updateDirChoiceList();
|
||||
|
||||
SetSizerAndFit( bSizer0 );
|
||||
Layout();
|
||||
Centre( wxBOTH );
|
||||
|
||||
m_modelViewer->Refresh();
|
||||
m_modelViewer->SetFocus();
|
||||
}
|
||||
|
||||
|
||||
bool DLG_SELECT_3DMODEL::TransferDataFromWindow()
|
||||
{
|
||||
if( NULL == m_model || NULL == m_FileTree )
|
||||
return true;
|
||||
|
||||
m_model->m_Scale.x = 1.0;
|
||||
m_model->m_Scale.y = 1.0;
|
||||
m_model->m_Scale.z = 1.0;
|
||||
|
||||
m_model->m_Rotation.x = 0.0;
|
||||
m_model->m_Rotation.y = 0.0;
|
||||
m_model->m_Rotation.z = 0.0;
|
||||
|
||||
m_model->m_Offset = m_model->m_Rotation;
|
||||
m_model->m_Filename.clear();
|
||||
|
||||
wxString name = m_FileTree->GetFilePath();
|
||||
|
||||
if( name.empty() )
|
||||
return true;
|
||||
|
||||
m_previousDir = m_FileTree->GetPath();
|
||||
m_previousFilterIndex = m_FileTree->GetFilterIndex();
|
||||
|
||||
// file selection mode: retrieve the filename and specify a
|
||||
// path relative to one of the config paths
|
||||
wxFileName fname = m_FileTree->GetFilePath();
|
||||
fname.Normalize();
|
||||
m_model->m_Filename = m_resolver->ShortenPath( fname.GetFullPath() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void DLG_SELECT_3DMODEL::OnSelectionChanged( wxTreeEvent& event )
|
||||
{
|
||||
if( m_modelViewer )
|
||||
m_modelViewer->Set3DModel( m_FileTree->GetFilePath() );
|
||||
|
||||
event.Skip();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void DLG_SELECT_3DMODEL::OnFileActivated( wxTreeEvent& event )
|
||||
{
|
||||
if( m_modelViewer )
|
||||
m_modelViewer->Set3DModel( m_FileTree->GetFilePath() );
|
||||
|
||||
event.Skip();
|
||||
SetEscapeId( wxID_OK );
|
||||
Close();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void DLG_SELECT_3DMODEL::SetRootDir( wxCommandEvent& event )
|
||||
{
|
||||
if( m_FileTree && dirChoices->GetSelection() > 0 )
|
||||
m_FileTree->SetPath( dirChoices->GetString( dirChoices->GetSelection() ) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void DLG_SELECT_3DMODEL::Cfg3DPaths( wxCommandEvent& event )
|
||||
{
|
||||
if( S3D::Configure3DPaths( this, m_resolver ) )
|
||||
updateDirChoiceList();
|
||||
}
|
||||
|
||||
|
||||
void DLG_SELECT_3DMODEL::updateDirChoiceList( void )
|
||||
{
|
||||
if( NULL == m_FileTree || NULL == m_resolver || NULL == dirChoices )
|
||||
return;
|
||||
|
||||
std::list< SEARCH_PATH > const* md = m_resolver->GetPaths();
|
||||
std::list< SEARCH_PATH >::const_iterator sL = md->begin();
|
||||
std::list< SEARCH_PATH >::const_iterator eL = md->end();
|
||||
std::set< wxString > cl;
|
||||
wxString prjDir;
|
||||
|
||||
// extract the current project dir
|
||||
if( sL != eL )
|
||||
{
|
||||
prjDir = sL->m_pathexp;
|
||||
++sL;
|
||||
}
|
||||
|
||||
while( sL != eL )
|
||||
{
|
||||
if( !sL->m_pathexp.empty() && sL->m_pathexp.compare( prjDir ) )
|
||||
cl.insert( sL->m_pathexp );
|
||||
|
||||
++sL;
|
||||
}
|
||||
|
||||
if( !cl.empty() )
|
||||
{
|
||||
unsigned int choice = 0;
|
||||
dirChoices->Clear();
|
||||
dirChoices->Append( "" ); //Insert a blank string at the beginning to allow selection
|
||||
|
||||
if( !prjDir.empty() )
|
||||
{
|
||||
dirChoices->Append( prjDir );
|
||||
|
||||
if( prjDir == m_FileTree->GetPath() )
|
||||
choice = 1;
|
||||
}
|
||||
|
||||
std::set< wxString >::const_iterator sI = cl.begin();
|
||||
std::set< wxString >::const_iterator eI = cl.end();
|
||||
|
||||
while( sI != eI )
|
||||
{
|
||||
if( *sI == m_FileTree->GetPath() )
|
||||
choice = dirChoices->GetCount();
|
||||
|
||||
dirChoices->Append( *sI );
|
||||
++sI;
|
||||
}
|
||||
|
||||
dirChoices->Select( choice );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2018 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file dlg_select_3dmodel.h
|
||||
* creates a dialog to select 3D model files
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DLG_SELECT_3DMODEL_H
|
||||
#define DLG_SELECT_3DMODEL_H
|
||||
|
||||
#include <wx/event.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/dialog.h>
|
||||
#include <wx/dirctrl.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/frame.h>
|
||||
|
||||
#include <dialog_shim.h>
|
||||
|
||||
class MODULE_3D_SETTINGS;
|
||||
class S3D_CACHE;
|
||||
class FILENAME_RESOLVER;
|
||||
class C3D_MODEL_VIEWER;
|
||||
|
||||
class DLG_SELECT_3DMODEL : public DIALOG_SHIM
|
||||
{
|
||||
private:
|
||||
MODULE_3D_SETTINGS* m_model; // data for the selected model
|
||||
S3D_CACHE* m_cache; // cache manager
|
||||
FILENAME_RESOLVER* m_resolver; // 3D filename resolver
|
||||
|
||||
wxString& m_previousDir;
|
||||
int& m_previousFilterIndex;
|
||||
|
||||
wxGenericDirCtrl* m_FileTree;
|
||||
C3D_MODEL_VIEWER* m_modelViewer;
|
||||
wxChoice* dirChoices;
|
||||
|
||||
void updateDirChoiceList( void );
|
||||
|
||||
public:
|
||||
DLG_SELECT_3DMODEL( wxWindow* aParent, S3D_CACHE* aCacheManager, MODULE_3D_SETTINGS* aModelItem,
|
||||
wxString& prevModelSelectDir, int& prevModelWildcard );
|
||||
|
||||
bool TransferDataFromWindow() override;
|
||||
void OnSelectionChanged( wxTreeEvent& event );
|
||||
void OnFileActivated( wxTreeEvent& event );
|
||||
void SetRootDir( wxCommandEvent& event );
|
||||
void Cfg3DPaths( wxCommandEvent& event );
|
||||
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
||||
#endif // DLG_SELECT_3DMODEL_H
|
||||
@@ -1,310 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Jun 5 2018)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "panel_prev_3d_base.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PANEL_PREV_3D_BASE::PANEL_PREV_3D_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style )
|
||||
{
|
||||
wxBoxSizer* bSizermain;
|
||||
bSizermain = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
wxBoxSizer* bSizerLeft;
|
||||
bSizerLeft = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxStaticBoxSizer* sbSizerScale;
|
||||
sbSizerScale = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Scale") ), wxVERTICAL );
|
||||
|
||||
wxFlexGridSizer* fgSizerScale;
|
||||
fgSizerScale = new wxFlexGridSizer( 0, 3, 0, 0 );
|
||||
fgSizerScale->SetFlexibleDirection( wxBOTH );
|
||||
fgSizerScale->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
m_staticText1 = new wxStaticText( sbSizerScale->GetStaticBox(), wxID_ANY, _("X:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText1->Wrap( -1 );
|
||||
fgSizerScale->Add( m_staticText1, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
xscale = new wxTextCtrl( sbSizerScale->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizerScale->Add( xscale, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
m_spinXscale = new wxSpinButton( sbSizerScale->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerScale->Add( m_spinXscale, 0, wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
m_staticText2 = new wxStaticText( sbSizerScale->GetStaticBox(), wxID_ANY, _("Y:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText2->Wrap( -1 );
|
||||
fgSizerScale->Add( m_staticText2, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
yscale = new wxTextCtrl( sbSizerScale->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizerScale->Add( yscale, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
m_spinYscale = new wxSpinButton( sbSizerScale->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerScale->Add( m_spinYscale, 0, wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
m_staticText3 = new wxStaticText( sbSizerScale->GetStaticBox(), wxID_ANY, _("Z:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText3->Wrap( -1 );
|
||||
fgSizerScale->Add( m_staticText3, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxLEFT, 5 );
|
||||
|
||||
zscale = new wxTextCtrl( sbSizerScale->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizerScale->Add( zscale, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxLEFT, 5 );
|
||||
|
||||
m_spinZscale = new wxSpinButton( sbSizerScale->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerScale->Add( m_spinZscale, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM, 5 );
|
||||
|
||||
|
||||
sbSizerScale->Add( fgSizerScale, 0, wxEXPAND|wxRIGHT|wxLEFT, 10 );
|
||||
|
||||
|
||||
bSizerLeft->Add( sbSizerScale, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
wxStaticBoxSizer* sbSizerRotation;
|
||||
sbSizerRotation = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Rotation") ), wxVERTICAL );
|
||||
|
||||
wxFlexGridSizer* fgSizerRotate;
|
||||
fgSizerRotate = new wxFlexGridSizer( 0, 3, 0, 0 );
|
||||
fgSizerRotate->SetFlexibleDirection( wxBOTH );
|
||||
fgSizerRotate->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
m_staticText11 = new wxStaticText( sbSizerRotation->GetStaticBox(), wxID_ANY, _("X:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText11->Wrap( -1 );
|
||||
fgSizerRotate->Add( m_staticText11, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
xrot = new wxTextCtrl( sbSizerRotation->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizerRotate->Add( xrot, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
m_spinXrot = new wxSpinButton( sbSizerRotation->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerRotate->Add( m_spinXrot, 0, wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
m_staticText21 = new wxStaticText( sbSizerRotation->GetStaticBox(), wxID_ANY, _("Y:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText21->Wrap( -1 );
|
||||
fgSizerRotate->Add( m_staticText21, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
yrot = new wxTextCtrl( sbSizerRotation->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizerRotate->Add( yrot, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
m_spinYrot = new wxSpinButton( sbSizerRotation->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerRotate->Add( m_spinYrot, 0, wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
m_staticText31 = new wxStaticText( sbSizerRotation->GetStaticBox(), wxID_ANY, _("Z:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText31->Wrap( -1 );
|
||||
fgSizerRotate->Add( m_staticText31, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxLEFT, 5 );
|
||||
|
||||
zrot = new wxTextCtrl( sbSizerRotation->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizerRotate->Add( zrot, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxLEFT, 5 );
|
||||
|
||||
m_spinZrot = new wxSpinButton( sbSizerRotation->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerRotate->Add( m_spinZrot, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM, 5 );
|
||||
|
||||
|
||||
sbSizerRotation->Add( fgSizerRotate, 0, wxEXPAND|wxRIGHT|wxLEFT, 10 );
|
||||
|
||||
|
||||
bSizerLeft->Add( sbSizerRotation, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
wxStaticBoxSizer* sbSizerOffset;
|
||||
sbSizerOffset = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Offset") ), wxVERTICAL );
|
||||
|
||||
wxFlexGridSizer* fgSizerOffset;
|
||||
fgSizerOffset = new wxFlexGridSizer( 0, 3, 0, 0 );
|
||||
fgSizerOffset->SetFlexibleDirection( wxBOTH );
|
||||
fgSizerOffset->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
m_staticText12 = new wxStaticText( sbSizerOffset->GetStaticBox(), wxID_ANY, _("X:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText12->Wrap( -1 );
|
||||
fgSizerOffset->Add( m_staticText12, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
xoff = new wxTextCtrl( sbSizerOffset->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizerOffset->Add( xoff, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
m_spinXoffset = new wxSpinButton( sbSizerOffset->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerOffset->Add( m_spinXoffset, 0, wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
m_staticText22 = new wxStaticText( sbSizerOffset->GetStaticBox(), wxID_ANY, _("Y:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText22->Wrap( -1 );
|
||||
fgSizerOffset->Add( m_staticText22, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
yoff = new wxTextCtrl( sbSizerOffset->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizerOffset->Add( yoff, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
m_spinYoffset = new wxSpinButton( sbSizerOffset->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerOffset->Add( m_spinYoffset, 0, wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
m_staticText32 = new wxStaticText( sbSizerOffset->GetStaticBox(), wxID_ANY, _("Z:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText32->Wrap( -1 );
|
||||
fgSizerOffset->Add( m_staticText32, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxLEFT, 5 );
|
||||
|
||||
zoff = new wxTextCtrl( sbSizerOffset->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizerOffset->Add( zoff, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxLEFT, 5 );
|
||||
|
||||
m_spinZoffset = new wxSpinButton( sbSizerOffset->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerOffset->Add( m_spinZoffset, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM, 5 );
|
||||
|
||||
|
||||
sbSizerOffset->Add( fgSizerOffset, 0, wxEXPAND|wxLEFT|wxRIGHT, 10 );
|
||||
|
||||
|
||||
bSizerLeft->Add( sbSizerOffset, 0, wxEXPAND|wxALL, 5 );
|
||||
|
||||
|
||||
bSizermain->Add( bSizerLeft, 0, 0, 5 );
|
||||
|
||||
wxBoxSizer* bSizerRight;
|
||||
bSizerRight = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxStaticText* staticPreviewLabel;
|
||||
staticPreviewLabel = new wxStaticText( this, wxID_ANY, _("Preview"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
staticPreviewLabel->Wrap( -1 );
|
||||
staticPreviewLabel->SetFont( wxFont( 11, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) );
|
||||
|
||||
bSizerRight->Add( staticPreviewLabel, 0, wxLEFT, 15 );
|
||||
|
||||
m_SizerPanelView = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
|
||||
bSizerRight->Add( m_SizerPanelView, 1, wxEXPAND|wxBOTTOM, 8 );
|
||||
|
||||
|
||||
bSizermain->Add( bSizerRight, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 4 );
|
||||
|
||||
wxBoxSizer* bSizer3DButtons;
|
||||
bSizer3DButtons = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
|
||||
bSizer3DButtons->Add( 0, 0, 0, wxEXPAND|wxTOP, 4 );
|
||||
|
||||
m_bpvISO = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW );
|
||||
m_bpvISO->SetToolTip( _("Change to isometric perspective") );
|
||||
|
||||
bSizer3DButtons->Add( m_bpvISO, 0, wxTOP|wxBOTTOM, 5 );
|
||||
|
||||
m_bpvLeft = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW );
|
||||
bSizer3DButtons->Add( m_bpvLeft, 0, 0, 5 );
|
||||
|
||||
m_bpvRight = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW );
|
||||
bSizer3DButtons->Add( m_bpvRight, 0, 0, 5 );
|
||||
|
||||
m_bpvFront = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW );
|
||||
bSizer3DButtons->Add( m_bpvFront, 0, 0, 5 );
|
||||
|
||||
m_bpvBack = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW );
|
||||
bSizer3DButtons->Add( m_bpvBack, 0, 0, 5 );
|
||||
|
||||
m_bpvTop = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW );
|
||||
bSizer3DButtons->Add( m_bpvTop, 0, 0, 5 );
|
||||
|
||||
m_bpvBottom = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW );
|
||||
bSizer3DButtons->Add( m_bpvBottom, 0, 0, 5 );
|
||||
|
||||
m_bpUpdate = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW );
|
||||
m_bpUpdate->SetToolTip( _("Reload board and 3D models") );
|
||||
|
||||
bSizer3DButtons->Add( m_bpUpdate, 0, wxTOP, 5 );
|
||||
|
||||
|
||||
bSizermain->Add( bSizer3DButtons, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
this->SetSizer( bSizermain );
|
||||
this->Layout();
|
||||
bSizermain->Fit( this );
|
||||
|
||||
// Connect Events
|
||||
xscale->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelScale ), NULL, this );
|
||||
xscale->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinXscale->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementScale ), NULL, this );
|
||||
m_spinXscale->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementScale ), NULL, this );
|
||||
yscale->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelScale ), NULL, this );
|
||||
yscale->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinYscale->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementScale ), NULL, this );
|
||||
m_spinYscale->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementScale ), NULL, this );
|
||||
zscale->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelScale ), NULL, this );
|
||||
zscale->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinZscale->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementScale ), NULL, this );
|
||||
m_spinZscale->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementScale ), NULL, this );
|
||||
xrot->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelRot ), NULL, this );
|
||||
xrot->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinXrot->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementRot ), NULL, this );
|
||||
m_spinXrot->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementRot ), NULL, this );
|
||||
yrot->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelRot ), NULL, this );
|
||||
yrot->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinYrot->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementRot ), NULL, this );
|
||||
m_spinYrot->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementRot ), NULL, this );
|
||||
zrot->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelRot ), NULL, this );
|
||||
zrot->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinZrot->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementRot ), NULL, this );
|
||||
m_spinZrot->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementRot ), NULL, this );
|
||||
xoff->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelOffset ), NULL, this );
|
||||
xoff->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinXoffset->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementOffset ), NULL, this );
|
||||
m_spinXoffset->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementOffset ), NULL, this );
|
||||
yoff->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelOffset ), NULL, this );
|
||||
yoff->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinYoffset->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementOffset ), NULL, this );
|
||||
m_spinYoffset->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementOffset ), NULL, this );
|
||||
zoff->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelOffset ), NULL, this );
|
||||
zoff->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinZoffset->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementOffset ), NULL, this );
|
||||
m_spinZoffset->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementOffset ), NULL, this );
|
||||
m_bpvISO->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DISO ), NULL, this );
|
||||
m_bpvLeft->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DLeft ), NULL, this );
|
||||
m_bpvRight->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DRight ), NULL, this );
|
||||
m_bpvFront->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DFront ), NULL, this );
|
||||
m_bpvBack->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DBack ), NULL, this );
|
||||
m_bpvTop->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DTop ), NULL, this );
|
||||
m_bpvBottom->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DBottom ), NULL, this );
|
||||
m_bpUpdate->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DUpdate ), NULL, this );
|
||||
}
|
||||
|
||||
PANEL_PREV_3D_BASE::~PANEL_PREV_3D_BASE()
|
||||
{
|
||||
// Disconnect Events
|
||||
xscale->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelScale ), NULL, this );
|
||||
xscale->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinXscale->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementScale ), NULL, this );
|
||||
m_spinXscale->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementScale ), NULL, this );
|
||||
yscale->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelScale ), NULL, this );
|
||||
yscale->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinYscale->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementScale ), NULL, this );
|
||||
m_spinYscale->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementScale ), NULL, this );
|
||||
zscale->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelScale ), NULL, this );
|
||||
zscale->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinZscale->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementScale ), NULL, this );
|
||||
m_spinZscale->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementScale ), NULL, this );
|
||||
xrot->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelRot ), NULL, this );
|
||||
xrot->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinXrot->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementRot ), NULL, this );
|
||||
m_spinXrot->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementRot ), NULL, this );
|
||||
yrot->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelRot ), NULL, this );
|
||||
yrot->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinYrot->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementRot ), NULL, this );
|
||||
m_spinYrot->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementRot ), NULL, this );
|
||||
zrot->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelRot ), NULL, this );
|
||||
zrot->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinZrot->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementRot ), NULL, this );
|
||||
m_spinZrot->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementRot ), NULL, this );
|
||||
xoff->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelOffset ), NULL, this );
|
||||
xoff->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinXoffset->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementOffset ), NULL, this );
|
||||
m_spinXoffset->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementOffset ), NULL, this );
|
||||
yoff->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelOffset ), NULL, this );
|
||||
yoff->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinYoffset->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementOffset ), NULL, this );
|
||||
m_spinYoffset->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementOffset ), NULL, this );
|
||||
zoff->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelOffset ), NULL, this );
|
||||
zoff->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinZoffset->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementOffset ), NULL, this );
|
||||
m_spinZoffset->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementOffset ), NULL, this );
|
||||
m_bpvISO->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DISO ), NULL, this );
|
||||
m_bpvLeft->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DLeft ), NULL, this );
|
||||
m_bpvRight->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DRight ), NULL, this );
|
||||
m_bpvFront->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DFront ), NULL, this );
|
||||
m_bpvBack->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DBack ), NULL, this );
|
||||
m_bpvTop->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DTop ), NULL, this );
|
||||
m_bpvBottom->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DBottom ), NULL, this );
|
||||
m_bpUpdate->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DUpdate ), NULL, this );
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,107 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Jun 5 2018)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __PANEL_PREV_3D_BASE_H__
|
||||
#define __PANEL_PREV_3D_BASE_H__
|
||||
|
||||
#include <wx/artprov.h>
|
||||
#include <wx/xrc/xmlres.h>
|
||||
#include <wx/intl.h>
|
||||
#include <wx/string.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <wx/font.h>
|
||||
#include <wx/colour.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/spinbutt.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/statbox.h>
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/icon.h>
|
||||
#include <wx/bmpbuttn.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/panel.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Class PANEL_PREV_3D_BASE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class PANEL_PREV_3D_BASE : public wxPanel
|
||||
{
|
||||
private:
|
||||
|
||||
protected:
|
||||
wxStaticText* m_staticText1;
|
||||
wxTextCtrl* xscale;
|
||||
wxSpinButton* m_spinXscale;
|
||||
wxStaticText* m_staticText2;
|
||||
wxTextCtrl* yscale;
|
||||
wxSpinButton* m_spinYscale;
|
||||
wxStaticText* m_staticText3;
|
||||
wxTextCtrl* zscale;
|
||||
wxSpinButton* m_spinZscale;
|
||||
wxStaticText* m_staticText11;
|
||||
wxTextCtrl* xrot;
|
||||
wxSpinButton* m_spinXrot;
|
||||
wxStaticText* m_staticText21;
|
||||
wxTextCtrl* yrot;
|
||||
wxSpinButton* m_spinYrot;
|
||||
wxStaticText* m_staticText31;
|
||||
wxTextCtrl* zrot;
|
||||
wxSpinButton* m_spinZrot;
|
||||
wxStaticText* m_staticText12;
|
||||
wxTextCtrl* xoff;
|
||||
wxSpinButton* m_spinXoffset;
|
||||
wxStaticText* m_staticText22;
|
||||
wxSpinButton* m_spinYoffset;
|
||||
wxStaticText* m_staticText32;
|
||||
wxTextCtrl* zoff;
|
||||
wxSpinButton* m_spinZoffset;
|
||||
wxBoxSizer* m_SizerPanelView;
|
||||
wxBitmapButton* m_bpvISO;
|
||||
wxBitmapButton* m_bpvLeft;
|
||||
wxBitmapButton* m_bpvRight;
|
||||
wxBitmapButton* m_bpvFront;
|
||||
wxBitmapButton* m_bpvBack;
|
||||
wxBitmapButton* m_bpvTop;
|
||||
wxBitmapButton* m_bpvBottom;
|
||||
wxBitmapButton* m_bpUpdate;
|
||||
|
||||
// Virtual event handlers, overide them in your derived class
|
||||
virtual void onMouseWheelScale( wxMouseEvent& event ) { event.Skip(); }
|
||||
virtual void updateOrientation( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void onDecrementScale( wxSpinEvent& event ) { event.Skip(); }
|
||||
virtual void onIncrementScale( wxSpinEvent& event ) { event.Skip(); }
|
||||
virtual void onMouseWheelRot( wxMouseEvent& event ) { event.Skip(); }
|
||||
virtual void onDecrementRot( wxSpinEvent& event ) { event.Skip(); }
|
||||
virtual void onIncrementRot( wxSpinEvent& event ) { event.Skip(); }
|
||||
virtual void onMouseWheelOffset( wxMouseEvent& event ) { event.Skip(); }
|
||||
virtual void onDecrementOffset( wxSpinEvent& event ) { event.Skip(); }
|
||||
virtual void onIncrementOffset( wxSpinEvent& event ) { event.Skip(); }
|
||||
virtual void View3DISO( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DLeft( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DRight( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DFront( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DBack( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DTop( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DBottom( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DUpdate( wxCommandEvent& event ) { event.Skip(); }
|
||||
|
||||
|
||||
public:
|
||||
wxTextCtrl* yoff;
|
||||
|
||||
PANEL_PREV_3D_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL );
|
||||
~PANEL_PREV_3D_BASE();
|
||||
|
||||
};
|
||||
|
||||
#endif //__PANEL_PREV_3D_BASE_H__
|
||||
@@ -1,404 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2015-2018 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file panel_prev_model.cpp
|
||||
*/
|
||||
|
||||
#include "panel_prev_model.h"
|
||||
|
||||
#include <3d_canvas/eda_3d_canvas.h>
|
||||
#include <common_ogl/cogl_att_list.h>
|
||||
|
||||
#include <class_board.h>
|
||||
|
||||
#include <base_units.h>
|
||||
#include <bitmaps.h>
|
||||
#include <class_drawpanel.h>
|
||||
#include <dpi_scaling.h>
|
||||
#include <pgm_base.h>
|
||||
#include <project.h>
|
||||
|
||||
|
||||
PANEL_PREV_3D::PANEL_PREV_3D( wxWindow* aParent, PCB_BASE_FRAME* aFrame, MODULE* aModule,
|
||||
std::vector<MODULE_3D_SETTINGS> *aParentModelList ) :
|
||||
PANEL_PREV_3D_BASE( aParent, wxID_ANY )
|
||||
{
|
||||
m_userUnits = aFrame->GetUserUnits();
|
||||
|
||||
initPanel();
|
||||
|
||||
// Initialize the color settings to draw the board and the footprint
|
||||
m_dummyBoard->SetColorsSettings( &aFrame->Settings().Colors() );
|
||||
|
||||
m_parentModelList = aParentModelList;
|
||||
|
||||
m_dummyModule = new MODULE( *aModule );
|
||||
m_dummyBoard->Add( m_dummyModule );
|
||||
|
||||
// Set 3d viewer configuration for preview
|
||||
m_settings3Dviewer = new CINFO3D_VISU();
|
||||
|
||||
// Create the 3D canvas
|
||||
m_previewPane = new EDA_3D_CANVAS( this, COGL_ATT_LIST::GetAttributesList( true ),
|
||||
m_dummyBoard, *m_settings3Dviewer,
|
||||
aFrame->Prj().Get3DCacheManager() );
|
||||
|
||||
loadCommonSettings();
|
||||
|
||||
m_SizerPanelView->Add( m_previewPane, 1, wxEXPAND, 5 );
|
||||
}
|
||||
|
||||
|
||||
PANEL_PREV_3D::~PANEL_PREV_3D()
|
||||
{
|
||||
delete m_settings3Dviewer;
|
||||
delete m_dummyBoard;
|
||||
delete m_previewPane;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::initPanel()
|
||||
{
|
||||
m_dummyBoard = new BOARD();
|
||||
m_selected = -1;
|
||||
|
||||
// Set the bitmap of 3D view buttons:
|
||||
m_bpvTop->SetBitmap( KiBitmap( axis3d_top_xpm ) );
|
||||
m_bpvFront->SetBitmap( KiBitmap( axis3d_front_xpm ) );
|
||||
m_bpvBack->SetBitmap( KiBitmap( axis3d_back_xpm ) );
|
||||
m_bpvLeft->SetBitmap( KiBitmap( axis3d_left_xpm ) );
|
||||
m_bpvRight->SetBitmap( KiBitmap( axis3d_right_xpm ) );
|
||||
m_bpvBottom->SetBitmap( KiBitmap( axis3d_bottom_xpm ) );
|
||||
m_bpvISO->SetBitmap( KiBitmap( ortho_xpm ) );
|
||||
m_bpUpdate->SetBitmap( KiBitmap( reload_xpm ) );
|
||||
|
||||
// Set the min and max values of spin buttons (mandatory on Linux)
|
||||
// They are not used, so they are set to min and max 32 bits int values
|
||||
// (the min and max values supported by a wxSpinButton)
|
||||
// It avoids blocking the up or down arrows when reaching this limit after
|
||||
// a few clicks.
|
||||
wxSpinButton* spinButtonList[] =
|
||||
{
|
||||
m_spinXscale, m_spinYscale, m_spinZscale,
|
||||
m_spinXrot, m_spinYrot, m_spinZrot,
|
||||
m_spinXoffset,m_spinYoffset, m_spinZoffset
|
||||
};
|
||||
|
||||
for( int ii = 0; ii < 9; ii++ )
|
||||
spinButtonList[ii]->SetRange( INT_MIN, INT_MAX );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::loadCommonSettings()
|
||||
{
|
||||
wxCHECK_RET( m_previewPane, "Cannot load settings to null canvas" );
|
||||
|
||||
wxConfigBase& cmnCfg = *Pgm().CommonSettings();
|
||||
|
||||
{
|
||||
const DPI_SCALING dpi{ &cmnCfg, this };
|
||||
m_previewPane->SetScaleFactor( dpi.GetScaleFactor() );
|
||||
}
|
||||
|
||||
{
|
||||
bool option;
|
||||
cmnCfg.Read( ENBL_MOUSEWHEEL_PAN_KEY, &option, false );
|
||||
m_settings3Dviewer->SetFlag( FL_MOUSEWHEEL_PANNING, option );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief rotationFromString
|
||||
* Ensure -MAX_ROTATION <= rotation <= MAX_ROTATION
|
||||
* aRotation will be normalized between -MAX_ROTATION and MAX_ROTATION
|
||||
*/
|
||||
static double rotationFromString( const wxString& aValue )
|
||||
{
|
||||
double rotation = DoubleValueFromString( DEGREES, aValue ) / 10.0;
|
||||
|
||||
if( rotation > MAX_ROTATION )
|
||||
{
|
||||
int n = rotation / MAX_ROTATION;
|
||||
rotation -= MAX_ROTATION * n;
|
||||
}
|
||||
else if( rotation < -MAX_ROTATION )
|
||||
{
|
||||
int n = -rotation / MAX_ROTATION;
|
||||
rotation += MAX_ROTATION * n;
|
||||
}
|
||||
|
||||
return rotation;
|
||||
}
|
||||
|
||||
|
||||
wxString PANEL_PREV_3D::formatScaleValue( double aValue )
|
||||
{
|
||||
return wxString::Format( "%.4f", aValue );
|
||||
}
|
||||
|
||||
|
||||
wxString PANEL_PREV_3D::formatRotationValue( double aValue )
|
||||
{
|
||||
return wxString::Format( "%.2f %s", aValue, GetAbbreviatedUnitsLabel( DEGREES ) );
|
||||
}
|
||||
|
||||
|
||||
wxString PANEL_PREV_3D::formatOffsetValue( double aValue )
|
||||
{
|
||||
// Convert from internal units (mm) to user units
|
||||
if( m_userUnits == INCHES )
|
||||
aValue /= 25.4f;
|
||||
|
||||
return wxString::Format( "%.4f %s", aValue, GetAbbreviatedUnitsLabel( m_userUnits ) );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::SetSelectedModel( int idx )
|
||||
{
|
||||
if( m_parentModelList && idx >= 0 && idx < (int) m_parentModelList->size() )
|
||||
{
|
||||
m_selected = idx;
|
||||
const MODULE_3D_SETTINGS& modelInfo = m_parentModelList->at( (unsigned) m_selected );
|
||||
|
||||
// Use ChangeValue() instead of SetValue(). It's not the user making the change, so we
|
||||
// don't want to generate wxEVT_GRID_CELL_CHANGED events.
|
||||
|
||||
xscale->ChangeValue( formatScaleValue( modelInfo.m_Scale.x ) );
|
||||
yscale->ChangeValue( formatScaleValue( modelInfo.m_Scale.y ) );
|
||||
zscale->ChangeValue( formatScaleValue( modelInfo.m_Scale.z ) );
|
||||
|
||||
xrot->ChangeValue( formatRotationValue( modelInfo.m_Rotation.x ) );
|
||||
yrot->ChangeValue( formatRotationValue( modelInfo.m_Rotation.y ) );
|
||||
zrot->ChangeValue( formatRotationValue( modelInfo.m_Rotation.z ) );
|
||||
|
||||
xoff->ChangeValue( formatOffsetValue( modelInfo.m_Offset.x ) );
|
||||
yoff->ChangeValue( formatOffsetValue( modelInfo.m_Offset.y ) );
|
||||
zoff->ChangeValue( formatOffsetValue( modelInfo.m_Offset.z ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_selected = -1;
|
||||
|
||||
xscale->ChangeValue( wxEmptyString );
|
||||
yscale->ChangeValue( wxEmptyString );
|
||||
zscale->ChangeValue( wxEmptyString );
|
||||
|
||||
xrot->ChangeValue( wxEmptyString );
|
||||
yrot->ChangeValue( wxEmptyString );
|
||||
zrot->ChangeValue( wxEmptyString );
|
||||
|
||||
xoff->ChangeValue( wxEmptyString );
|
||||
yoff->ChangeValue( wxEmptyString );
|
||||
zoff->ChangeValue( wxEmptyString );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::updateOrientation( wxCommandEvent &event )
|
||||
{
|
||||
if( m_parentModelList && m_selected >= 0 && m_selected < (int) m_parentModelList->size() )
|
||||
{
|
||||
// Write settings back to the parent
|
||||
MODULE_3D_SETTINGS* modelInfo = &m_parentModelList->at( (unsigned) m_selected );
|
||||
|
||||
modelInfo->m_Scale.x = DoubleValueFromString( UNSCALED_UNITS, xscale->GetValue() );
|
||||
modelInfo->m_Scale.y = DoubleValueFromString( UNSCALED_UNITS, yscale->GetValue() );
|
||||
modelInfo->m_Scale.z = DoubleValueFromString( UNSCALED_UNITS, zscale->GetValue() );
|
||||
|
||||
modelInfo->m_Rotation.x = rotationFromString( xrot->GetValue() );
|
||||
modelInfo->m_Rotation.y = rotationFromString( yrot->GetValue() );
|
||||
modelInfo->m_Rotation.z = rotationFromString( zrot->GetValue() );
|
||||
|
||||
modelInfo->m_Offset.x = DoubleValueFromString( m_userUnits, xoff->GetValue() ) / IU_PER_MM;
|
||||
modelInfo->m_Offset.y = DoubleValueFromString( m_userUnits, yoff->GetValue() ) / IU_PER_MM;
|
||||
modelInfo->m_Offset.z = DoubleValueFromString( m_userUnits, zoff->GetValue() ) / IU_PER_MM;
|
||||
|
||||
// Update the dummy module for the preview
|
||||
UpdateDummyModule( false );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::doIncrementScale( wxSpinEvent& event, double aSign )
|
||||
{
|
||||
wxSpinButton* spinCtrl = (wxSpinButton*) event.GetEventObject();
|
||||
|
||||
wxTextCtrl * textCtrl = xscale;
|
||||
|
||||
if( spinCtrl == m_spinYscale )
|
||||
textCtrl = yscale;
|
||||
else if( spinCtrl == m_spinZscale )
|
||||
textCtrl = zscale;
|
||||
|
||||
double curr_value = DoubleValueFromString( UNSCALED_UNITS, textCtrl->GetValue() );
|
||||
|
||||
curr_value += ( SCALE_INCREMENT * aSign );
|
||||
curr_value = std::max( 1/MAX_SCALE, curr_value );
|
||||
curr_value = std::min( curr_value, MAX_SCALE );
|
||||
|
||||
textCtrl->SetValue( formatScaleValue( curr_value ) );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::doIncrementRotation( wxSpinEvent& aEvent, double aSign )
|
||||
{
|
||||
wxSpinButton* spinCtrl = (wxSpinButton*) aEvent.GetEventObject();
|
||||
wxTextCtrl* textCtrl = xrot;
|
||||
|
||||
if( spinCtrl == m_spinYrot )
|
||||
textCtrl = yrot;
|
||||
else if( spinCtrl == m_spinZrot )
|
||||
textCtrl = zrot;
|
||||
|
||||
double curr_value = DoubleValueFromString( DEGREES, textCtrl->GetValue() ) / 10.0;
|
||||
|
||||
curr_value += ( ROTATION_INCREMENT * aSign );
|
||||
curr_value = std::max( -MAX_ROTATION, curr_value );
|
||||
curr_value = std::min( curr_value, MAX_ROTATION );
|
||||
|
||||
textCtrl->SetValue( formatRotationValue( curr_value ) );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::doIncrementOffset( wxSpinEvent& event, double aSign )
|
||||
{
|
||||
wxSpinButton* spinCtrl = (wxSpinButton*) event.GetEventObject();
|
||||
|
||||
wxTextCtrl * textCtrl = xoff;
|
||||
|
||||
if( spinCtrl == m_spinYoffset )
|
||||
textCtrl = yoff;
|
||||
else if( spinCtrl == m_spinZoffset )
|
||||
textCtrl = zoff;
|
||||
|
||||
double step = OFFSET_INCREMENT_MM;
|
||||
|
||||
if( m_userUnits == INCHES )
|
||||
step = OFFSET_INCREMENT_MIL/1000.0;
|
||||
|
||||
double curr_value = DoubleValueFromString( m_userUnits, textCtrl->GetValue() ) / IU_PER_MM;
|
||||
|
||||
curr_value += ( step * aSign );
|
||||
curr_value = std::max( -MAX_OFFSET, curr_value );
|
||||
curr_value = std::min( curr_value, MAX_OFFSET );
|
||||
|
||||
textCtrl->SetValue( formatOffsetValue( curr_value ) );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::onMouseWheelScale( wxMouseEvent& event )
|
||||
{
|
||||
wxTextCtrl* textCtrl = (wxTextCtrl*) event.GetEventObject();
|
||||
|
||||
double step = SCALE_INCREMENT;
|
||||
|
||||
if( event.ShiftDown( ) )
|
||||
step = SCALE_INCREMENT_FINE;
|
||||
|
||||
if( event.GetWheelRotation() >= 0 )
|
||||
step = -step;
|
||||
|
||||
double curr_value = DoubleValueFromString( UNSCALED_UNITS, textCtrl->GetValue() );
|
||||
|
||||
curr_value += step;
|
||||
curr_value = std::max( 1/MAX_SCALE, curr_value );
|
||||
curr_value = std::min( curr_value, MAX_SCALE );
|
||||
|
||||
textCtrl->SetValue( formatScaleValue( curr_value ) );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::onMouseWheelRot( wxMouseEvent& event )
|
||||
{
|
||||
wxTextCtrl* textCtrl = (wxTextCtrl*) event.GetEventObject();
|
||||
|
||||
double step = ROTATION_INCREMENT_WHEEL;
|
||||
|
||||
if( event.ShiftDown( ) )
|
||||
step = ROTATION_INCREMENT_WHEEL_FINE;
|
||||
|
||||
if( event.GetWheelRotation() >= 0 )
|
||||
step = -step;
|
||||
|
||||
double curr_value = DoubleValueFromString( DEGREES, textCtrl->GetValue() ) / 10.0;
|
||||
|
||||
curr_value += step;
|
||||
curr_value = std::max( -MAX_ROTATION, curr_value );
|
||||
curr_value = std::min( curr_value, MAX_ROTATION );
|
||||
|
||||
textCtrl->SetValue( formatRotationValue( curr_value ) );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::onMouseWheelOffset( wxMouseEvent& event )
|
||||
{
|
||||
wxTextCtrl* textCtrl = (wxTextCtrl*) event.GetEventObject();
|
||||
|
||||
double step = OFFSET_INCREMENT_MM;
|
||||
|
||||
if( event.ShiftDown( ) )
|
||||
step = OFFSET_INCREMENT_MM_FINE;
|
||||
|
||||
if( m_userUnits == INCHES )
|
||||
{
|
||||
step = OFFSET_INCREMENT_MIL/1000.0;
|
||||
if( event.ShiftDown( ) )
|
||||
step = OFFSET_INCREMENT_MIL_FINE/1000.0;
|
||||
}
|
||||
|
||||
if( event.GetWheelRotation() >= 0 )
|
||||
step = -step;
|
||||
|
||||
double curr_value = DoubleValueFromString( m_userUnits, textCtrl->GetValue() ) / IU_PER_MM;
|
||||
|
||||
curr_value += step;
|
||||
curr_value = std::max( -MAX_OFFSET, curr_value );
|
||||
curr_value = std::min( curr_value, MAX_OFFSET );
|
||||
|
||||
textCtrl->SetValue( formatOffsetValue( curr_value ) );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::UpdateDummyModule( bool aReloadRequired )
|
||||
{
|
||||
m_dummyModule->Models().clear();
|
||||
|
||||
for( size_t i = 0; i < m_parentModelList->size(); ++i )
|
||||
{
|
||||
if( m_parentModelList->at( i ).m_Preview )
|
||||
{
|
||||
m_dummyModule->Models().insert( m_dummyModule->Models().end(),
|
||||
m_parentModelList->at( i ) );
|
||||
}
|
||||
}
|
||||
|
||||
if( aReloadRequired )
|
||||
m_previewPane->ReloadRequest();
|
||||
|
||||
m_previewPane->Request_refresh();
|
||||
}
|
||||
@@ -1,200 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2015-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file panel_prev_model.h
|
||||
* @brief Defines a panel which is to be added to a wxFileDialog via
|
||||
* SetExtraControl();
|
||||
* The panel shows a preview of the module being edited and provides controls
|
||||
* to set the offset/rotation/scale of each model 3d shape as per KiCad's
|
||||
* current behavior. The panel may also be used in the 3D configuration dialog
|
||||
* to tune the positioning of the models without invoking a file selector dialog.
|
||||
*/
|
||||
|
||||
#ifndef PANEL_PREV_MODEL_H
|
||||
#define PANEL_PREV_MODEL_H
|
||||
|
||||
#include "panel_prev_3d_base.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <3d_canvas/eda_3d_canvas.h>
|
||||
|
||||
// Define min and max parameter values
|
||||
#define MAX_SCALE 10000.0
|
||||
#define MAX_ROTATION 180.0
|
||||
#define MAX_OFFSET 1000.0
|
||||
|
||||
#define SCALE_INCREMENT_FINE 0.02
|
||||
#define SCALE_INCREMENT 0.1
|
||||
|
||||
#define ROTATION_INCREMENT 5 // in degrees, for spin button command
|
||||
#define ROTATION_INCREMENT_WHEEL 15 // in degrees, for mouse wheel command
|
||||
#define ROTATION_INCREMENT_WHEEL_FINE 1 // in degrees, for mouse wheel command
|
||||
|
||||
#define OFFSET_INCREMENT_MM 0.5
|
||||
#define OFFSET_INCREMENT_MM_FINE 0.1
|
||||
|
||||
#define OFFSET_INCREMENT_MIL 25.0
|
||||
#define OFFSET_INCREMENT_MIL_FINE 5.0
|
||||
|
||||
|
||||
// Declared classes to create pointers
|
||||
class S3D_CACHE;
|
||||
class FILENAME_RESOLVER;
|
||||
class BOARD;
|
||||
class CINFO3D_VISU;
|
||||
class MODULE;
|
||||
class COLORS_DESIGN_SETTINGS;
|
||||
|
||||
class PANEL_PREV_3D: public PANEL_PREV_3D_BASE
|
||||
{
|
||||
public:
|
||||
PANEL_PREV_3D( wxWindow* aParent, PCB_BASE_FRAME* aFrame, MODULE* aModule,
|
||||
std::vector<MODULE_3D_SETTINGS> *aParentModelList );
|
||||
|
||||
~PANEL_PREV_3D();
|
||||
|
||||
private:
|
||||
EDA_3D_CANVAS* m_previewPane;
|
||||
CINFO3D_VISU* m_settings3Dviewer;
|
||||
|
||||
BOARD* m_dummyBoard;
|
||||
MODULE* m_dummyModule;
|
||||
|
||||
std::vector<MODULE_3D_SETTINGS>* m_parentModelList;
|
||||
int m_selected; /// Index into m_parentInfoList
|
||||
|
||||
EDA_UNITS_T m_userUnits;
|
||||
|
||||
// Methods of the class
|
||||
private:
|
||||
void initPanel();
|
||||
|
||||
/**
|
||||
* Load 3D relevant settings from the user configuration
|
||||
*/
|
||||
void loadCommonSettings();
|
||||
|
||||
/**
|
||||
* @brief updateOrientation - it will receive the events from editing the fields
|
||||
* @param event
|
||||
*/
|
||||
void updateOrientation( wxCommandEvent &event ) override;
|
||||
|
||||
void onMouseWheelScale( wxMouseEvent& event ) override;
|
||||
void onMouseWheelRot( wxMouseEvent& event ) override;
|
||||
void onMouseWheelOffset( wxMouseEvent& event ) override;
|
||||
|
||||
void onIncrementRot( wxSpinEvent& event ) override
|
||||
{
|
||||
doIncrementRotation( event, 1.0 );
|
||||
}
|
||||
void onDecrementRot( wxSpinEvent& event ) override
|
||||
{
|
||||
doIncrementRotation( event, -1.0 );
|
||||
}
|
||||
void onIncrementScale( wxSpinEvent& event ) override
|
||||
{
|
||||
doIncrementScale( event, 1.0 );
|
||||
}
|
||||
void onDecrementScale( wxSpinEvent& event ) override
|
||||
{
|
||||
doIncrementScale( event, -1.0 );
|
||||
}
|
||||
void onIncrementOffset( wxSpinEvent& event ) override
|
||||
{
|
||||
doIncrementOffset( event, 1.0 );
|
||||
}
|
||||
void onDecrementOffset( wxSpinEvent& event ) override
|
||||
{
|
||||
doIncrementOffset( event, -1.0 );
|
||||
}
|
||||
|
||||
void doIncrementScale( wxSpinEvent& aEvent, double aSign );
|
||||
void doIncrementRotation( wxSpinEvent& aEvent, double aSign );
|
||||
void doIncrementOffset( wxSpinEvent& aEvent, double aSign );
|
||||
|
||||
wxString formatScaleValue( double aValue );
|
||||
wxString formatRotationValue( double aValue );
|
||||
wxString formatOffsetValue( double aValue );
|
||||
|
||||
void View3DISO( wxCommandEvent& event ) override
|
||||
{
|
||||
m_settings3Dviewer->CameraGet().ToggleProjection();
|
||||
m_previewPane->Refresh();
|
||||
}
|
||||
|
||||
void View3DLeft( wxCommandEvent& event ) override
|
||||
{
|
||||
m_previewPane->SetView3D( GR_KB_SHIFT + 'X' );
|
||||
}
|
||||
|
||||
void View3DFront( wxCommandEvent& event ) override
|
||||
{
|
||||
m_previewPane->SetView3D( 'Y' );
|
||||
}
|
||||
|
||||
void View3DTop( wxCommandEvent& event ) override
|
||||
{
|
||||
m_previewPane->SetView3D( 'Z' );
|
||||
}
|
||||
|
||||
void View3DUpdate( wxCommandEvent& event ) override
|
||||
{
|
||||
m_previewPane->ReloadRequest();
|
||||
m_previewPane->Refresh();
|
||||
}
|
||||
|
||||
void View3DRight( wxCommandEvent& event ) override
|
||||
{
|
||||
m_previewPane->SetView3D( 'X' );
|
||||
}
|
||||
|
||||
void View3DBack( wxCommandEvent& event ) override
|
||||
{
|
||||
m_previewPane->SetView3D( GR_KB_SHIFT + 'Y' );
|
||||
}
|
||||
|
||||
void View3DBottom( wxCommandEvent& event ) override
|
||||
{
|
||||
m_previewPane->SetView3D( GR_KB_SHIFT + 'Z' );
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief SetModelDataIdx - Sets the currently selected index in the model list so that
|
||||
* the scale/rotation/offset controls can be updated.
|
||||
*/
|
||||
void SetSelectedModel( int idx );
|
||||
|
||||
/**
|
||||
* @brief UpdateModelInfoList - copy shapes from the current shape list which are flagged
|
||||
* for preview to the copy of module that is on the preview dummy board
|
||||
*/
|
||||
void UpdateDummyModule( bool aRelaodRequired = true );
|
||||
};
|
||||
|
||||
#endif // PANEL_PREV_MODEL_H
|
||||
@@ -1,102 +0,0 @@
|
||||
include_directories(
|
||||
${CMAKE_SOURCE_DIR}/include
|
||||
${CMAKE_SOURCE_DIR}/3d-viewer
|
||||
)
|
||||
|
||||
set( SG_FILES
|
||||
sg_base.cpp
|
||||
sg_node.cpp
|
||||
sg_helpers.cpp
|
||||
scenegraph.cpp
|
||||
sg_appearance.cpp
|
||||
sg_faceset.cpp
|
||||
sg_shape.cpp
|
||||
sg_colors.cpp
|
||||
sg_coords.cpp
|
||||
sg_normals.cpp
|
||||
sg_index.cpp
|
||||
sg_coordindex.cpp
|
||||
ifsg_node.cpp
|
||||
ifsg_transform.cpp
|
||||
ifsg_appearance.cpp
|
||||
ifsg_index.cpp
|
||||
ifsg_coordindex.cpp
|
||||
ifsg_colors.cpp
|
||||
ifsg_coords.cpp
|
||||
ifsg_faceset.cpp
|
||||
ifsg_normals.cpp
|
||||
ifsg_shape.cpp
|
||||
ifsg_api.cpp
|
||||
)
|
||||
|
||||
if( MINGW )
|
||||
list( APPEND SG_FILES ${CMAKE_SOURCE_DIR}/common/streamwrapper.cpp )
|
||||
endif( MINGW )
|
||||
|
||||
add_library( kicad_3dsg SHARED ${SG_FILES} )
|
||||
|
||||
if( APPLE )
|
||||
# puts library into the main kicad.app bundle in build tree
|
||||
set_target_properties( kicad_3dsg PROPERTIES
|
||||
LIBRARY_OUTPUT_DIRECTORY "${OSX_BUNDLE_BUILD_LIB_DIR}"
|
||||
INSTALL_NAME_DIR "${OSX_BUNDLE_BUILD_LIB_DIR}"
|
||||
)
|
||||
endif()
|
||||
|
||||
find_file( S3DSG_VERSION_FILE sg_version.h
|
||||
PATHS ${CMAKE_SOURCE_DIR}/include/plugins/3dapi NO_DEFAULT_PATH )
|
||||
|
||||
if( NOT ${S3DSG_VERSION_FILE} STREQUAL "S3DSG_VERSION_FILE-NOTFOUND" )
|
||||
|
||||
# extract the "#define KICADSG_VERSION_*" lines
|
||||
file( STRINGS ${S3DSG_VERSION_FILE} _version
|
||||
REGEX "^[' ','\t']*#define[' ','\t']*KICADSG_VERSION_.*" )
|
||||
|
||||
foreach( SVAR ${_version} )
|
||||
string( REGEX MATCH KICADSG_VERSION_[M,A,J,O,R,I,N,P,T,C,H,E,V]* _VARNAME ${SVAR} )
|
||||
string( REGEX MATCH [0-9]+ _VALUE ${SVAR} )
|
||||
|
||||
if( NOT ${_VARNAME} STREQUAL "" )
|
||||
if( NOT ${_VALUE} STREQUAL "" )
|
||||
set( ${_VARNAME} ${_VALUE} )
|
||||
else()
|
||||
set( ${_VARNAME} 0 )
|
||||
endif()
|
||||
endif()
|
||||
|
||||
endforeach()
|
||||
|
||||
if( NOT KICADSG_VERSION_MAJOR AND NOT ${KICADSG_VERSION_MAJOR} STREQUAL "0" )
|
||||
message( FATAL_ERROR "Cannot determine the S3DSG library version" )
|
||||
endif()
|
||||
|
||||
#ensure that NOT SG_VERSION* will evaluate to '0'
|
||||
if( NOT KICADSG_VERSION_MINOR )
|
||||
set( KICADSG_VERSION_MINOR 0 )
|
||||
endif()
|
||||
|
||||
if( NOT KICADSG_VERSION_PATCH )
|
||||
set( KICADSG_VERSION_PATCH 0 )
|
||||
endif()
|
||||
|
||||
set_target_properties( kicad_3dsg
|
||||
PROPERTIES SOVERSION
|
||||
${KICADSG_VERSION_MAJOR}.${KICADSG_VERSION_MINOR}.${KICADSG_VERSION_PATCH} )
|
||||
|
||||
message( STATUS "S3DSG version: ${KICADSG_VERSION_MAJOR}.${KICADSG_VERSION_MINOR}.${KICADSG_VERSION_PATCH}" )
|
||||
else()
|
||||
message( FATAL_ERROR "Cannot determine the S3DSG library version" )
|
||||
endif()
|
||||
|
||||
unset( S3DSG_VERSION_FILE CACHE )
|
||||
|
||||
# Define a flag to expose the appropriate EXPORT macro at build time
|
||||
target_compile_definitions( kicad_3dsg PRIVATE -DCOMPILE_SGLIB )
|
||||
|
||||
target_link_libraries( kicad_3dsg ${wxWidgets_LIBRARIES} )
|
||||
|
||||
install( TARGETS
|
||||
kicad_3dsg
|
||||
DESTINATION ${KICAD_LIB}
|
||||
COMPONENT binary
|
||||
)
|
||||
@@ -1,671 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <wx/filename.h>
|
||||
#include <wx/log.h>
|
||||
#include "plugins/3dapi/ifsg_api.h"
|
||||
#include "plugins/3dapi/sg_version.h"
|
||||
#include "streamwrapper.h"
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
#include "3d_cache/sg/scenegraph.h"
|
||||
#include "3d_cache/sg/sg_appearance.h"
|
||||
#include "3d_cache/sg/sg_shape.h"
|
||||
#include "3d_cache/sg/sg_helpers.h"
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
static char BadNode[] = " * [BUG] NULL pointer passed for aNode\n";
|
||||
#endif
|
||||
|
||||
// version format of the cache file
|
||||
#define SG_VERSION_TAG "VERSION:2"
|
||||
|
||||
|
||||
static void formatMaterial( SMATERIAL& mat, SGAPPEARANCE const* app )
|
||||
{
|
||||
float v0, v1, v2;
|
||||
|
||||
app->ambient.GetColor( v0, v1, v2 );
|
||||
mat.m_Ambient.x = v0;
|
||||
mat.m_Ambient.y = v1;
|
||||
mat.m_Ambient.z = v2;
|
||||
|
||||
app->diffuse.GetColor( v0, v1, v2 );
|
||||
mat.m_Diffuse.x = v0;
|
||||
mat.m_Diffuse.y = v1;
|
||||
mat.m_Diffuse.z = v2;
|
||||
mat.m_Ambient.x *= v0;
|
||||
mat.m_Ambient.y *= v1;
|
||||
mat.m_Ambient.z *= v2;
|
||||
|
||||
app->emissive.GetColor( v0, v1, v2 );
|
||||
mat.m_Emissive.x = v0;
|
||||
mat.m_Emissive.y = v1;
|
||||
mat.m_Emissive.z = v2;
|
||||
|
||||
app->specular.GetColor( v0, v1, v2 );
|
||||
mat.m_Specular.x = v0;
|
||||
mat.m_Specular.y = v1;
|
||||
mat.m_Specular.z = v2;
|
||||
|
||||
mat.m_Shininess = app->shininess;
|
||||
mat.m_Transparency = app->transparency;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::WriteVRML( const char* filename, bool overwrite, SGNODE* aTopNode,
|
||||
bool reuse, bool renameNodes )
|
||||
{
|
||||
if( NULL == filename || filename[0] == 0 )
|
||||
return false;
|
||||
|
||||
wxString ofile = wxString::FromUTF8Unchecked( filename );
|
||||
|
||||
if( wxFileName::Exists( ofile ) )
|
||||
{
|
||||
if( !overwrite )
|
||||
return false;
|
||||
|
||||
// make sure we make no attempt to write a directory
|
||||
if( !wxFileName::FileExists( ofile ) )
|
||||
return false;
|
||||
}
|
||||
|
||||
if( NULL == aTopNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aTopNode";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_TRANSFORM != aTopNode->GetNodeType() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] aTopNode is not a SCENEGRAPH object";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
OPEN_OSTREAM( op, filename );
|
||||
|
||||
if( op.fail() )
|
||||
{
|
||||
wxString errmsg;
|
||||
errmsg << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
errmsg << " * [INFO] " << "failed to open file" << " '" << filename << "'";
|
||||
wxLogTrace( MASK_3D_SG, errmsg );
|
||||
return false;
|
||||
}
|
||||
|
||||
op.imbue( std::locale( "C" ) );
|
||||
op << "#VRML V2.0 utf8\n";
|
||||
|
||||
if( renameNodes )
|
||||
{
|
||||
aTopNode->ResetNodeIndex();
|
||||
aTopNode->ReNameNodes();
|
||||
}
|
||||
|
||||
aTopNode->WriteVRML( op, reuse );
|
||||
|
||||
if( !op.fail() )
|
||||
{
|
||||
CLOSE_STREAM( op );
|
||||
return true;
|
||||
}
|
||||
|
||||
CLOSE_STREAM( op );
|
||||
|
||||
wxString errmsg;
|
||||
errmsg << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
errmsg << " * [INFO] " << "problems encountered writing file" << " '" << filename << "'";
|
||||
wxLogTrace( MASK_3D_SG, errmsg );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void S3D::ResetNodeIndex( SGNODE* aNode )
|
||||
{
|
||||
if( NULL == aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadNode;
|
||||
wxLogTrace( MASK_3D_SG, "%s", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
aNode->ResetNodeIndex();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D::RenameNodes( SGNODE* aNode )
|
||||
{
|
||||
if( NULL == aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadNode;
|
||||
wxLogTrace( MASK_3D_SG, "%s", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
aNode->ReNameNodes();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D::DestroyNode( SGNODE* aNode )
|
||||
{
|
||||
if( NULL == aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadNode;
|
||||
wxLogTrace( MASK_3D_SG, "%s", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
delete aNode;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::WriteCache( const char* aFileName, bool overwrite, SGNODE* aNode,
|
||||
const char* aPluginInfo )
|
||||
{
|
||||
if( NULL == aFileName || aFileName[0] == 0 )
|
||||
return false;
|
||||
|
||||
wxString ofile = wxString::FromUTF8Unchecked( aFileName );
|
||||
|
||||
if( NULL == aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadNode;
|
||||
wxLogTrace( MASK_3D_SG, "%s", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if( wxFileName::Exists( ofile ) )
|
||||
{
|
||||
if( !overwrite )
|
||||
{
|
||||
wxString errmsg;
|
||||
errmsg << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
errmsg << " * [INFO] " << "file exists; not overwriting" << " '";
|
||||
errmsg << aFileName << "'";
|
||||
wxLogTrace( MASK_3D_SG, errmsg );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// make sure we make no attempt to write a directory
|
||||
if( !wxFileName::FileExists( aFileName ) )
|
||||
{
|
||||
wxString errmsg;
|
||||
errmsg << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
errmsg << " * [INFO] " << "specified path is a directory" << " '";
|
||||
errmsg << aFileName << "'";
|
||||
wxLogTrace( MASK_3D_SG, errmsg );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
OPEN_OSTREAM( output, aFileName );
|
||||
|
||||
if( output.fail() )
|
||||
{
|
||||
wxString errmsg;
|
||||
errmsg << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
errmsg << " * [INFO] " << "failed to open file" << " '" << aFileName << "'";
|
||||
wxLogTrace( MASK_3D_SG, errmsg );
|
||||
return false;
|
||||
}
|
||||
|
||||
output << "(" << SG_VERSION_TAG << ")";
|
||||
|
||||
if( NULL != aPluginInfo && aPluginInfo[0] != 0 )
|
||||
output << "(" << aPluginInfo << ")";
|
||||
else
|
||||
output << "(INTERNAL:0.0.0.0)";
|
||||
|
||||
bool rval = aNode->WriteCache( output, NULL );
|
||||
CLOSE_STREAM( output );
|
||||
|
||||
if( !rval )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] problems encountered writing cache file '";
|
||||
ostr << aFileName << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
// delete the defective file
|
||||
wxRemoveFile( ofile );
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
SGNODE* S3D::ReadCache( const char* aFileName, void* aPluginMgr,
|
||||
bool (*aTagCheck)( const char*, void* ) )
|
||||
{
|
||||
if( NULL == aFileName || aFileName[0] == 0 )
|
||||
return NULL;
|
||||
|
||||
wxString ofile = wxString::FromUTF8Unchecked( aFileName );
|
||||
|
||||
if( !wxFileName::FileExists( aFileName ) )
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
wxString errmsg = _( "no such file" );
|
||||
ostr << " * [INFO] " << errmsg.ToUTF8() << " '";
|
||||
ostr << aFileName << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SGNODE* np = new SCENEGRAPH( NULL );
|
||||
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] failed to instantiate SCENEGRAPH";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OPEN_ISTREAM( file, aFileName );
|
||||
|
||||
if( file.fail() )
|
||||
{
|
||||
delete np;
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
wxString errmsg = _( "failed to open file" );
|
||||
ostr << " * [INFO] " << errmsg.ToUTF8() << " '";
|
||||
ostr << aFileName << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// from SG_VERSION_TAG 1, read the version tag; if it's not the expected tag
|
||||
// then we fail to read the cache file
|
||||
do
|
||||
{
|
||||
std::string name;
|
||||
char schar;
|
||||
file.get( schar );
|
||||
|
||||
if( '(' != schar )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; missing left parenthesis at position ";
|
||||
ostr << file.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
CLOSE_STREAM( file );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
file.get( schar );
|
||||
|
||||
while( ')' != schar && file.good() )
|
||||
{
|
||||
name.push_back( schar );
|
||||
file.get( schar );
|
||||
}
|
||||
|
||||
if( name.compare( SG_VERSION_TAG ) )
|
||||
{
|
||||
CLOSE_STREAM( file );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
|
||||
// from SG_VERSION_TAG 2, read the PluginInfo string and check that it matches
|
||||
// version tag; if it's not the expected tag then we fail to read the file
|
||||
do
|
||||
{
|
||||
std::string name;
|
||||
char schar;
|
||||
file.get( schar );
|
||||
|
||||
if( '(' != schar )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; missing left parenthesis at position ";
|
||||
ostr << file.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
CLOSE_STREAM( file );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
file.get( schar );
|
||||
|
||||
while( ')' != schar && file.good() )
|
||||
{
|
||||
name.push_back( schar );
|
||||
file.get( schar );
|
||||
}
|
||||
|
||||
// check the plugin tag
|
||||
if( NULL != aTagCheck && NULL != aPluginMgr && !aTagCheck( name.c_str(), aPluginMgr ) )
|
||||
{
|
||||
CLOSE_STREAM( file );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
|
||||
bool rval = np->ReadCache( file, NULL );
|
||||
CLOSE_STREAM( file );
|
||||
|
||||
if( !rval )
|
||||
{
|
||||
delete np;
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
wxString errmsg = "problems encountered reading cache file";
|
||||
ostr << " * [INFO] " << errmsg.ToUTF8() << " '";
|
||||
ostr << aFileName << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return np;
|
||||
}
|
||||
|
||||
|
||||
S3DMODEL* S3D::GetModel( SCENEGRAPH* aNode )
|
||||
{
|
||||
if( NULL == aNode )
|
||||
return NULL;
|
||||
|
||||
if( aNode->GetNodeType() != S3D::SGTYPE_TRANSFORM )
|
||||
return NULL;
|
||||
|
||||
S3D::MATLIST materials;
|
||||
std::vector< SMESH > meshes;
|
||||
|
||||
// the materials list shall have a default color; although the VRML
|
||||
// default is an opaque black, the default used here shall be a median
|
||||
// gray in hopes that it may help highlight faulty models; this color is
|
||||
// also typical of MCAD applications. When a model has no associated
|
||||
// material color it shall be assigned the index 0.
|
||||
SGAPPEARANCE app( NULL );
|
||||
app.ambient = SGCOLOR( 0.6, 0.6, 0.6 );
|
||||
app.diffuse = SGCOLOR( 0.6, 0.6, 0.6 );
|
||||
app.specular = app.diffuse;
|
||||
app.shininess = 0.05;
|
||||
app.transparency = 0.0;
|
||||
|
||||
materials.matorder.push_back( &app );
|
||||
materials.matmap.insert( std::pair< SGAPPEARANCE const*, int >( &app, 0 ) );
|
||||
|
||||
if( aNode->Prepare( NULL, materials, meshes ) )
|
||||
{
|
||||
if( meshes.empty() )
|
||||
return NULL;
|
||||
|
||||
S3DMODEL* model = S3D::New3DModel();
|
||||
|
||||
// add all the materials
|
||||
size_t j = materials.matorder.size();
|
||||
SMATERIAL* lmat = new SMATERIAL[j];
|
||||
|
||||
for( size_t i = 0; i < j; ++i )
|
||||
formatMaterial( lmat[i], materials.matorder[i] );
|
||||
|
||||
model->m_Materials = lmat;
|
||||
model->m_MaterialsSize = j;
|
||||
|
||||
// add all the meshes
|
||||
j = meshes.size();
|
||||
SMESH* lmesh = new SMESH[j];
|
||||
|
||||
for( size_t i = 0; i < j; ++i )
|
||||
lmesh[i] = meshes[i];
|
||||
|
||||
model->m_Meshes = lmesh;
|
||||
model->m_MeshesSize = j;
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
size_t j = meshes.size();
|
||||
|
||||
for( size_t i = 0; i < j; ++i )
|
||||
S3D::Free3DMesh( meshes[i] );
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void S3D::Destroy3DModel( S3DMODEL** aModel )
|
||||
{
|
||||
if( NULL == aModel || NULL == *aModel )
|
||||
return;
|
||||
|
||||
S3DMODEL* m = *aModel;
|
||||
S3D::FREE_S3DMODEL( *m );
|
||||
delete m;
|
||||
*aModel = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void Free3DModel( S3DMODEL& aModel )
|
||||
{
|
||||
S3D::FREE_S3DMODEL( aModel );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D::Free3DMesh( SMESH& aMesh )
|
||||
{
|
||||
S3D::FREE_SMESH( aMesh );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
S3DMODEL* S3D::New3DModel( void )
|
||||
{
|
||||
S3DMODEL* mp = new S3DMODEL;
|
||||
S3D::INIT_S3DMODEL( *mp );
|
||||
return mp;
|
||||
}
|
||||
|
||||
|
||||
void S3D::Init3DMaterial( SMATERIAL& aMat )
|
||||
{
|
||||
S3D::INIT_SMATERIAL( aMat );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D::Init3DMesh( SMESH& aMesh )
|
||||
{
|
||||
S3D::INIT_SMESH( aMesh );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D::GetLibVersion( unsigned char* Major, unsigned char* Minor,
|
||||
unsigned char* Patch, unsigned char* Revision )
|
||||
{
|
||||
if( Major )
|
||||
*Major = KICADSG_VERSION_MAJOR;
|
||||
|
||||
if( Minor )
|
||||
*Minor = KICADSG_VERSION_MINOR;
|
||||
|
||||
if( Revision )
|
||||
*Revision = KICADSG_VERSION_REVISION;
|
||||
|
||||
if( Patch )
|
||||
*Patch = KICADSG_VERSION_PATCH;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGVECTOR S3D::CalcTriNorm( const SGPOINT& p1, const SGPOINT& p2, const SGPOINT& p3 )
|
||||
{
|
||||
glm::dvec3 tri = glm::dvec3( 0.0, 0.0, 0.0 );
|
||||
glm::dvec3 pts[3];
|
||||
|
||||
pts[0] = glm::dvec3( p1.x, p1.y, p1.z );
|
||||
pts[1] = glm::dvec3( p2.x, p2.y, p2.z );
|
||||
pts[2] = glm::dvec3( p3.x, p3.y, p3.z );
|
||||
|
||||
// degenerate points are given a default 0, 0, 1 normal
|
||||
if( S3D::degenerate( pts ) )
|
||||
return SGVECTOR( 0.0, 0.0, 1.0 );
|
||||
|
||||
// normal
|
||||
tri = glm::cross( pts[1] - pts[0], pts[2] - pts[0] );
|
||||
glm::normalize( tri );
|
||||
|
||||
return SGVECTOR( tri.x, tri.y, tri.z );
|
||||
}
|
||||
|
||||
|
||||
S3D::SGTYPES S3D::GetSGNodeType( SGNODE* aNode )
|
||||
{
|
||||
if( NULL == aNode )
|
||||
return SGTYPE_END;
|
||||
|
||||
return aNode->GetNodeType();
|
||||
}
|
||||
|
||||
|
||||
SGNODE* S3D::GetSGNodeParent( SGNODE* aNode )
|
||||
{
|
||||
if( NULL == aNode )
|
||||
return NULL;
|
||||
|
||||
return aNode->GetParent();
|
||||
}
|
||||
|
||||
|
||||
bool S3D::AddSGNodeRef( SGNODE* aParent, SGNODE* aChild )
|
||||
{
|
||||
if( NULL == aParent || NULL == aChild )
|
||||
return false;
|
||||
|
||||
return aParent->AddRefNode( aChild );
|
||||
}
|
||||
|
||||
|
||||
bool S3D::AddSGNodeChild( SGNODE* aParent, SGNODE* aChild )
|
||||
{
|
||||
if( NULL == aParent || NULL == aChild )
|
||||
return false;
|
||||
|
||||
return aParent->AddChildNode( aChild );
|
||||
}
|
||||
|
||||
|
||||
void S3D::AssociateSGNodeWrapper( SGNODE* aObject, SGNODE** aRefPtr )
|
||||
{
|
||||
if( NULL == aObject || NULL == aRefPtr || aObject != *aRefPtr )
|
||||
return;
|
||||
|
||||
aObject->AssociateWrapper( aRefPtr );
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1,472 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
#include "plugins/3dapi/ifsg_appearance.h"
|
||||
#include "3d_cache/sg/sg_appearance.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadOperand[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_APPEARANCE::IFSG_APPEARANCE( bool create )
|
||||
{
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return ;
|
||||
|
||||
m_node = new SGAPPEARANCE( NULL );
|
||||
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_APPEARANCE::IFSG_APPEARANCE( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGAPPEARANCE( NULL );
|
||||
|
||||
if( m_node )
|
||||
{
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_APPEARANCE::IFSG_APPEARANCE( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* pp = aParent.GetRawPtr();
|
||||
|
||||
#ifdef DEBUG
|
||||
if( ! pp )
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
|
||||
m_node = new SGAPPEARANCE( NULL );
|
||||
|
||||
if( m_node )
|
||||
{
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::Attach( SGNODE* aNode )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
|
||||
if( S3D::SGTYPE_APPEARANCE != aNode->GetNodeType() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node = aNode;
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::NewNode( SGNODE* aParent )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = new SGAPPEARANCE( aParent );
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid SGNODE parent (";
|
||||
ostr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||
ostr << ") to SGAPPEARANCE";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return NewNode( np );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetEmissive( float aRVal, float aGVal, float aBVal )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject << "\n";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetEmissive( aRVal, aGVal, aBVal );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetEmissive( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject << "\n";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetEmissive( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetEmissive( const SGCOLOR& aRGBColor )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetEmissive( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetDiffuse( float aRVal, float aGVal, float aBVal )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetDiffuse( aRVal, aGVal, aBVal );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetDiffuse( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetDiffuse( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetDiffuse( const SGCOLOR& aRGBColor )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetDiffuse( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetSpecular( float aRVal, float aGVal, float aBVal )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetSpecular( aRVal, aGVal, aBVal );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetSpecular( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetSpecular( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetSpecular( const SGCOLOR& aRGBColor )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetSpecular( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetAmbient( float aRVal, float aGVal, float aBVal )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetAmbient( aRVal, aGVal, aBVal );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetAmbient( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetAmbient( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetAmbient( const SGCOLOR& aRGBColor )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetAmbient( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetShininess( float aShininess )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( aShininess < 0 || aShininess > 1.0 )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] shininess out of range [0..1]";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGAPPEARANCE*)m_node)->shininess = aShininess;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetTransparency( float aTransparency )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( aTransparency < 0 || aTransparency > 1.0 )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] transparency out of range [0..1]";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGAPPEARANCE*)m_node)->transparency = aTransparency;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,267 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "plugins/3dapi/ifsg_colors.h"
|
||||
#include "3d_cache/sg/sg_colors.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_COLORS::IFSG_COLORS( bool create )
|
||||
{
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return ;
|
||||
|
||||
m_node = new SGCOLORS( NULL );
|
||||
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_COLORS::IFSG_COLORS( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGCOLORS( NULL );
|
||||
|
||||
if( m_node )
|
||||
{
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_COLORS::IFSG_COLORS( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* pp = aParent.GetRawPtr();
|
||||
|
||||
#ifdef DEBUG
|
||||
if( ! pp )
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
|
||||
m_node = new SGCOLORS( NULL );
|
||||
|
||||
if( m_node )
|
||||
{
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COLORS::Attach( SGNODE* aNode )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
|
||||
if( S3D::SGTYPE_COLORS != aNode->GetNodeType() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node = aNode;
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COLORS::NewNode( SGNODE* aParent )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = new SGCOLORS( aParent );
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid SGNODE parent (";
|
||||
ostr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||
ostr << ") to SGCOLORS";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COLORS::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return NewNode( np );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COLORS::GetColorList( size_t& aListSize, SGCOLOR*& aColorList )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGCOLORS*)m_node)->GetColorList( aListSize, aColorList );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COLORS::SetColorList( size_t aListSize, const SGCOLOR* aColorList )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGCOLORS*)m_node)->SetColorList( aListSize, aColorList );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COLORS::AddColor( double aRedValue, double aGreenValue, double aBlueValue )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGCOLORS*)m_node)->AddColor( aRedValue, aGreenValue, aBlueValue );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COLORS::AddColor( const SGCOLOR& aColor )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGCOLORS*)m_node)->AddColor( aColor );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,186 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "plugins/3dapi/ifsg_coordindex.h"
|
||||
#include "3d_cache/sg/sg_coordindex.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadOperand[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_COORDINDEX::IFSG_COORDINDEX( bool create )
|
||||
{
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return;
|
||||
|
||||
m_node = new SGCOORDINDEX( NULL );
|
||||
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_COORDINDEX::IFSG_COORDINDEX( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGCOORDINDEX( NULL );
|
||||
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_COORDINDEX::IFSG_COORDINDEX( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* pp = aParent.GetRawPtr();
|
||||
|
||||
if( !pp )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node = new SGCOORDINDEX( NULL );
|
||||
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COORDINDEX::Attach( SGNODE* aNode )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
|
||||
if( S3D::SGTYPE_COORDINDEX != aNode->GetNodeType() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node = aNode;
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COORDINDEX::NewNode( SGNODE* aParent )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = new SGCOORDINDEX( aParent );
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid SGNODE parent (";
|
||||
ostr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||
ostr << ") to SGCOORDINDEX";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COORDINDEX::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return NewNode( np );
|
||||
}
|
||||
@@ -1,267 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "plugins/3dapi/ifsg_coords.h"
|
||||
#include "3d_cache/sg/sg_coords.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_COORDS::IFSG_COORDS( bool create )
|
||||
{
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return ;
|
||||
|
||||
m_node = new SGCOORDS( NULL );
|
||||
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_COORDS::IFSG_COORDS( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGCOORDS( NULL );
|
||||
|
||||
if( m_node )
|
||||
{
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_COORDS::IFSG_COORDS( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* pp = aParent.GetRawPtr();
|
||||
|
||||
#ifdef DEBUG
|
||||
if( ! pp )
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
|
||||
m_node = new SGCOORDS( NULL );
|
||||
|
||||
if( m_node )
|
||||
{
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COORDS::Attach( SGNODE* aNode )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
|
||||
if( S3D::SGTYPE_COORDS != aNode->GetNodeType() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node = aNode;
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COORDS::NewNode( SGNODE* aParent )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = new SGCOORDS( aParent );
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid SGNODE parent (";
|
||||
ostr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||
ostr << ") to SGCOORDS";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COORDS::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return NewNode( np );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COORDS::GetCoordsList( size_t& aListSize, SGPOINT*& aCoordsList )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGCOORDS*)m_node)->GetCoordsList( aListSize, aCoordsList );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COORDS::SetCoordsList( size_t aListSize, const SGPOINT* aCoordsList )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGCOORDS*)m_node)->SetCoordsList( aListSize, aCoordsList );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COORDS::AddCoord( double aXValue, double aYValue, double aZValue )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGCOORDS*)m_node)->AddCoord( aXValue, aYValue, aZValue );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COORDS::AddCoord( const SGPOINT& aPoint )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGCOORDS*)m_node)->AddCoord( aPoint );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,199 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "plugins/3dapi/ifsg_faceset.h"
|
||||
#include "3d_cache/sg/sg_faceset.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_FACESET::IFSG_FACESET( bool create )
|
||||
{
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return ;
|
||||
|
||||
m_node = new SGFACESET( NULL );
|
||||
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_FACESET::IFSG_FACESET( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGFACESET( NULL );
|
||||
|
||||
if( m_node )
|
||||
{
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_FACESET::IFSG_FACESET( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* pp = aParent.GetRawPtr();
|
||||
|
||||
#ifdef DEBUG
|
||||
if( ! pp )
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
|
||||
m_node = new SGFACESET( NULL );
|
||||
|
||||
if( m_node )
|
||||
{
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_FACESET::Attach( SGNODE* aNode )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
|
||||
if( S3D::SGTYPE_FACESET != aNode->GetNodeType() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node = aNode;
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_FACESET::NewNode( SGNODE* aParent )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = new SGFACESET( aParent );
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid SGNODE parent (";
|
||||
ostr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||
ostr << ") to SGFACESET";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_FACESET::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return NewNode( np );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_FACESET::CalcNormals( SGNODE** aPtr )
|
||||
{
|
||||
if( m_node )
|
||||
return ((SGFACESET*)m_node)->CalcNormals( aPtr );
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "plugins/3dapi/ifsg_index.h"
|
||||
#include "3d_cache/sg/sg_coordindex.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadOperand[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_INDEX::IFSG_INDEX() : IFSG_NODE()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_INDEX::GetIndices( size_t& nIndices, int*& aIndexList )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGINDEX*)m_node)->GetIndices( nIndices, aIndexList );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_INDEX::SetIndices( size_t nIndices, int* aIndexList )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGINDEX*)m_node)->SetIndices( nIndices, aIndexList );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_INDEX::AddIndex( int aIndex )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGINDEX*)m_node)->AddIndex( aIndex );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,296 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "plugins/3dapi/ifsg_node.h"
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
#include "plugins/3dapi/ifsg_api.h"
|
||||
|
||||
// collection of common error strings used by the wrappers
|
||||
char BadObject[] = " * [BUG] operating on an invalid wrapper (object may have been deleted)";
|
||||
char BadOperand[] = " * [BUG] parameter aNode is an invalid wrapper; its data may have been deleted";
|
||||
char BadParent[] = " * [BUG] invalid parent node (data may have been deleted)";
|
||||
char WrongParent[] = " * [BUG] parent node type is incompatible";
|
||||
|
||||
IFSG_NODE::IFSG_NODE()
|
||||
{
|
||||
m_node = NULL;
|
||||
}
|
||||
|
||||
|
||||
IFSG_NODE::~IFSG_NODE()
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void IFSG_NODE::Destroy( void )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGNODE* IFSG_NODE::GetRawPtr( void )
|
||||
{
|
||||
return m_node;
|
||||
}
|
||||
|
||||
|
||||
S3D::SGTYPES IFSG_NODE::GetNodeType( void ) const
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return S3D::SGTYPE_END;
|
||||
}
|
||||
|
||||
return m_node->GetNodeType();
|
||||
}
|
||||
|
||||
|
||||
SGNODE* IFSG_NODE::GetParent( void ) const
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m_node->GetParent();
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NODE::SetParent( SGNODE* aParent )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_node->SetParent( aParent );
|
||||
}
|
||||
|
||||
|
||||
const char* IFSG_NODE::GetName( void )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m_node->GetName();
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NODE::SetName( const char *aName )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node->SetName( aName );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
const char * IFSG_NODE::GetNodeTypeName( S3D::SGTYPES aNodeType ) const
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m_node->GetNodeTypeName( aNodeType );
|
||||
}
|
||||
|
||||
|
||||
SGNODE* IFSG_NODE::FindNode( const char *aNodeName )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m_node->FindNode( aNodeName, NULL );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NODE::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_node->AddRefNode( aNode );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NODE::AddRefNode( IFSG_NODE& aNode )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = aNode.GetRawPtr();
|
||||
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadOperand;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_node->AddRefNode( np );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NODE::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_node->AddChildNode( aNode );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NODE::AddChildNode( IFSG_NODE& aNode )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = aNode.GetRawPtr();
|
||||
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadOperand;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_node->AddChildNode( np );
|
||||
}
|
||||
@@ -1,266 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "plugins/3dapi/ifsg_normals.h"
|
||||
#include "3d_cache/sg/sg_normals.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadOperand[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_NORMALS::IFSG_NORMALS( bool create )
|
||||
{
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return;
|
||||
|
||||
m_node = new SGNORMALS( NULL );
|
||||
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_NORMALS::IFSG_NORMALS( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGNORMALS( NULL );
|
||||
|
||||
if( m_node )
|
||||
{
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_NORMALS::IFSG_NORMALS( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* pp = aParent.GetRawPtr();
|
||||
|
||||
#ifdef DEBUG
|
||||
if( ! pp )
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
|
||||
m_node = new SGNORMALS( NULL );
|
||||
|
||||
if( m_node )
|
||||
{
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NORMALS::Attach( SGNODE* aNode )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
|
||||
if( S3D::SGTYPE_NORMALS != aNode->GetNodeType() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node = aNode;
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NORMALS::NewNode( SGNODE* aParent )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = new SGNORMALS( aParent );
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid SGNODE parent (";
|
||||
ostr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||
ostr << ") to SGNORMALS";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NORMALS::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return NewNode( np );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NORMALS::GetNormalList( size_t& aListSize, SGVECTOR*& aNormalList )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGNORMALS*)m_node)->GetNormalList( aListSize, aNormalList );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NORMALS::SetNormalList( size_t aListSize, const SGVECTOR* aNormalList )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGNORMALS*)m_node)->SetNormalList( aListSize, aNormalList );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NORMALS::AddNormal( double aXValue, double aYValue, double aZValue )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGNORMALS*)m_node)->AddNormal( aXValue, aYValue, aZValue );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NORMALS::AddNormal( const SGVECTOR& aNormal )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGNORMALS*)m_node)->AddNormal( aNormal );
|
||||
return true;
|
||||
}
|
||||
@@ -1,191 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "plugins/3dapi/ifsg_shape.h"
|
||||
#include "3d_cache/sg/sg_shape.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadOperand[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_SHAPE::IFSG_SHAPE( bool create )
|
||||
{
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return ;
|
||||
|
||||
m_node = new SGSHAPE( NULL );
|
||||
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_SHAPE::IFSG_SHAPE( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGSHAPE( NULL );
|
||||
|
||||
if( m_node )
|
||||
{
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_SHAPE::IFSG_SHAPE( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* pp = aParent.GetRawPtr();
|
||||
|
||||
#ifdef DEBUG
|
||||
if( ! pp )
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
|
||||
m_node = new SGSHAPE( NULL );
|
||||
|
||||
if( m_node )
|
||||
{
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_SHAPE::Attach( SGNODE* aNode )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
|
||||
if( S3D::SGTYPE_SHAPE != aNode->GetNodeType() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node = aNode;
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_SHAPE::NewNode( SGNODE* aParent )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = new SGSHAPE( aParent );
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid SGNODE parent (";
|
||||
ostr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||
ostr << ") to SGSHAPE";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_SHAPE::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return NewNode( np );
|
||||
}
|
||||
@@ -1,284 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "plugins/3dapi/ifsg_transform.h"
|
||||
#include "3d_cache/sg/scenegraph.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadOperand[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
IFSG_TRANSFORM::IFSG_TRANSFORM( bool create )
|
||||
{
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return;
|
||||
|
||||
m_node = new SCENEGRAPH( NULL );
|
||||
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_TRANSFORM::IFSG_TRANSFORM( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SCENEGRAPH( NULL );
|
||||
|
||||
if( m_node )
|
||||
{
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_TRANSFORM::Attach( SGNODE* aNode )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
|
||||
if( S3D::SGTYPE_TRANSFORM != aNode->GetNodeType() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node = aNode;
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_TRANSFORM::NewNode( SGNODE* aParent )
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = new SCENEGRAPH( aParent );
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid SGNODE parent (";
|
||||
ostr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||
ostr << ") to SCENEGRAPH";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_TRANSFORM::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return NewNode( np );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_TRANSFORM::SetRotation( const SGVECTOR& aRotationAxis, double aAngle )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SCENEGRAPH*)m_node)->rotation_axis = aRotationAxis;
|
||||
((SCENEGRAPH*)m_node)->rotation_angle = aAngle;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_TRANSFORM::SetScale( const SGPOINT& aScale )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SCENEGRAPH*)m_node)->scale = aScale;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_TRANSFORM::SetScale( double aScale )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( aScale < 1e-8 && aScale > -1e-8 )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] |scale| is < 1e-8 - this seems strange";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SCENEGRAPH*)m_node)->scale = SGPOINT( aScale, aScale, aScale );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_TRANSFORM::SetTranslation( const SGPOINT& aTranslation )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SCENEGRAPH*)m_node)->translation = aTranslation;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_TRANSFORM::SetScaleOrientation( const SGVECTOR& aScaleAxis, double aAngle )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SCENEGRAPH*)m_node)->scale_axis = aScaleAxis;
|
||||
((SCENEGRAPH*)m_node)->scale_angle = aAngle;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_TRANSFORM::SetCenter( const SGPOINT& aCenter )
|
||||
{
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SCENEGRAPH*)m_node)->center = aCenter;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,817 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#define GLM_FORCE_RADIANS
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/ext.hpp>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "3d_cache/sg/scenegraph.h"
|
||||
#include "3d_cache/sg/sg_shape.h"
|
||||
#include "3d_cache/sg/sg_helpers.h"
|
||||
|
||||
|
||||
SCENEGRAPH::SCENEGRAPH( SGNODE* aParent ) : SGNODE( aParent )
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_TRANSFORM;
|
||||
rotation_angle = 0.0;
|
||||
scale_angle = 0.0;
|
||||
|
||||
scale.x = 1.0;
|
||||
scale.y = 1.0;
|
||||
scale.z = 1.0;
|
||||
|
||||
if( NULL != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] inappropriate parent to SCENEGRAPH (type ";
|
||||
ostr << aParent->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
else if( NULL != aParent && S3D::SGTYPE_TRANSFORM == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SCENEGRAPH::~SCENEGRAPH()
|
||||
{
|
||||
// drop references
|
||||
DROP_REFS( SCENEGRAPH, m_RTransforms );
|
||||
DROP_REFS( SGSHAPE, m_RShape );
|
||||
|
||||
// delete owned objects
|
||||
DEL_OBJS( SCENEGRAPH, m_Transforms );
|
||||
DEL_OBJS( SGSHAPE, m_Shape );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SCENEGRAPH::SetParent( SGNODE* aParent, bool notify )
|
||||
{
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
|
||||
// handle the change in parents
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = NULL;
|
||||
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a transform may be parent to a transform
|
||||
if( NULL != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
|
||||
if( m_Parent )
|
||||
m_Parent->AddChildNode( this );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SCENEGRAPH::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
FIND_NODE( SCENEGRAPH, aNodeName, m_Transforms, aCaller );
|
||||
FIND_NODE( SGSHAPE, aNodeName, m_Shape, aCaller );
|
||||
|
||||
// query the parent if appropriate
|
||||
if( aCaller == m_Parent || NULL == m_Parent )
|
||||
return NULL;
|
||||
|
||||
return m_Parent->FindNode( aNodeName, this );
|
||||
}
|
||||
|
||||
|
||||
void SCENEGRAPH::unlinkNode( const SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( NULL == aNode )
|
||||
return;
|
||||
|
||||
switch( aNode->GetNodeType() )
|
||||
{
|
||||
case S3D::SGTYPE_TRANSFORM:
|
||||
UNLINK_NODE( S3D::SGTYPE_TRANSFORM, SCENEGRAPH, aNode, m_Transforms, m_RTransforms, isChild );
|
||||
break;
|
||||
|
||||
case S3D::SGTYPE_SHAPE:
|
||||
UNLINK_NODE( S3D::SGTYPE_SHAPE, SGSHAPE, aNode, m_Shape, m_RShape, isChild );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unlinkNode() did not find its target";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SCENEGRAPH::unlinkChildNode( const SGNODE* aNode )
|
||||
{
|
||||
unlinkNode( aNode, true );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SCENEGRAPH::unlinkRefNode( const SGNODE* aNode )
|
||||
{
|
||||
unlinkNode( aNode, false );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SCENEGRAPH::addNode( SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( NULL == aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aNode";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ADD_NODE( S3D::SGTYPE_TRANSFORM, SCENEGRAPH, aNode, m_Transforms, m_RTransforms, isChild );
|
||||
ADD_NODE( S3D::SGTYPE_SHAPE, SGSHAPE, aNode, m_Shape, m_RShape, isChild );
|
||||
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] object '" << aNode->GetName();
|
||||
ostr << "' is not a valid type for this object (" << aNode->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SCENEGRAPH::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
return addNode( aNode, false );
|
||||
}
|
||||
|
||||
|
||||
bool SCENEGRAPH::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
return addNode( aNode, true );
|
||||
}
|
||||
|
||||
|
||||
void SCENEGRAPH::ReNameNodes( void )
|
||||
{
|
||||
m_written = false;
|
||||
|
||||
// rename this node
|
||||
m_Name.clear();
|
||||
GetName();
|
||||
|
||||
// rename all shapes
|
||||
do
|
||||
{
|
||||
std::vector< SGSHAPE* >::iterator sL = m_Shape.begin();
|
||||
std::vector< SGSHAPE* >::iterator eL = m_Shape.end();
|
||||
|
||||
while( sL != eL )
|
||||
{
|
||||
(*sL)->ReNameNodes();
|
||||
++sL;
|
||||
}
|
||||
|
||||
} while(0);
|
||||
|
||||
// rename all transforms
|
||||
do
|
||||
{
|
||||
std::vector< SCENEGRAPH* >::iterator sL = m_Transforms.begin();
|
||||
std::vector< SCENEGRAPH* >::iterator eL = m_Transforms.end();
|
||||
|
||||
while( sL != eL )
|
||||
{
|
||||
(*sL)->ReNameNodes();
|
||||
++sL;
|
||||
}
|
||||
|
||||
} while(0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SCENEGRAPH::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
{
|
||||
if( m_Transforms.empty() && m_RTransforms.empty()
|
||||
&& m_Shape.empty() && m_RShape.empty() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string tmp;
|
||||
|
||||
if( aReuseFlag )
|
||||
{
|
||||
if( !m_written )
|
||||
{
|
||||
aFile << "DEF " << GetName() << " Transform {\n";
|
||||
m_written = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
aFile << "USE " << GetName() << "\n";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aFile << " Transform {\n";
|
||||
}
|
||||
|
||||
// convert center to 1VRML unit = 0.1 inch
|
||||
SGPOINT pt = center;
|
||||
pt.x /= 2.54;
|
||||
pt.y /= 2.54;
|
||||
pt.z /= 2.54;
|
||||
|
||||
S3D::FormatPoint( tmp, pt );
|
||||
aFile << " center " << tmp << "\n";
|
||||
S3D::FormatOrientation( tmp, rotation_axis, rotation_angle );
|
||||
aFile << " rotation " << tmp << "\n";
|
||||
S3D::FormatPoint( tmp, scale );
|
||||
aFile << " scale " << tmp << "\n";
|
||||
S3D::FormatOrientation( tmp, scale_axis, scale_angle );
|
||||
aFile << " scaleOrientation " << tmp << "\n";
|
||||
|
||||
// convert translation to 1VRML unit = 0.1 inch
|
||||
pt = translation;
|
||||
pt.x /= 2.54;
|
||||
pt.y /= 2.54;
|
||||
pt.z /= 2.54;
|
||||
S3D::FormatPoint( tmp, pt );
|
||||
aFile << " translation " << tmp << "\n";
|
||||
|
||||
aFile << " children [\n";
|
||||
|
||||
if( !m_Transforms.empty() )
|
||||
{
|
||||
std::vector< SCENEGRAPH* >::iterator sL = m_Transforms.begin();
|
||||
std::vector< SCENEGRAPH* >::iterator eL = m_Transforms.end();
|
||||
|
||||
while( sL != eL )
|
||||
{
|
||||
(*sL)->WriteVRML( aFile, aReuseFlag );
|
||||
++sL;
|
||||
}
|
||||
}
|
||||
|
||||
if( !m_RTransforms.empty() )
|
||||
{
|
||||
std::vector< SCENEGRAPH* >::iterator sL = m_RTransforms.begin();
|
||||
std::vector< SCENEGRAPH* >::iterator eL = m_RTransforms.end();
|
||||
|
||||
while( sL != eL )
|
||||
{
|
||||
(*sL)->WriteVRML( aFile, aReuseFlag );
|
||||
++sL;
|
||||
}
|
||||
}
|
||||
|
||||
if( !m_Shape.empty() )
|
||||
{
|
||||
std::vector< SGSHAPE* >::iterator sL = m_Shape.begin();
|
||||
std::vector< SGSHAPE* >::iterator eL = m_Shape.end();
|
||||
|
||||
while( sL != eL )
|
||||
{
|
||||
(*sL)->WriteVRML( aFile, aReuseFlag );
|
||||
++sL;
|
||||
}
|
||||
}
|
||||
|
||||
if( !m_RShape.empty() )
|
||||
{
|
||||
std::vector< SGSHAPE* >::iterator sL = m_RShape.begin();
|
||||
std::vector< SGSHAPE* >::iterator eL = m_RShape.end();
|
||||
|
||||
while( sL != eL )
|
||||
{
|
||||
(*sL)->WriteVRML( aFile, aReuseFlag );
|
||||
++sL;
|
||||
}
|
||||
}
|
||||
|
||||
aFile << "] }\n";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SCENEGRAPH::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( NULL == parentNode && NULL != m_Parent )
|
||||
{
|
||||
SGNODE* np = m_Parent;
|
||||
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( parentNode != m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; parentNode != m_aParent";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
// ensure unique node names
|
||||
ResetNodeIndex();
|
||||
ReNameNodes();
|
||||
}
|
||||
|
||||
if( aFile.fail() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
aFile << "[" << GetName() << "]";
|
||||
S3D::WritePoint( aFile, center );
|
||||
S3D::WritePoint( aFile, translation );
|
||||
S3D::WriteVector( aFile, rotation_axis );
|
||||
aFile.write( (char*)&rotation_angle, sizeof( rotation_angle ) );
|
||||
S3D::WritePoint( aFile, scale );
|
||||
S3D::WriteVector( aFile, scale_axis );
|
||||
aFile.write( (char*)&scale_angle, sizeof( scale_angle ) );
|
||||
|
||||
// Transfer ownership of any Transform references which hadn't been written
|
||||
size_t asize = m_RTransforms.size();
|
||||
size_t i;
|
||||
|
||||
for( i = 0; i < asize; ++i )
|
||||
{
|
||||
if( !m_RTransforms[i]->isWritten() )
|
||||
{
|
||||
m_RTransforms[i]->SwapParent( this );
|
||||
--asize;
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
||||
// Transfer ownership of any Shape references which hadn't been written
|
||||
asize = m_RShape.size();
|
||||
|
||||
for( i = 0; i < asize; ++i )
|
||||
{
|
||||
if( !m_RShape[i]->isWritten() )
|
||||
{
|
||||
m_RShape[i]->SwapParent( this );
|
||||
--asize;
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
||||
asize = m_Transforms.size();
|
||||
aFile.write( (char*)&asize, sizeof( size_t ) );
|
||||
asize = m_RTransforms.size();
|
||||
aFile.write( (char*)&asize, sizeof( size_t ) );
|
||||
asize = m_Shape.size();
|
||||
aFile.write( (char*)&asize, sizeof( size_t ) );
|
||||
asize = m_RShape.size();
|
||||
aFile.write( (char*)&asize, sizeof( size_t ) );
|
||||
asize = m_Transforms.size();
|
||||
|
||||
// write child transforms
|
||||
for( i = 0; i < asize; ++i )
|
||||
{
|
||||
if( !m_Transforms[i]->WriteCache( aFile, this ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream while writing child transforms";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// write referenced transform names
|
||||
asize = m_RTransforms.size();
|
||||
for( i = 0; i < asize; ++i )
|
||||
aFile << "[" << m_RTransforms[i]->GetName() << "]";
|
||||
|
||||
// write child shapes
|
||||
asize = m_Shape.size();
|
||||
for( i = 0; i < asize; ++i )
|
||||
{
|
||||
if( !m_Shape[i]->WriteCache( aFile, this ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream while writing child shapes";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// write referenced transform names
|
||||
asize = m_RShape.size();
|
||||
for( i = 0; i < asize; ++i )
|
||||
aFile << "[" << m_RShape[i]->GetName() << "]";
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
m_written = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( !m_Transforms.empty() || !m_RTransforms.empty()
|
||||
|| !m_Shape.empty() || !m_RShape.empty() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] non-empty node";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string name; // name of the node
|
||||
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
// we need to read the tag and verify its type
|
||||
if( S3D::SGTYPE_TRANSFORM != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; tag mismatch at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
m_Name = name;
|
||||
}
|
||||
|
||||
// read fixed member data
|
||||
S3D::ReadPoint( aFile, center );
|
||||
S3D::ReadPoint( aFile, translation );
|
||||
S3D::ReadVector( aFile, rotation_axis );
|
||||
aFile.read( (char*)&rotation_angle, sizeof( rotation_angle ) );
|
||||
S3D::ReadPoint( aFile, scale );
|
||||
S3D::ReadVector( aFile, scale_axis );
|
||||
aFile.read( (char*)&scale_angle, sizeof( scale_angle ) );
|
||||
|
||||
size_t sizeCT = 0; // child transforms
|
||||
size_t sizeRT = 0; // referenced transforms
|
||||
size_t sizeCS = 0; // child shapes
|
||||
size_t sizeRS = 0; // referenced shapes
|
||||
|
||||
aFile.read( (char*)&sizeCT, sizeof( size_t ) );
|
||||
aFile.read( (char*)&sizeRT, sizeof( size_t ) );
|
||||
aFile.read( (char*)&sizeCS, sizeof( size_t ) );
|
||||
aFile.read( (char*)&sizeRS, sizeof( size_t ) );
|
||||
|
||||
size_t i;
|
||||
|
||||
// read child transforms
|
||||
for( i = 0; i < sizeCT; ++i )
|
||||
{
|
||||
if( S3D::SGTYPE_TRANSFORM != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad child transform tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SCENEGRAPH* sp = new SCENEGRAPH( this );
|
||||
sp->SetName( name.c_str() );
|
||||
|
||||
if( !sp->ReadCache( aFile, this ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data while reading transform '";
|
||||
ostr << name << "' pos " << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// read referenced transforms
|
||||
for( i = 0; i < sizeRT; ++i )
|
||||
{
|
||||
if( S3D::SGTYPE_TRANSFORM != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad ref transform tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* sp = FindNode( name.c_str(), this );
|
||||
|
||||
if( !sp )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: cannot find ref transform '";
|
||||
ostr << name << "' pos " << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_TRANSFORM != sp->GetNodeType() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: type is not TRANSFORM '";
|
||||
ostr << name << "' pos " << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
AddRefNode( sp );
|
||||
}
|
||||
|
||||
// read child shapes
|
||||
for( i = 0; i < sizeCS; ++i )
|
||||
{
|
||||
if( S3D::SGTYPE_SHAPE != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad child shape tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGSHAPE* sp = new SGSHAPE( this );
|
||||
sp->SetName( name.c_str() );
|
||||
|
||||
if( !sp->ReadCache( aFile, this ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data while reading shape '";
|
||||
ostr << name << "' pos " << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// read referenced shapes
|
||||
for( i = 0; i < sizeRS; ++i )
|
||||
{
|
||||
if( S3D::SGTYPE_SHAPE != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad ref shape tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* sp = FindNode( name.c_str(), this );
|
||||
|
||||
if( !sp )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: cannot find ref shape '";
|
||||
ostr << name << "' pos " << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_SHAPE != sp->GetNodeType() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: type is not SGSHAPE '";
|
||||
ostr << name << "' pos " << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
AddRefNode( sp );
|
||||
}
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SCENEGRAPH::Prepare( const glm::dmat4* aTransform,
|
||||
S3D::MATLIST& materials, std::vector< SMESH >& meshes )
|
||||
{
|
||||
// calculate the accumulated transform
|
||||
double rX, rY, rZ;
|
||||
// rotation
|
||||
rotation_axis.GetVector( rX, rY, rZ );
|
||||
glm::dmat4 rM = glm::rotate( glm::dmat4( 1.0 ), rotation_angle, glm::dvec3( rX, rY, rZ ) );
|
||||
// translation
|
||||
glm::dmat4 tM = glm::translate( glm::dmat4( 1.0 ), glm::dvec3( translation.x, translation.y, translation.z ) );
|
||||
// center
|
||||
glm::dmat4 cM = glm::translate( glm::dmat4( 1.0 ), glm::dvec3( center.x, center.y, center.z ) );
|
||||
glm::dmat4 ncM = glm::translate( glm::dmat4( 1.0 ), glm::dvec3( -center.x, -center.y, -center.z ) );
|
||||
// scale
|
||||
glm::dmat4 sM = glm::scale( glm::dmat4( 1.0 ), glm::dvec3( scale.x, scale.y, scale.z ) );
|
||||
// scaleOrientation
|
||||
scale_axis.GetVector( rX, rY, rZ );
|
||||
glm::dmat4 srM = glm::rotate( glm::dmat4( 1.0 ), scale_angle, glm::dvec3( rX, rY, rZ ) );
|
||||
glm::dmat4 nsrM = glm::rotate( glm::dmat4( 1.0 ), -scale_angle, glm::dvec3( rX, rY, rZ ) );
|
||||
|
||||
// resultant point:
|
||||
// P' = T x C x R x SR x S x -SR x -C x P
|
||||
// resultant transform:
|
||||
// tx0 = tM * cM * rM * srM * sM * nsrM * ncM
|
||||
glm::dmat4 tx0;
|
||||
|
||||
if( NULL != aTransform )
|
||||
tx0 = (*aTransform) * tM * cM * rM * srM * sM * nsrM * ncM;
|
||||
else
|
||||
tx0 = tM * cM * rM * srM * sM * nsrM * ncM;
|
||||
|
||||
bool ok = true;
|
||||
|
||||
// prepare all shapes
|
||||
do
|
||||
{
|
||||
std::vector< SGSHAPE* >::iterator sL = m_Shape.begin();
|
||||
std::vector< SGSHAPE* >::iterator eL = m_Shape.end();
|
||||
|
||||
while( sL != eL && ok )
|
||||
{
|
||||
ok = (*sL)->Prepare( &tx0, materials, meshes );
|
||||
++sL;
|
||||
}
|
||||
|
||||
sL = m_RShape.begin();
|
||||
eL = m_RShape.end();
|
||||
|
||||
while( sL != eL && ok )
|
||||
{
|
||||
ok = (*sL)->Prepare( &tx0, materials, meshes );
|
||||
++sL;
|
||||
}
|
||||
|
||||
} while(0);
|
||||
|
||||
// prepare all transforms
|
||||
do
|
||||
{
|
||||
std::vector< SCENEGRAPH* >::iterator sL = m_Transforms.begin();
|
||||
std::vector< SCENEGRAPH* >::iterator eL = m_Transforms.end();
|
||||
|
||||
while( sL != eL && ok )
|
||||
{
|
||||
ok = (*sL)->Prepare( &tx0, materials, meshes );
|
||||
++sL;
|
||||
}
|
||||
|
||||
sL = m_RTransforms.begin();
|
||||
eL = m_RTransforms.end();
|
||||
|
||||
while( sL != eL && ok )
|
||||
{
|
||||
ok = (*sL)->Prepare( &tx0, materials, meshes );
|
||||
++sL;
|
||||
}
|
||||
|
||||
} while(0);
|
||||
|
||||
return ok;
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file scenegraph.h
|
||||
* defines the basic data set required to represent a 3D model;
|
||||
* this model must remain compatible with VRML2.0 in order to
|
||||
* facilitate VRML export of scene graph data created by available
|
||||
* 3D plugins.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SCENE_GRAPH_H
|
||||
#define SCENE_GRAPH_H
|
||||
|
||||
#include <vector>
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
|
||||
class SGSHAPE;
|
||||
|
||||
class SCENEGRAPH : public SGNODE
|
||||
{
|
||||
private:
|
||||
// The following are items which may be defined for reuse
|
||||
// in a VRML output file. They do not necessarily correspond
|
||||
// to the use of DEF within a VRML input file; it is the
|
||||
// responsibility of the plugin to perform any necessary
|
||||
// conversions to comply with the restrictions imposed by
|
||||
// this scene graph structure
|
||||
std::vector< SCENEGRAPH* > m_Transforms; // local Transform nodes
|
||||
std::vector< SGSHAPE* > m_Shape; // local Shape nodes
|
||||
|
||||
std::vector< SCENEGRAPH* > m_RTransforms; // referenced Transform nodes
|
||||
std::vector< SGSHAPE* > m_RShape; // referenced Shape nodes
|
||||
|
||||
void unlinkNode( const SGNODE* aNode, bool isChild );
|
||||
bool addNode( SGNODE* aNode, bool isChild );
|
||||
|
||||
public:
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
|
||||
public:
|
||||
// note: order of transformation is Translate, Rotate, Offset
|
||||
SGPOINT center;
|
||||
SGPOINT translation;
|
||||
SGVECTOR rotation_axis;
|
||||
double rotation_angle; // radians
|
||||
SGPOINT scale;
|
||||
SGVECTOR scale_axis;
|
||||
double scale_angle; // radians
|
||||
|
||||
SCENEGRAPH( SGNODE* aParent );
|
||||
virtual ~SCENEGRAPH();
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) override;
|
||||
bool AddRefNode( SGNODE* aNode ) override;
|
||||
bool AddChildNode( SGNODE* aNode ) override;
|
||||
|
||||
void ReNameNodes( void ) override;
|
||||
bool WriteVRML( std::ostream& aFile, bool aReuseFlag ) override;
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
|
||||
bool Prepare( const glm::dmat4* aTransform,
|
||||
S3D::MATLIST& materials, std::vector< SMESH >& meshes );
|
||||
};
|
||||
|
||||
/*
|
||||
p.120
|
||||
Transform {
|
||||
center 0 0 0
|
||||
children []
|
||||
rotation 0 0 1 0
|
||||
scale 1 1 1
|
||||
scaleOrientation 0 0 1 0
|
||||
translation 0 0 0
|
||||
bboxCenter 0 0 0
|
||||
bboxSize -1 -1 -1
|
||||
}
|
||||
*/
|
||||
|
||||
#endif // SCENE_GRAPH_H
|
||||
@@ -1,452 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "3d_cache/sg/sg_appearance.h"
|
||||
#include "3d_cache/sg/sg_helpers.h"
|
||||
|
||||
SGAPPEARANCE::SGAPPEARANCE( SGNODE* aParent ) : SGNODE( aParent)
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_APPEARANCE;
|
||||
|
||||
// defaults in accord with VRML2.0 spec
|
||||
ambient.SetColor( 0.05317, 0.17879, 0.01804 );
|
||||
shininess = 0.2;
|
||||
transparency = 0.0;
|
||||
diffuse.SetColor( 0.8, 0.8, 0.8 );
|
||||
|
||||
if( NULL != aParent && S3D::SGTYPE_SHAPE != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] inappropriate parent to SGAPPEARANCE (type ";
|
||||
ostr << aParent->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
else if( NULL != aParent && S3D::SGTYPE_SHAPE == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGAPPEARANCE::~SGAPPEARANCE()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::SetParent( SGNODE* aParent, bool notify )
|
||||
{
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
|
||||
// handle the change in parents
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = NULL;
|
||||
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a SGSHAPE may be parent to a SGAPPEARANCE
|
||||
if( NULL != aParent && S3D::SGTYPE_SHAPE != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
|
||||
if( m_Parent )
|
||||
m_Parent->AddChildNode( this );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::SetEmissive( float aRVal, float aGVal, float aBVal )
|
||||
{
|
||||
return emissive.SetColor( aRVal, aGVal, aBVal );
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::SetEmissive( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
if( NULL == aRGBColor )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aRGBColor";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return emissive.SetColor( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::SetEmissive( const SGCOLOR& aRGBColor )
|
||||
{
|
||||
return emissive.SetColor( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::SetDiffuse( float aRVal, float aGVal, float aBVal )
|
||||
{
|
||||
return diffuse.SetColor( aRVal, aGVal, aBVal );
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::SetDiffuse( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
if( NULL == aRGBColor )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aRGBColor";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return diffuse.SetColor( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::SetDiffuse( const SGCOLOR& aRGBColor )
|
||||
{
|
||||
return diffuse.SetColor( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::SetSpecular( float aRVal, float aGVal, float aBVal )
|
||||
{
|
||||
return specular.SetColor( aRVal, aGVal, aBVal );
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::SetSpecular( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
if( NULL == aRGBColor )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aRGBColor";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return specular.SetColor( aRGBColor );
|
||||
}
|
||||
|
||||
bool SGAPPEARANCE::SetSpecular( const SGCOLOR& aRGBColor )
|
||||
{
|
||||
return specular.SetColor( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::SetAmbient( float aRVal, float aGVal, float aBVal )
|
||||
{
|
||||
return ambient.SetColor( aRVal, aGVal, aBVal );
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::SetAmbient( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
if( NULL == aRGBColor )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aRGBColor";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ambient.SetColor( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::SetAmbient( const SGCOLOR& aRGBColor )
|
||||
{
|
||||
return ambient.SetColor( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGAPPEARANCE::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void SGAPPEARANCE::unlinkChildNode( const SGNODE* aCaller )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGAPPEARANCE::unlinkRefNode( const SGNODE* aCaller )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void SGAPPEARANCE::ReNameNodes( void )
|
||||
{
|
||||
m_written = false;
|
||||
|
||||
// rename this node
|
||||
m_Name.clear();
|
||||
GetName();
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
{
|
||||
if( aReuseFlag )
|
||||
{
|
||||
if( !m_written )
|
||||
{
|
||||
aFile << " appearance DEF " << GetName() << " Appearance {\n";
|
||||
m_written = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
aFile << " appearance USE " << GetName() << "\n";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aFile << " appearance Appearance {\n";
|
||||
}
|
||||
|
||||
aFile << " material Material {\n";
|
||||
|
||||
std::string tmp;
|
||||
float ambr, ambg, ambb;
|
||||
ambient.GetColor( ambr, ambg, ambb );
|
||||
float amb = ( 0.212671 * ambr + 0.71516 * ambg + 0.072169 * ambb );
|
||||
diffuse.GetColor( ambr, ambg, ambb );
|
||||
float den = ( 0.212671 * ambr + 0.71516 * ambg + 0.072169 * ambb );
|
||||
|
||||
if( den < 0.004 )
|
||||
den = 0.004;
|
||||
|
||||
amb /= den;
|
||||
|
||||
if( amb > 1.0 )
|
||||
amb = 1.0;
|
||||
|
||||
S3D::FormatFloat( tmp, amb );
|
||||
aFile << " ambientIntensity " << tmp << "\n";
|
||||
|
||||
float red, green, blue;
|
||||
diffuse.GetColor( red, green, blue );
|
||||
S3D::FormatFloat( tmp, red );
|
||||
aFile << " diffuseColor " << tmp << " ";
|
||||
S3D::FormatFloat( tmp, green );
|
||||
aFile << tmp << " ";
|
||||
S3D::FormatFloat( tmp, blue);
|
||||
aFile << tmp << "\n";
|
||||
|
||||
emissive.GetColor( red, green, blue );
|
||||
S3D::FormatFloat( tmp, red );
|
||||
aFile << " emissiveColor " << tmp << " ";
|
||||
S3D::FormatFloat( tmp, green );
|
||||
aFile << tmp << " ";
|
||||
S3D::FormatFloat( tmp, blue);
|
||||
aFile << tmp << "\n";
|
||||
|
||||
S3D::FormatFloat( tmp, shininess );
|
||||
aFile << " shininess " << tmp << "\n";
|
||||
|
||||
specular.GetColor( red, green, blue );
|
||||
S3D::FormatFloat( tmp, red );
|
||||
aFile << " specularColor " << tmp << " ";
|
||||
S3D::FormatFloat( tmp, green );
|
||||
aFile << tmp << " ";
|
||||
S3D::FormatFloat( tmp, blue);
|
||||
aFile << tmp << "\n";
|
||||
|
||||
S3D::FormatFloat( tmp, transparency );
|
||||
aFile << " transparency " << tmp << "\n";
|
||||
|
||||
aFile << "} }\n";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; m_aParent is NULL";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = m_Parent;
|
||||
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( parentNode != m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; parentNode != m_aParent";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !aFile.good() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
aFile << "[" << GetName() << "]";
|
||||
S3D::WriteColor( aFile, ambient );
|
||||
aFile.write( (char*)&shininess, sizeof(shininess) );
|
||||
aFile.write( (char*)&transparency, sizeof(transparency) );
|
||||
S3D::WriteColor( aFile, diffuse );
|
||||
S3D::WriteColor( aFile, emissive );
|
||||
S3D::WriteColor( aFile, specular );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
m_written = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
S3D::ReadColor( aFile, ambient );
|
||||
aFile.read( (char*)&shininess, sizeof(shininess) );
|
||||
aFile.read( (char*)&transparency, sizeof(transparency) );
|
||||
S3D::ReadColor( aFile, diffuse );
|
||||
S3D::ReadColor( aFile, emissive );
|
||||
S3D::ReadColor( aFile, specular );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file sg_appearance.h
|
||||
* defines the generic material appearance of a scenegraph object
|
||||
*/
|
||||
|
||||
#ifndef SG_APPEARANCE_H
|
||||
#define SG_APPEARANCE_H
|
||||
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
|
||||
class SGAPPEARANCE : public SGNODE
|
||||
{
|
||||
public:
|
||||
float shininess; // default 0.2
|
||||
float transparency; // default 0.0
|
||||
SGCOLOR ambient; // default 0.05317 0.17879 0.01804
|
||||
SGCOLOR diffuse; // default 0.8 0.8 0.8
|
||||
SGCOLOR emissive; // default 0.0 0.0 0.0
|
||||
SGCOLOR specular; // default 0.0 0.0 0.0
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
|
||||
public:
|
||||
SGAPPEARANCE( SGNODE* aParent );
|
||||
virtual ~SGAPPEARANCE();
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
|
||||
bool SetEmissive( float aRVal, float aGVal, float aBVal );
|
||||
bool SetEmissive( const SGCOLOR* aRGBColor );
|
||||
bool SetEmissive( const SGCOLOR& aRGBColor );
|
||||
|
||||
bool SetDiffuse( float aRVal, float aGVal, float aBVal );
|
||||
bool SetDiffuse( const SGCOLOR* aRGBColor );
|
||||
bool SetDiffuse( const SGCOLOR& aRGBColor );
|
||||
|
||||
bool SetSpecular( float aRVal, float aGVal, float aBVal );
|
||||
bool SetSpecular( const SGCOLOR* aRGBColor );
|
||||
bool SetSpecular( const SGCOLOR& aRGBColor );
|
||||
|
||||
bool SetAmbient( float aRVal, float aGVal, float aBVal );
|
||||
bool SetAmbient( const SGCOLOR* aRGBColor );
|
||||
bool SetAmbient( const SGCOLOR& aRGBColor );
|
||||
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) override;
|
||||
bool AddRefNode( SGNODE* aNode ) override;
|
||||
bool AddChildNode( SGNODE* aNode ) override;
|
||||
|
||||
void ReNameNodes( void ) override;
|
||||
bool WriteVRML( std::ostream& aFile, bool aReuseFlag ) override;
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
};
|
||||
|
||||
#endif // SG_APPEARANCE_H
|
||||
@@ -1,340 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "plugins/3dapi/sg_base.h"
|
||||
|
||||
|
||||
SGCOLOR::SGCOLOR()
|
||||
{
|
||||
red = 0.0;
|
||||
green = 0.0;
|
||||
blue = 0.0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SGCOLOR::SGCOLOR( float aRVal, float aGVal, float aBVal )
|
||||
{
|
||||
if( !checkRange( aRVal, aGVal, aBVal ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid value passed to constructor";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
red = 0.0;
|
||||
green = 0.0;
|
||||
blue = 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
red = aRVal;
|
||||
green = aGVal;
|
||||
blue = aBVal;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOLOR::GetColor( float& aRedVal, float& aGreenVal, float& aBlueVal ) const
|
||||
{
|
||||
aRedVal = red;
|
||||
aGreenVal = green;
|
||||
aBlueVal = blue;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOLOR::GetColor( SGCOLOR& aColor ) const
|
||||
{
|
||||
aColor.red = red;
|
||||
aColor.green = green;
|
||||
aColor.blue = blue;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOLOR::GetColor( SGCOLOR* aColor ) const
|
||||
{
|
||||
if( NULL == aColor )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aColor";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
aColor->red = red;
|
||||
aColor->green = green;
|
||||
aColor->blue = blue;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLOR::SetColor( float aRedVal, float aGreenVal, float aBlueVal )
|
||||
{
|
||||
if( !checkRange( aRedVal, aGreenVal, aBlueVal ) )
|
||||
return false;
|
||||
|
||||
red = aRedVal;
|
||||
green = aGreenVal;
|
||||
blue = aBlueVal;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLOR::SetColor( const SGCOLOR& aColor )
|
||||
{
|
||||
red = aColor.red;
|
||||
green = aColor.green;
|
||||
blue = aColor.blue;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLOR::SetColor( const SGCOLOR* aColor )
|
||||
{
|
||||
if( NULL == aColor )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aColor";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
red = aColor->red;
|
||||
green = aColor->green;
|
||||
blue = aColor->blue;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLOR::checkRange( float aRedVal, float aGreenVal, float aBlueVal ) const
|
||||
{
|
||||
bool ok = true;
|
||||
|
||||
if( aRedVal < 0.0 || aRedVal > 1.0 )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid RED value: " << aRedVal;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
ok = false;
|
||||
}
|
||||
|
||||
if( aGreenVal < 0.0 || aGreenVal > 1.0 )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if( ok )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, "%s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__ );
|
||||
}
|
||||
wxLogTrace( MASK_3D_SG, " * [BUG] invalid GREEN value: %f\n", aGreenVal );
|
||||
#endif
|
||||
ok = false;
|
||||
}
|
||||
|
||||
if( aBlueVal < 0.0 || aBlueVal > 1.0 )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if( ok )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, "%s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__ );
|
||||
}
|
||||
wxLogTrace( MASK_3D_SG, " * [BUG] invalid BLUE value: %f\n", aBlueVal );
|
||||
#endif
|
||||
ok = false;
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
SGPOINT::SGPOINT()
|
||||
{
|
||||
x = 0.0;
|
||||
y = 0.0;
|
||||
z = 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGPOINT::SGPOINT( double aXVal, double aYVal, double aZVal )
|
||||
{
|
||||
x = aXVal;
|
||||
y = aYVal;
|
||||
z = aZVal;
|
||||
}
|
||||
|
||||
|
||||
void SGPOINT::GetPoint( double& aXVal, double& aYVal, double& aZVal )
|
||||
{
|
||||
x = aXVal;
|
||||
y = aYVal;
|
||||
z = aZVal;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGPOINT::GetPoint( SGPOINT& aPoint )
|
||||
{
|
||||
x = aPoint.x;
|
||||
y = aPoint.y;
|
||||
z = aPoint.z;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGPOINT::GetPoint( SGPOINT* aPoint )
|
||||
{
|
||||
if( NULL == aPoint )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aPoint";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
x = aPoint->x;
|
||||
y = aPoint->y;
|
||||
z = aPoint->z;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGPOINT::SetPoint( double aXVal, double aYVal, double aZVal )
|
||||
{
|
||||
x = aXVal;
|
||||
y = aYVal;
|
||||
z = aZVal;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGPOINT::SetPoint( const SGPOINT& aPoint )
|
||||
{
|
||||
x = aPoint.x;
|
||||
y = aPoint.y;
|
||||
z = aPoint.z;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGVECTOR::SGVECTOR()
|
||||
{
|
||||
vx = 0.0;
|
||||
vy = 0.0;
|
||||
vz = 1.0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGVECTOR::SGVECTOR( double aXVal, double aYVal, double aZVal )
|
||||
{
|
||||
vx = aXVal;
|
||||
vy = aYVal;
|
||||
vz = aZVal;
|
||||
normalize();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGVECTOR::GetVector( double& aXVal, double& aYVal, double& aZVal ) const
|
||||
{
|
||||
aXVal = vx;
|
||||
aYVal = vy;
|
||||
aZVal = vz;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGVECTOR::SetVector( double aXVal, double aYVal, double aZVal )
|
||||
{
|
||||
vx = aXVal;
|
||||
vy = aYVal;
|
||||
vz = aZVal;
|
||||
normalize();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGVECTOR::SetVector( const SGVECTOR& aVector )
|
||||
{
|
||||
aVector.GetVector( vx, vy, vz );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGVECTOR::normalize( void )
|
||||
{
|
||||
double dx = vx * vx;
|
||||
double dy = vy * vy;
|
||||
double dz = vz * vz;
|
||||
double dv2 = sqrt( dx + dy + dz );
|
||||
|
||||
if( (dx + dy + dz) < 1e-8 )
|
||||
{
|
||||
// use the default; the numbers are too small
|
||||
// to be believable
|
||||
vx = 0.0;
|
||||
vy = 0.0;
|
||||
vz = 1.0;
|
||||
return;
|
||||
}
|
||||
|
||||
vx /= dv2;
|
||||
vy /= dv2;
|
||||
vz /= dv2;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGVECTOR& SGVECTOR::operator=( const SGVECTOR& source )
|
||||
{
|
||||
vx = source.vx;
|
||||
vy = source.vy;
|
||||
vz = source.vz;
|
||||
return *this;
|
||||
}
|
||||
@@ -1,367 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "3d_cache/sg/sg_colors.h"
|
||||
#include "3d_cache/sg/sg_helpers.h"
|
||||
|
||||
SGCOLORS::SGCOLORS( SGNODE* aParent ) : SGNODE( aParent )
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_COLORS;
|
||||
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] inappropriate parent to SGCOLORS (type ";
|
||||
ostr << aParent->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
else if( NULL != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGCOLORS::~SGCOLORS()
|
||||
{
|
||||
colors.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLORS::SetParent( SGNODE* aParent, bool notify )
|
||||
{
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
|
||||
// handle the change in parents
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = NULL;
|
||||
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a SGFACESET may be parent to a SGCOLORS
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
|
||||
if( m_Parent )
|
||||
m_Parent->AddChildNode( this );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGCOLORS::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void SGCOLORS::unlinkChildNode( const SGNODE* aCaller )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOLORS::unlinkRefNode( const SGNODE* aCaller )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLORS::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLORS::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLORS::GetColorList( size_t& aListSize, SGCOLOR*& aColorList )
|
||||
{
|
||||
if( colors.empty() )
|
||||
{
|
||||
aListSize = 0;
|
||||
aColorList = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
aListSize = colors.size();
|
||||
aColorList = &colors[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void SGCOLORS::SetColorList( size_t aListSize, const SGCOLOR* aColorList )
|
||||
{
|
||||
colors.clear();
|
||||
|
||||
if( 0 == aListSize || NULL == aColorList )
|
||||
return;
|
||||
|
||||
for( size_t i = 0; i < aListSize; ++i )
|
||||
colors.push_back( aColorList[i] );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOLORS::AddColor( double aRedValue, double aGreenValue, double aBlueValue )
|
||||
{
|
||||
colors.push_back( SGCOLOR( aRedValue, aGreenValue, aBlueValue ) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOLORS::AddColor( const SGCOLOR& aColor )
|
||||
{
|
||||
colors.push_back( aColor );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOLORS::ReNameNodes( void )
|
||||
{
|
||||
m_written = false;
|
||||
|
||||
// rename this node
|
||||
m_Name.clear();
|
||||
GetName();
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLORS::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
{
|
||||
if( colors.empty() )
|
||||
return false;
|
||||
|
||||
if( aReuseFlag )
|
||||
{
|
||||
if( !m_written )
|
||||
{
|
||||
aFile << "color DEF " << GetName() << " Color { color [\n ";
|
||||
m_written = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
aFile << "color USE " << GetName() << "\n";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aFile << "color Color { color [\n ";
|
||||
}
|
||||
|
||||
std::string tmp;
|
||||
size_t n = colors.size();
|
||||
bool nline = false;
|
||||
|
||||
for( size_t i = 0; i < n; )
|
||||
{
|
||||
S3D::FormatColor( tmp, colors[i] );
|
||||
float r,g,b;
|
||||
colors[i].GetColor(r, g, b);
|
||||
aFile << tmp ;
|
||||
++i;
|
||||
|
||||
if( i < n )
|
||||
{
|
||||
aFile << ",";
|
||||
|
||||
if( nline )
|
||||
{
|
||||
aFile << "\n ";
|
||||
nline = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
nline = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
aFile << "] }\n";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLORS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; m_aParent is NULL";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = m_Parent;
|
||||
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( parentNode != m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; parentNode != m_aParent";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !aFile.good() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
aFile << "[" << GetName() << "]";
|
||||
size_t ncolors = colors.size();
|
||||
aFile.write( (char*)&ncolors, sizeof(size_t) );
|
||||
|
||||
for( size_t i = 0; i < ncolors; ++i )
|
||||
S3D::WriteColor( aFile, colors[i] );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
m_written = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLORS::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( !colors.empty() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] non-empty node";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t ncolors;
|
||||
aFile.read( (char*)&ncolors, sizeof(size_t) );
|
||||
SGCOLOR tmp;
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
for( size_t i = 0; i < ncolors; ++i )
|
||||
{
|
||||
if( !S3D::ReadColor( aFile, tmp ) || aFile.fail() )
|
||||
return false;
|
||||
|
||||
colors.push_back( tmp );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file sg_colors.h
|
||||
* defines an RGB color set for a scenegraph object
|
||||
*/
|
||||
|
||||
#ifndef SG_COLORS_H
|
||||
#define SG_COLORS_H
|
||||
|
||||
#include <vector>
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
|
||||
class SGCOLORS : public SGNODE
|
||||
{
|
||||
public:
|
||||
std::vector< SGCOLOR > colors;
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
|
||||
public:
|
||||
SGCOLORS( SGNODE* aParent );
|
||||
virtual ~SGCOLORS();
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) override;
|
||||
bool AddRefNode( SGNODE* aNode ) override;
|
||||
bool AddChildNode( SGNODE* aNode ) override;
|
||||
|
||||
bool GetColorList( size_t& aListSize, SGCOLOR*& aColorList );
|
||||
void SetColorList( size_t aListSize, const SGCOLOR* aColorList );
|
||||
void AddColor( double aRedValue, double aGreenValue, double aBlueValue );
|
||||
void AddColor( const SGCOLOR& aColor );
|
||||
|
||||
void ReNameNodes( void ) override;
|
||||
bool WriteVRML( std::ostream& aFile, bool aReuseFlag ) override;
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
};
|
||||
|
||||
#endif // SG_COLORS_H
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "3d_cache/sg/sg_coordindex.h"
|
||||
|
||||
|
||||
SGCOORDINDEX::SGCOORDINDEX( SGNODE* aParent ) : SGINDEX( aParent )
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_COORDINDEX;
|
||||
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGCOORDINDEX::~SGCOORDINDEX()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOORDINDEX::GatherCoordIndices( std::vector< int >& aIndexList )
|
||||
{
|
||||
if( index.empty() )
|
||||
return;
|
||||
|
||||
aIndexList.insert( aIndexList.end(), index.begin(), index.end() );
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file sg_coordindex.h
|
||||
* defines an coordinate index set for a scenegraph object
|
||||
*/
|
||||
|
||||
#ifndef SG_COORDINDEX_H
|
||||
#define SG_COORDINDEX_H
|
||||
|
||||
#include "3d_cache/sg/sg_index.h"
|
||||
|
||||
/**
|
||||
* Class SGCOORDINDEX
|
||||
* is a class which maintains a coordinate index list. Users
|
||||
* must ensure that coordinate indices are specified as
|
||||
* triplets (triangular faces) since no checking is performed.
|
||||
* In instances where it is not possible to determine which
|
||||
* side of the triangle is to be rendered (for example IGES
|
||||
* entities) then the user must supply each triplet in both
|
||||
* point orders.
|
||||
*/
|
||||
class SGCOORDINDEX : public SGINDEX
|
||||
{
|
||||
public:
|
||||
SGCOORDINDEX( SGNODE* aParent );
|
||||
virtual ~SGCOORDINDEX();
|
||||
|
||||
/**
|
||||
* Function GatherCoordIndices
|
||||
* adds all coordinate indices to the given list
|
||||
* in preparation for a normals calculation
|
||||
*/
|
||||
void GatherCoordIndices( std::vector< int >& aIndexList );
|
||||
};
|
||||
|
||||
#endif // SG_COORDINDEX_H
|
||||
@@ -1,431 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "3d_cache/sg/sg_coords.h"
|
||||
#include "3d_cache/sg/sg_helpers.h"
|
||||
#include "3d_cache/sg/sg_normals.h"
|
||||
#include "3d_cache/sg/sg_faceset.h"
|
||||
|
||||
|
||||
SGCOORDS::SGCOORDS( SGNODE* aParent ) : SGNODE( aParent )
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_COORDS;
|
||||
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] inappropriate parent to SGCOORDS (type ";
|
||||
ostr << aParent->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
else if( NULL != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGCOORDS::~SGCOORDS()
|
||||
{
|
||||
coords.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOORDS::SetParent( SGNODE* aParent, bool notify )
|
||||
{
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
|
||||
// handle the change in parents
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = NULL;
|
||||
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a SGFACESET may be parent to a SGCOORDS
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
|
||||
if( m_Parent )
|
||||
m_Parent->AddChildNode( this );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGCOORDS::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void SGCOORDS::unlinkChildNode( const SGNODE* aCaller )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOORDS::unlinkRefNode( const SGNODE* aCaller )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOORDS::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOORDS::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOORDS::GetCoordsList( size_t& aListSize, SGPOINT*& aCoordsList )
|
||||
{
|
||||
if( coords.empty() )
|
||||
{
|
||||
aListSize = 0;
|
||||
aCoordsList = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
aListSize = coords.size();
|
||||
aCoordsList = &coords[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void SGCOORDS::SetCoordsList( size_t aListSize, const SGPOINT* aCoordsList )
|
||||
{
|
||||
coords.clear();
|
||||
|
||||
if( 0 == aListSize || NULL == aCoordsList )
|
||||
return;
|
||||
|
||||
for( size_t i = 0; i < aListSize; ++i )
|
||||
coords.push_back( aCoordsList[i] );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOORDS::AddCoord( double aXValue, double aYValue, double aZValue )
|
||||
{
|
||||
coords.push_back( SGPOINT( aXValue, aYValue, aZValue ) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOORDS::AddCoord( const SGPOINT& aPoint )
|
||||
{
|
||||
coords.push_back( aPoint );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOORDS::ReNameNodes( void )
|
||||
{
|
||||
m_written = false;
|
||||
|
||||
// rename this node
|
||||
m_Name.clear();
|
||||
GetName();
|
||||
}
|
||||
|
||||
|
||||
bool SGCOORDS::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
{
|
||||
if( coords.empty() )
|
||||
return false;
|
||||
|
||||
if( aReuseFlag )
|
||||
{
|
||||
if( !m_written )
|
||||
{
|
||||
aFile << " coord DEF " << GetName() << " Coordinate { point [\n ";
|
||||
m_written = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
aFile << " coord USE " << GetName() << "\n";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aFile << " coord Coordinate { point [\n ";
|
||||
}
|
||||
|
||||
std::string tmp;
|
||||
size_t n = coords.size();
|
||||
bool nline = false;
|
||||
SGPOINT pt;
|
||||
|
||||
for( size_t i = 0; i < n; )
|
||||
{
|
||||
// ensure VRML output has 1U = 0.1 inch as per legacy kicad expectations
|
||||
pt = coords[i];
|
||||
pt.x /= 2.54;
|
||||
pt.y /= 2.54;
|
||||
pt.z /= 2.54;
|
||||
S3D::FormatPoint( tmp, pt );
|
||||
aFile << tmp ;
|
||||
++i;
|
||||
|
||||
if( i < n )
|
||||
{
|
||||
aFile << ",";
|
||||
|
||||
if( nline )
|
||||
{
|
||||
aFile << "\n ";
|
||||
nline = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
nline = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
aFile << "] }\n";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOORDS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; m_aParent is NULL";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = m_Parent;
|
||||
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( parentNode != m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; parentNode != m_aParent";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !aFile.good() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
aFile << "[" << GetName() << "]";
|
||||
size_t npts = coords.size();
|
||||
aFile.write( (char*)&npts, sizeof(size_t) );
|
||||
|
||||
for( size_t i = 0; i < npts; ++i )
|
||||
S3D::WritePoint( aFile, coords[i] );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
m_written = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOORDS::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( !coords.empty() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] non-empty node";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t npts;
|
||||
aFile.read( (char*)&npts, sizeof(size_t) );
|
||||
SGPOINT tmp;
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
for( size_t i = 0; i < npts; ++i )
|
||||
{
|
||||
if( !S3D::ReadPoint( aFile, tmp ) || aFile.fail() )
|
||||
return false;
|
||||
|
||||
coords.push_back( tmp );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOORDS::CalcNormals( SGFACESET* callingNode, SGNODE** aPtr )
|
||||
{
|
||||
if( aPtr )
|
||||
*aPtr = NULL;
|
||||
|
||||
if( NULL == m_Parent || NULL == callingNode )
|
||||
return false;
|
||||
|
||||
// the parent and all references must have indices; collect all
|
||||
// indices into one std::vector<>
|
||||
std::vector< int > ilist;
|
||||
SGNORMALS* np = NULL;
|
||||
|
||||
if( callingNode == m_Parent )
|
||||
{
|
||||
((SGFACESET*)m_Parent)->GatherCoordIndices( ilist );
|
||||
|
||||
std::list< SGNODE* >::iterator sB = m_BackPointers.begin();
|
||||
std::list< SGNODE* >::iterator eB = m_BackPointers.end();
|
||||
|
||||
while( sB != eB )
|
||||
{
|
||||
SGFACESET* fp = (SGFACESET*)(*sB);
|
||||
fp->GatherCoordIndices( ilist );
|
||||
++sB;
|
||||
}
|
||||
|
||||
np = ((SGFACESET*)m_Parent)->m_Normals;
|
||||
|
||||
if( !np )
|
||||
np = new SGNORMALS( m_Parent );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
callingNode->GatherCoordIndices( ilist );
|
||||
np = callingNode->m_Normals;
|
||||
|
||||
if( !np )
|
||||
np = new SGNORMALS( callingNode );
|
||||
|
||||
}
|
||||
|
||||
if( S3D::CalcTriangleNormals( coords, ilist, np->norms ) )
|
||||
{
|
||||
if( aPtr )
|
||||
*aPtr = np;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
delete np;
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file sg_coords.h
|
||||
* defines a vertex coordinate set for a scenegraph object
|
||||
*/
|
||||
|
||||
#ifndef SG_COORDS_H
|
||||
#define SG_COORDS_H
|
||||
|
||||
#include <vector>
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
|
||||
class SGFACESET;
|
||||
|
||||
class SGCOORDS : public SGNODE
|
||||
{
|
||||
public:
|
||||
std::vector< SGPOINT > coords;
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
|
||||
public:
|
||||
SGCOORDS( SGNODE* aParent );
|
||||
virtual ~SGCOORDS();
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) override;
|
||||
bool AddRefNode( SGNODE* aNode ) override;
|
||||
bool AddChildNode( SGNODE* aNode ) override;
|
||||
|
||||
bool GetCoordsList( size_t& aListSize, SGPOINT*& aCoordsList );
|
||||
void SetCoordsList( size_t aListSize, const SGPOINT* aCoordsList );
|
||||
void AddCoord( double aXValue, double aYValue, double aZValue );
|
||||
void AddCoord( const SGPOINT& aPoint );
|
||||
|
||||
/**
|
||||
* Function CalcNormals
|
||||
* calculates normals for this coordinate list and sets the
|
||||
* normals list in the parent SGFACESET
|
||||
*/
|
||||
bool CalcNormals( SGFACESET* callingNode, SGNODE** aPtr = NULL );
|
||||
|
||||
void ReNameNodes( void ) override;
|
||||
bool WriteVRML( std::ostream& aFile, bool aReuseFlag ) override;
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
};
|
||||
|
||||
#endif // SG_COORDS_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,114 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file sg_faceset.h
|
||||
* defines an indexed face set for a scenegraph
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SG_FACESET_H
|
||||
#define SG_FACESET_H
|
||||
|
||||
#include <vector>
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
|
||||
|
||||
class SGCOLORS;
|
||||
class SGCOORDS;
|
||||
class SGNORMALS;
|
||||
class SGCOLORINDEX;
|
||||
class SGCOORDINDEX;
|
||||
|
||||
class SGFACESET : public SGNODE
|
||||
{
|
||||
private:
|
||||
bool valid;
|
||||
bool validated;
|
||||
void unlinkNode( const SGNODE* aNode, bool isChild );
|
||||
bool addNode( SGNODE* aNode, bool isChild );
|
||||
|
||||
public:
|
||||
// owned objects
|
||||
SGCOLORS* m_Colors;
|
||||
SGCOORDS* m_Coords;
|
||||
SGCOORDINDEX* m_CoordIndices;
|
||||
SGNORMALS* m_Normals;
|
||||
|
||||
// referenced objects
|
||||
SGCOLORS* m_RColors;
|
||||
SGCOORDS* m_RCoords;
|
||||
SGNORMALS* m_RNormals;
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
// validate the data held by this face set
|
||||
bool validate( void );
|
||||
|
||||
public:
|
||||
SGFACESET( SGNODE* aParent );
|
||||
virtual ~SGFACESET();
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
|
||||
SGNODE* FindNode( const char *aNodeName, const SGNODE *aCaller ) override;
|
||||
bool AddRefNode( SGNODE* aNode ) override;
|
||||
bool AddChildNode( SGNODE* aNode ) override;
|
||||
|
||||
bool CalcNormals( SGNODE** aPtr );
|
||||
|
||||
void ReNameNodes( void ) override;
|
||||
bool WriteVRML( std::ostream& aFile, bool aReuseFlag ) override;
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
|
||||
/**
|
||||
* Function GatherCoordIndices
|
||||
* adds all internal coordinate indices to the given list
|
||||
* in preparation for a normals calculation
|
||||
*/
|
||||
void GatherCoordIndices( std::vector< int >& aIndexList );
|
||||
};
|
||||
|
||||
/*
|
||||
p.88
|
||||
IndexedFaceSet {
|
||||
color NULL
|
||||
coord NULL
|
||||
normal NULL
|
||||
texCoord NULL
|
||||
ccw TRUE
|
||||
colorIndex []
|
||||
colorPerVertex TRUE
|
||||
convex TRUE
|
||||
coordIndex []
|
||||
creaseAngle 0
|
||||
normalIndex []
|
||||
normalPerVertex TRUE
|
||||
solid TRUE
|
||||
texCoordIndex []
|
||||
}
|
||||
*/
|
||||
|
||||
#endif // SG_FACESET_H
|
||||
@@ -1,539 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "3d_cache/sg/sg_helpers.h"
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
|
||||
|
||||
// formats a floating point number for text output to a VRML file
|
||||
void S3D::FormatFloat( std::string& result, double value )
|
||||
{
|
||||
if( value < 1e-8 && value > -1e-8 )
|
||||
{
|
||||
result = "0";
|
||||
return;
|
||||
}
|
||||
|
||||
// note: many VRML implementations use float so we use the max.
|
||||
// precision here of 8 digits.
|
||||
std::ostringstream out;
|
||||
out << std::setprecision( 8 ) << value;
|
||||
|
||||
result = out.str();
|
||||
|
||||
size_t p = result.find( "." );
|
||||
|
||||
// trim trailing 0 if appropriate
|
||||
|
||||
if( std::string::npos == p )
|
||||
return;
|
||||
|
||||
p = result.find_first_of( "eE" );
|
||||
|
||||
if( std::string::npos == p )
|
||||
{
|
||||
while( '0' == *(result.rbegin()) )
|
||||
result.erase( result.size() - 1 );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if( '0' != result.at( p -1 ) )
|
||||
return;
|
||||
|
||||
// trim all 0 to the left of 'p'
|
||||
std::string tmp = result.substr( p );
|
||||
result = result.substr( 0, p );
|
||||
|
||||
while( '0' == *(result.rbegin()) )
|
||||
result.erase( result.size() - 1 );
|
||||
|
||||
result.append( tmp );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// format orientation data for VRML output
|
||||
void S3D::FormatOrientation( std::string& result, const SGVECTOR& axis, double rotation )
|
||||
{
|
||||
double aX;
|
||||
double aY;
|
||||
double aZ;
|
||||
|
||||
axis.GetVector( aX, aY, aZ );
|
||||
FormatFloat( result, aX );
|
||||
std::string tmp;
|
||||
FormatFloat( tmp, aY );
|
||||
result.append( " " );
|
||||
result.append( tmp );
|
||||
FormatFloat( tmp, aZ );
|
||||
result.append( " " );
|
||||
result.append( tmp );
|
||||
FormatFloat( tmp, rotation );
|
||||
result.append( " " );
|
||||
result.append( tmp );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// format point data for VRML output
|
||||
void S3D::FormatPoint( std::string& result, const SGPOINT& point )
|
||||
{
|
||||
FormatFloat( result, point.x );
|
||||
|
||||
std::string tmp;
|
||||
FormatFloat( tmp, point.y );
|
||||
result.append( " " );
|
||||
result.append( tmp );
|
||||
|
||||
FormatFloat( tmp, point.z );
|
||||
result.append( " " );
|
||||
result.append( tmp );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// format vector data for VRML output
|
||||
void S3D::FormatVector( std::string& result, const SGVECTOR& aVector )
|
||||
{
|
||||
double X, Y, Z;
|
||||
aVector.GetVector( X, Y, Z );
|
||||
FormatFloat( result, X );
|
||||
|
||||
std::string tmp;
|
||||
FormatFloat( tmp, Y );
|
||||
result.append( " " );
|
||||
result.append( tmp );
|
||||
|
||||
FormatFloat( tmp, Z );
|
||||
result.append( " " );
|
||||
result.append( tmp );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// format Color data for VRML output
|
||||
void S3D::FormatColor( std::string& result, const SGCOLOR& aColor )
|
||||
{
|
||||
float R, G, B;
|
||||
aColor.GetColor( R, G, B );
|
||||
FormatFloat( result, R );
|
||||
|
||||
std::string tmp;
|
||||
FormatFloat( tmp, G );
|
||||
result.append( " " );
|
||||
result.append( tmp );
|
||||
|
||||
FormatFloat( tmp, B );
|
||||
result.append( " " );
|
||||
result.append( tmp );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::WritePoint( std::ostream& aFile, const SGPOINT& aPoint )
|
||||
{
|
||||
aFile.write( (char*)&aPoint.x, sizeof(aPoint.x) );
|
||||
aFile.write( (char*)&aPoint.y, sizeof(aPoint.y) );
|
||||
aFile.write( (char*)&aPoint.z, sizeof(aPoint.z) );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::WriteVector( std::ostream& aFile, const SGVECTOR& aVector )
|
||||
{
|
||||
double x, y, z;
|
||||
aVector.GetVector( x, y, z );
|
||||
aFile.write( (char*)&x, sizeof(double) );
|
||||
aFile.write( (char*)&y, sizeof(double) );
|
||||
aFile.write( (char*)&z, sizeof(double) );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::WriteColor( std::ostream& aFile, const SGCOLOR& aColor )
|
||||
{
|
||||
float r, g, b;
|
||||
aColor.GetColor( r, g, b );
|
||||
aFile.write( (char*)&r, sizeof(float) );
|
||||
aFile.write( (char*)&g, sizeof(float) );
|
||||
aFile.write( (char*)&b, sizeof(float) );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
S3D::SGTYPES S3D::ReadTag( std::istream& aFile, std::string& aName )
|
||||
{
|
||||
char schar;
|
||||
aFile.get( schar );
|
||||
|
||||
if( '[' != schar )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; missing left bracket at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return S3D::SGTYPE_END;
|
||||
}
|
||||
|
||||
std::string name;
|
||||
aFile.get( schar );
|
||||
|
||||
while( ']' != schar && aFile.good() )
|
||||
{
|
||||
name.push_back( schar );
|
||||
aFile.get( schar );
|
||||
}
|
||||
|
||||
if( schar != ']' )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; could not find right bracket";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return S3D::SGTYPE_END;
|
||||
}
|
||||
|
||||
aName = name;
|
||||
size_t upos = name.find( '_' );
|
||||
|
||||
if( std::string::npos == upos )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; no underscore in name '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return S3D::SGTYPE_END;
|
||||
}
|
||||
|
||||
name = name.substr( 0, upos );
|
||||
S3D::SGTYPES types[S3D::SGTYPE_END] = {
|
||||
SGTYPE_TRANSFORM,
|
||||
SGTYPE_APPEARANCE,
|
||||
SGTYPE_COLORS,
|
||||
SGTYPE_COLORINDEX,
|
||||
SGTYPE_FACESET,
|
||||
SGTYPE_COORDS,
|
||||
SGTYPE_COORDINDEX,
|
||||
SGTYPE_NORMALS,
|
||||
SGTYPE_SHAPE
|
||||
};
|
||||
|
||||
for( int i = 0; i < S3D::SGTYPE_END; ++i )
|
||||
{
|
||||
if( !name.compare( S3D::GetNodeTypeName( types[i] ) ) )
|
||||
return types[i];
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; no node type matching '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return S3D::SGTYPE_END;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::ReadPoint( std::istream& aFile, SGPOINT& aPoint )
|
||||
{
|
||||
aFile.read( (char*)&aPoint.x, sizeof( aPoint.x ) );
|
||||
aFile.read( (char*)&aPoint.y, sizeof( aPoint.y ) );
|
||||
aFile.read( (char*)&aPoint.z, sizeof( aPoint.z ) );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::ReadVector( std::istream& aFile, SGVECTOR& aVector )
|
||||
{
|
||||
double x, y, z;
|
||||
aFile.read( (char*)&x, sizeof(double) );
|
||||
aFile.read( (char*)&y, sizeof(double) );
|
||||
aFile.read( (char*)&z, sizeof(double) );
|
||||
aVector.SetVector( x, y, z );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::ReadColor( std::istream& aFile, SGCOLOR& aColor )
|
||||
{
|
||||
float r, g, b;
|
||||
aFile.read( (char*)&r, sizeof(float) );
|
||||
aFile.read( (char*)&g, sizeof(float) );
|
||||
aFile.read( (char*)&b, sizeof(float) );
|
||||
aColor.SetColor( r, g, b );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::degenerate( glm::dvec3* pts )
|
||||
{
|
||||
double dx, dy, dz;
|
||||
|
||||
dx = pts[1].x - pts[0].x;
|
||||
dy = pts[1].y - pts[0].y;
|
||||
dz = pts[1].z - pts[0].z;
|
||||
|
||||
if( ( dx*dx + dy*dy + dz*dz ) < 1e-15 )
|
||||
return true;
|
||||
|
||||
dx = pts[2].x - pts[0].x;
|
||||
dy = pts[2].y - pts[0].y;
|
||||
dz = pts[2].z - pts[0].z;
|
||||
|
||||
if( ( dx*dx + dy*dy + dz*dz ) < 1e-15 )
|
||||
return true;
|
||||
|
||||
dx = pts[2].x - pts[1].x;
|
||||
dy = pts[2].y - pts[1].y;
|
||||
dz = pts[2].z - pts[1].z;
|
||||
|
||||
if( ( dx*dx + dy*dy + dz*dz ) < 1e-15 )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static void calcTriad( glm::dvec3* pts, glm::dvec3& tri )
|
||||
{
|
||||
if( S3D::degenerate( pts ) )
|
||||
{
|
||||
// degenerate points should contribute nothing to the result
|
||||
tri = glm::dvec3( 0.0, 0.0, 0.0 );
|
||||
return;
|
||||
}
|
||||
|
||||
// normal * 2 * area
|
||||
tri = glm::cross( pts[1] - pts[0], pts[2] - pts[0] );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::CalcTriangleNormals( std::vector< SGPOINT > coords,
|
||||
std::vector< int >& index, std::vector< SGVECTOR >& norms )
|
||||
{
|
||||
size_t vsize = coords.size();
|
||||
|
||||
if( vsize < 3 )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] invalid vertex set (fewer than 3 vertices)";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t isize = index.size();
|
||||
|
||||
if( 0 != isize % 3 || index.empty() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] invalid index set (not multiple of 3)";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !norms.empty() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] normals set is not empty";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::map< int, std::list< glm::dvec3 > >vmap;
|
||||
|
||||
int p1, p2, p3;
|
||||
|
||||
// create the map of indices to facet sets
|
||||
for( size_t i = 0; i < isize; )
|
||||
{
|
||||
p1 = index[i++];
|
||||
p2 = index[i++];
|
||||
p3 = index[i++];
|
||||
|
||||
if( p1 < 0 || p1 >= (int)vsize || p2 < 0 || p2 >= (int)vsize ||
|
||||
p3 < 0 || p3 >= (int)vsize )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] invalid index set; index out of bounds";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
glm::dvec3 tri;
|
||||
glm::dvec3 trip[3];
|
||||
trip[0] = glm::dvec3( coords[p1].x, coords[p1].y, coords[p1].z );
|
||||
trip[1] = glm::dvec3( coords[p2].x, coords[p2].y, coords[p2].z );
|
||||
trip[2] = glm::dvec3( coords[p3].x, coords[p3].y, coords[p3].z );
|
||||
calcTriad( trip, tri );
|
||||
|
||||
std::map< int, std::list< glm::dvec3 > >::iterator ip = vmap.find( p1 );
|
||||
|
||||
if( ip != vmap.end() )
|
||||
{
|
||||
ip->second.push_back( tri );
|
||||
}
|
||||
else
|
||||
{
|
||||
vmap.insert( std::pair < int, std::list < glm::dvec3 > >
|
||||
( p1, std::list < glm::dvec3 >( 1, tri ) ) );
|
||||
}
|
||||
|
||||
ip = vmap.find( p2 );
|
||||
|
||||
if( ip != vmap.end() )
|
||||
{
|
||||
ip->second.push_back( tri );
|
||||
}
|
||||
else
|
||||
{
|
||||
vmap.insert( std::pair < int, std::list < glm::dvec3 > >
|
||||
( p2, std::list < glm::dvec3 >( 1, tri ) ) );
|
||||
}
|
||||
|
||||
ip = vmap.find( p3 );
|
||||
|
||||
if( ip != vmap.end() )
|
||||
{
|
||||
ip->second.push_back( tri );
|
||||
}
|
||||
else
|
||||
{
|
||||
vmap.insert( std::pair < int, std::list < glm::dvec3 > >
|
||||
( p3, std::list < glm::dvec3 >( 1, tri ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
std::map< int, std::list< glm::dvec3 > >::iterator sM = vmap.begin();
|
||||
std::map< int, std::list< glm::dvec3 > >::iterator eM = vmap.end();
|
||||
size_t idx = 0;
|
||||
|
||||
while( sM != eM )
|
||||
{
|
||||
size_t item = sM->first;
|
||||
|
||||
// assign any skipped coordinates a normal of (0,0,1)
|
||||
while( item > idx )
|
||||
{
|
||||
norms.push_back( SGVECTOR( 0, 0, 1 ) );
|
||||
++idx;
|
||||
}
|
||||
|
||||
std::list< glm::dvec3 >::iterator sT = sM->second.begin();
|
||||
std::list< glm::dvec3 >::iterator eT = sM->second.end();
|
||||
glm::dvec3 norm( 0.0, 0.0, 0.0 );
|
||||
|
||||
while( sT != eT )
|
||||
{
|
||||
norm += *sT;
|
||||
++sT;
|
||||
}
|
||||
|
||||
norms.push_back( SGVECTOR( norm.x, norm.y, norm.z ) );
|
||||
|
||||
++idx;
|
||||
++sM;
|
||||
}
|
||||
|
||||
if( norms.size() != coords.size() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] number of normals does not equal number of vertices";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,247 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file sg_helpers.h
|
||||
* defines a number of macro functions to aid in repetitious code which
|
||||
* is probably best expressed as a preprocessor macro rather than as
|
||||
* a template. This header also declares a number of functions which are
|
||||
* only of use within the sg_* classes.
|
||||
*/
|
||||
|
||||
#ifndef SG_HELPERS_H
|
||||
#define SG_HELPERS_H
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include "plugins/3dapi/sg_base.h"
|
||||
#include "plugins/3dapi/sg_types.h"
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
class SGNORMALS;
|
||||
class SGCOORDS;
|
||||
class SGCOORDINDEX;
|
||||
|
||||
// Function to drop references within an SGNODE
|
||||
// The node being destroyed must remove itself from the object reference's
|
||||
// backpointer list in order to avoid a segfault.
|
||||
#define DROP_REFS( aType, aList ) do { \
|
||||
std::vector< aType* >::iterator sL = aList.begin(); \
|
||||
std::vector< aType* >::iterator eL = aList.end(); \
|
||||
while( sL != eL ) { \
|
||||
((SGNODE*)*sL)->delNodeRef( this ); \
|
||||
++sL; \
|
||||
} \
|
||||
aList.clear(); \
|
||||
} while( 0 )
|
||||
|
||||
|
||||
// Function to delete owned objects within an SGNODE
|
||||
// The owned object's parent is set to NULL before
|
||||
// deletion to avoid a redundant 'unlinkChildNode' call.
|
||||
#define DEL_OBJS( aType, aList ) do { \
|
||||
std::vector< aType* >::iterator sL = aList.begin(); \
|
||||
std::vector< aType* >::iterator eL = aList.end(); \
|
||||
while( sL != eL ) { \
|
||||
((SGNODE*)*sL)->SetParent( NULL, false ); \
|
||||
delete *sL; \
|
||||
++sL; \
|
||||
} \
|
||||
aList.clear(); \
|
||||
} while( 0 )
|
||||
|
||||
|
||||
// Function to unlink a child or reference node when that child or
|
||||
// reference node is being destroyed.
|
||||
#define UNLINK_NODE( aNodeID, aType, aNode, aOwnedList, aRefList, isChild ) do { \
|
||||
if( aNodeID == aNode->GetNodeType() ) { \
|
||||
std::vector< aType* >* oSL; \
|
||||
std::vector< aType* >::iterator sL; \
|
||||
std::vector< aType* >::iterator eL; \
|
||||
if( isChild ) { \
|
||||
oSL = &aOwnedList; \
|
||||
sL = oSL->begin(); \
|
||||
eL = oSL->end(); \
|
||||
while( sL != eL ) { \
|
||||
if( (SGNODE*)*sL == aNode ) { \
|
||||
oSL->erase( sL ); \
|
||||
return; \
|
||||
} \
|
||||
++sL; \
|
||||
} \
|
||||
} else { \
|
||||
oSL = &aRefList; \
|
||||
sL = oSL->begin(); \
|
||||
eL = oSL->end(); \
|
||||
while( sL != eL ) { \
|
||||
if( (SGNODE*)*sL == aNode ) { \
|
||||
delNodeRef( this ); \
|
||||
oSL->erase( sL ); \
|
||||
return; \
|
||||
} \
|
||||
++sL; \
|
||||
} \
|
||||
} \
|
||||
return; \
|
||||
} } while( 0 )
|
||||
|
||||
|
||||
// Function to check a node type, check for an existing reference,
|
||||
// and add the node type to the reference list if applicable
|
||||
#define ADD_NODE( aNodeID, aType, aNode, aOwnedList, aRefList, isChild ) do { \
|
||||
if( aNodeID == aNode->GetNodeType() ) { \
|
||||
std::vector< aType* >::iterator sL; \
|
||||
sL = std::find( aOwnedList.begin(), aOwnedList.end(), aNode ); \
|
||||
if( sL != aOwnedList.end() ) return true; \
|
||||
sL = std::find( aRefList.begin(), aRefList.end(), aNode ); \
|
||||
if( sL != aRefList.end() ) return true; \
|
||||
if( isChild ) { \
|
||||
SGNODE* ppn = (SGNODE*)aNode->GetParent(); \
|
||||
if( NULL != ppn ) { \
|
||||
if( this != ppn ) { \
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; \
|
||||
std::cerr << " * [BUG] object '" << aNode->GetName(); \
|
||||
std::cerr << "' has multiple parents '" << ppn->GetName() << "', '"; \
|
||||
std::cerr << m_Name << "'\n"; \
|
||||
return false; \
|
||||
} \
|
||||
} \
|
||||
aOwnedList.push_back( (aType*)aNode ); \
|
||||
aNode->SetParent( this, false ); \
|
||||
} else { \
|
||||
/*if( NULL == aNode->GetParent() ) { \
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; \
|
||||
std::cerr << " * [BUG] object '" << aNode->GetName(); \
|
||||
std::cerr << "' has no parent\n"; \
|
||||
std::cerr << " * [INFO] possible copy assignment or copy constructor bug\n"; \
|
||||
return false; \
|
||||
} */ \
|
||||
aRefList.push_back( (aType*)aNode ); \
|
||||
aNode->addNodeRef( this ); \
|
||||
} \
|
||||
return true; \
|
||||
} } while( 0 )
|
||||
|
||||
|
||||
// Function to find a node object given a (non-unique) node name
|
||||
#define FIND_NODE( aType, aName, aNodeList, aCallingNode ) do { \
|
||||
std::vector< aType* >::iterator sLA = aNodeList.begin(); \
|
||||
std::vector< aType* >::iterator eLA = aNodeList.end(); \
|
||||
SGNODE* psg = NULL; \
|
||||
while( sLA != eLA ) { \
|
||||
if( (SGNODE*)*sLA != aCallingNode ) { \
|
||||
psg = (SGNODE*) (*sLA)->FindNode( aName, this ); \
|
||||
if( NULL != psg) \
|
||||
return psg; \
|
||||
} \
|
||||
++sLA; \
|
||||
} } while ( 0 )
|
||||
|
||||
namespace S3D
|
||||
{
|
||||
bool degenerate( glm::dvec3* pts );
|
||||
|
||||
//
|
||||
// Normals calculations from triangles
|
||||
//
|
||||
|
||||
/*
|
||||
* Function CalcTriangleNormals
|
||||
* takes an array of 3D coordinates and its corresponding index set and calculates
|
||||
* the normals assuming that indices are given in CCW order. Care must be taken in
|
||||
* using this function to ensure that:
|
||||
* (a) all coordinates are indexed; unindexed coordinates are assigned normal(0,0,1);
|
||||
* when dealing with VRML models which may list and reuse one large coordinate set it
|
||||
* is necessary to gather all index sets and perform this operation only once.
|
||||
* (b) index sets must represent triangles (multiple of 3 indices) and must not be
|
||||
* degenerate - that is all indices and coordinates in a triad must be unique.
|
||||
*
|
||||
* @param coords is the array of 3D vertices
|
||||
* @param index is the array of 3x vertex indices (triads)
|
||||
* @param norms is an empty array which holds the normals corresponding to each vector
|
||||
* @return true on success; otherwise false.
|
||||
*/
|
||||
bool CalcTriangleNormals( std::vector< SGPOINT > coords, std::vector< int >& index,
|
||||
std::vector< SGVECTOR >& norms );
|
||||
|
||||
//
|
||||
// VRML related functions
|
||||
//
|
||||
|
||||
// formats a floating point number for text output to a VRML file
|
||||
void FormatFloat( std::string& result, double value );
|
||||
|
||||
// format orientation data for VRML output
|
||||
void FormatOrientation( std::string& result, const SGVECTOR& axis, double rotation );
|
||||
|
||||
// format point data for VRML output
|
||||
void FormatPoint( std::string& result, const SGPOINT& point );
|
||||
|
||||
// format vector data for VRML output
|
||||
void FormatVector( std::string& result, const SGVECTOR& aVector );
|
||||
|
||||
// format Color data for VRML output
|
||||
void FormatColor( std::string& result, const SGCOLOR& aColor );
|
||||
|
||||
//
|
||||
// Cache related WRITE functions
|
||||
//
|
||||
|
||||
// write out an XYZ vertex
|
||||
bool WritePoint( std::ostream& aFile, const SGPOINT& aPoint );
|
||||
|
||||
// write out a unit vector
|
||||
bool WriteVector( std::ostream& aFile, const SGVECTOR& aVector );
|
||||
|
||||
// write out an RGB color
|
||||
bool WriteColor( std::ostream& aFile, const SGCOLOR& aColor );
|
||||
|
||||
//
|
||||
// Cache related READ functions
|
||||
//
|
||||
|
||||
/**
|
||||
* Function ReadTag
|
||||
* reads the text tag of a binary cache file which is the
|
||||
* NodeTag and unique ID number combined
|
||||
*
|
||||
* @param aFile is a binary file open for reading
|
||||
* @param aName will hold the tag name on successful return
|
||||
* @return will be the NodeType which the tag represents or
|
||||
* S3D::SGTYPES::SGTYPE_END on failure
|
||||
*/
|
||||
S3D::SGTYPES ReadTag( std::istream& aFile, std::string& aName );
|
||||
|
||||
// read an XYZ vertex
|
||||
bool ReadPoint( std::istream& aFile, SGPOINT& aPoint );
|
||||
|
||||
// read a unit vector
|
||||
bool ReadVector( std::istream& aFile, SGVECTOR& aVector );
|
||||
|
||||
// read an RGB color
|
||||
bool ReadColor( std::istream& aFile, SGCOLOR& aColor );
|
||||
}
|
||||
|
||||
#endif // SG_HELPERS_H
|
||||
@@ -1,398 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "3d_cache/sg/sg_index.h"
|
||||
|
||||
|
||||
SGINDEX::SGINDEX( SGNODE* aParent ) : SGNODE( aParent )
|
||||
{
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] inappropriate parent to SGINDEX (type ";
|
||||
ostr << aParent->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGINDEX::~SGINDEX()
|
||||
{
|
||||
index.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGINDEX::SetParent( SGNODE* aParent, bool notify )
|
||||
{
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
|
||||
// handle the change in parents
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = NULL;
|
||||
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a SGFACESET may be parent to a SGINDEX and derived types
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
|
||||
if( m_Parent )
|
||||
m_Parent->AddChildNode( this );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGINDEX::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void SGINDEX::unlinkChildNode( const SGNODE* aCaller )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGINDEX::unlinkRefNode( const SGNODE* aCaller )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGINDEX::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SGINDEX::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SGINDEX::GetIndices( size_t& nIndices, int*& aIndexList )
|
||||
{
|
||||
if( index.empty() )
|
||||
{
|
||||
nIndices = 0;
|
||||
aIndexList = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
nIndices = index.size();
|
||||
aIndexList = & index[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void SGINDEX::SetIndices( size_t nIndices, int* aIndexList )
|
||||
{
|
||||
index.clear();
|
||||
|
||||
if( 0 == nIndices || NULL == aIndexList )
|
||||
return;
|
||||
|
||||
for( size_t i = 0; i < nIndices; ++i )
|
||||
index.push_back( aIndexList[i] );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGINDEX::AddIndex( int aIndex )
|
||||
{
|
||||
index.push_back( aIndex );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGINDEX::ReNameNodes( void )
|
||||
{
|
||||
m_written = false;
|
||||
|
||||
// rename this node
|
||||
m_Name.clear();
|
||||
GetName();
|
||||
}
|
||||
|
||||
|
||||
bool SGINDEX::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
{
|
||||
if( index.empty() )
|
||||
return false;
|
||||
|
||||
if( S3D::SGTYPE_COORDINDEX == m_SGtype )
|
||||
return writeCoordIndex( aFile );
|
||||
|
||||
return writeColorIndex( aFile );
|
||||
}
|
||||
|
||||
|
||||
bool SGINDEX::writeCoordIndex( std::ostream& aFile )
|
||||
{
|
||||
size_t n = index.size();
|
||||
|
||||
if( n % 3 )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] coord index is not divisible by three (violates triangle constraint)";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
aFile << " coordIndex [\n ";
|
||||
|
||||
// indices to control formatting
|
||||
int nv0 = 0;
|
||||
int nv1 = 0;
|
||||
|
||||
for( size_t i = 0; i < n; )
|
||||
{
|
||||
aFile << index[i];
|
||||
++i;
|
||||
|
||||
if( ++nv0 == 3 )
|
||||
{
|
||||
aFile << ",-1";
|
||||
++nv1;
|
||||
nv0 = 0;
|
||||
}
|
||||
|
||||
if( i < n )
|
||||
{
|
||||
aFile << ",";
|
||||
|
||||
if( nv1 == 8 )
|
||||
{
|
||||
nv1 = 0;
|
||||
aFile << "\n ";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aFile << "]\n";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGINDEX::writeColorIndex( std::ostream& aFile )
|
||||
{
|
||||
aFile << " colorIndex [\n ";
|
||||
return writeIndexList( aFile );
|
||||
}
|
||||
|
||||
|
||||
bool SGINDEX::writeIndexList( std::ostream& aFile )
|
||||
{
|
||||
// index to control formatting
|
||||
int nv = 0;
|
||||
size_t n = index.size();
|
||||
|
||||
for( size_t i = 0; i < n; )
|
||||
{
|
||||
aFile << index[i];
|
||||
++i;
|
||||
|
||||
if( i < n )
|
||||
{
|
||||
aFile << ",";
|
||||
|
||||
if( ++nv == 20 )
|
||||
{
|
||||
aFile << "\n ";
|
||||
nv = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aFile << "]\n";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGINDEX::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; m_aParent is NULL";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = m_Parent;
|
||||
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( parentNode != m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; parentNode != m_aParent";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !aFile.good() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
aFile << "[" << GetName() << "]";
|
||||
size_t npts = index.size();
|
||||
aFile.write( (char*)&npts, sizeof(size_t) );
|
||||
|
||||
for( size_t i = 0; i < npts; ++i )
|
||||
aFile.write( (char*)&index[i], sizeof(int) );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
m_written = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGINDEX::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( !index.empty() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] non-empty node";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t npts;
|
||||
aFile.read( (char*)&npts, sizeof(size_t) );
|
||||
int tmp;
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
for( size_t i = 0; i < npts; ++i )
|
||||
{
|
||||
aFile.read( (char*)&tmp, sizeof(int) );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
index.push_back( tmp );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file sg_index.h
|
||||
* defines a generic Index interface for a scenegraph object
|
||||
*/
|
||||
|
||||
#ifndef SG_INDEX_H
|
||||
#define SG_INDEX_H
|
||||
|
||||
#include <vector>
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
|
||||
class SGINDEX : public SGNODE
|
||||
{
|
||||
protected:
|
||||
bool writeCoordIndex( std::ostream& aFile );
|
||||
bool writeColorIndex( std::ostream& aFile );
|
||||
bool writeIndexList( std::ostream& aFile );
|
||||
|
||||
public:
|
||||
// for internal SG consumption only
|
||||
std::vector< int > index;
|
||||
void unlinkChildNode( const SGNODE* aCaller ) override;
|
||||
void unlinkRefNode( const SGNODE* aCaller ) override;
|
||||
|
||||
public:
|
||||
SGINDEX( SGNODE* aParent );
|
||||
virtual ~SGINDEX();
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) override;
|
||||
bool AddRefNode( SGNODE* aNode ) override;
|
||||
bool AddChildNode( SGNODE* aNode ) override;
|
||||
|
||||
/**
|
||||
* Function GetIndices
|
||||
* retrieves the number of indices and a pointer to
|
||||
* the list. Note: the returned pointer may be invalidated
|
||||
* by future operations on the SGNODE; the caller must make
|
||||
* immediate use of the data and must not rely on the pointer's
|
||||
* validity in the future.
|
||||
*
|
||||
* @param nIndices [out] will hold the number of indices in the list
|
||||
* @param aIndexList [out] will store a pointer to the data
|
||||
* @return true if there was available data (nIndices > 0) otherwise false
|
||||
*/
|
||||
bool GetIndices( size_t& nIndices, int*& aIndexList );
|
||||
|
||||
/**
|
||||
* Function SetIndices
|
||||
* sets the number of indices and creates a copy of the given index data.
|
||||
*
|
||||
* @param nIndices [in] the number of indices to be stored
|
||||
* @param aIndexList [in] the index data
|
||||
*/
|
||||
void SetIndices( size_t nIndices, int* aIndexList );
|
||||
|
||||
|
||||
/**
|
||||
* Function AddIndex
|
||||
* adds a single index to the list
|
||||
*
|
||||
* @param aIndex is the index to add
|
||||
*/
|
||||
void AddIndex( int aIndex );
|
||||
|
||||
void ReNameNodes( void ) override;
|
||||
bool WriteVRML( std::ostream& aFile, bool aReuseFlag ) override;
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
};
|
||||
|
||||
#endif // SG_INDEX_H
|
||||
@@ -1,439 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
#include "plugins/3dapi/c3dmodel.h"
|
||||
|
||||
static const std::string node_names[S3D::SGTYPE_END + 1] = {
|
||||
"TXFM",
|
||||
"APP",
|
||||
"COL",
|
||||
"COLIDX",
|
||||
"FACE",
|
||||
"COORD",
|
||||
"COORDIDX",
|
||||
"NORM",
|
||||
"SHAPE",
|
||||
"INVALID"
|
||||
};
|
||||
|
||||
|
||||
static unsigned int node_counts[S3D::SGTYPE_END] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 };
|
||||
|
||||
|
||||
char const* S3D::GetNodeTypeName( S3D::SGTYPES aType )
|
||||
{
|
||||
return node_names[aType].c_str();
|
||||
}
|
||||
|
||||
|
||||
static void getNodeName( S3D::SGTYPES nodeType, std::string& aName )
|
||||
{
|
||||
if( nodeType < 0 || nodeType >= S3D::SGTYPE_END )
|
||||
{
|
||||
aName = node_names[S3D::SGTYPE_END];
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int seqNum = node_counts[nodeType];
|
||||
++node_counts[nodeType];
|
||||
|
||||
std::ostringstream ostr;
|
||||
ostr << node_names[nodeType] << "_" << seqNum;
|
||||
aName = ostr.str();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGNODE::SGNODE( SGNODE* aParent )
|
||||
{
|
||||
m_Parent = aParent;
|
||||
m_Association = NULL;
|
||||
m_written = false;
|
||||
m_SGtype = S3D::SGTYPE_END;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGNODE::~SGNODE()
|
||||
{
|
||||
if( m_Parent )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
if( m_Association )
|
||||
*m_Association = NULL;
|
||||
|
||||
std::list< SGNODE* >::iterator sBP = m_BackPointers.begin();
|
||||
std::list< SGNODE* >::iterator eBP = m_BackPointers.end();
|
||||
|
||||
while( sBP != eBP )
|
||||
{
|
||||
(*sBP)->unlinkRefNode( this );
|
||||
++sBP;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
S3D::SGTYPES SGNODE::GetNodeType( void ) const
|
||||
{
|
||||
return m_SGtype;
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGNODE::GetParent( void ) const
|
||||
{
|
||||
return m_Parent;
|
||||
}
|
||||
|
||||
|
||||
bool SGNODE::SwapParent( SGNODE* aNewParent )
|
||||
{
|
||||
if( aNewParent == m_Parent )
|
||||
return true;
|
||||
|
||||
if( NULL == aNewParent )
|
||||
return false;
|
||||
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
if( aNewParent->AddChildNode( this ) )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( aNewParent->GetNodeType() != m_Parent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
SGNODE* oldParent = m_Parent;
|
||||
m_Parent->unlinkChildNode( this );
|
||||
m_Parent = NULL;
|
||||
aNewParent->unlinkRefNode( this );
|
||||
aNewParent->AddChildNode( this );
|
||||
oldParent->AddRefNode( this );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
const char* SGNODE::GetName( void )
|
||||
{
|
||||
if( m_Name.empty() )
|
||||
getNodeName( m_SGtype, m_Name );
|
||||
|
||||
return m_Name.c_str();
|
||||
}
|
||||
|
||||
|
||||
void SGNODE::SetName( const char *aName )
|
||||
{
|
||||
if( NULL == aName || 0 == aName[0] )
|
||||
getNodeName( m_SGtype, m_Name );
|
||||
else
|
||||
m_Name = aName;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const char * SGNODE::GetNodeTypeName( S3D::SGTYPES aNodeType ) const
|
||||
{
|
||||
return node_names[aNodeType].c_str();
|
||||
}
|
||||
|
||||
|
||||
void SGNODE::addNodeRef( SGNODE* aNode )
|
||||
{
|
||||
if( NULL == aNode )
|
||||
return;
|
||||
|
||||
std::list< SGNODE* >::iterator np =
|
||||
std::find( m_BackPointers.begin(), m_BackPointers.end(), aNode );
|
||||
|
||||
if( np != m_BackPointers.end() )
|
||||
return;
|
||||
|
||||
m_BackPointers.push_back( aNode );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGNODE::delNodeRef( const SGNODE* aNode )
|
||||
{
|
||||
if( NULL == aNode )
|
||||
return;
|
||||
|
||||
std::list< SGNODE* >::iterator np =
|
||||
std::find( m_BackPointers.begin(), m_BackPointers.end(), aNode );
|
||||
|
||||
if( np != m_BackPointers.end() )
|
||||
{
|
||||
m_BackPointers.erase( np );
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] delNodeRef() did not find its target\n";
|
||||
ostr << " * This Node Type: " << m_SGtype << ", Referenced node type: ";
|
||||
ostr << aNode->GetNodeType() << "\n";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGNODE::AssociateWrapper( SGNODE** aWrapperRef )
|
||||
{
|
||||
if( NULL == aWrapperRef )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL handle";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if( *aWrapperRef != this )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] handle value does not match this object's pointer";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// if there is an existing association then break it and emit a warning
|
||||
// just in case the behavior is undesired
|
||||
if( m_Association )
|
||||
{
|
||||
*m_Association = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [WARNING] association being broken with previous wrapper";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
|
||||
m_Association = aWrapperRef;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void SGNODE::DisassociateWrapper( SGNODE** aWrapperRef )
|
||||
{
|
||||
if( !m_Association )
|
||||
return;
|
||||
|
||||
if( !aWrapperRef )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid handle value aWrapperRef";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if( *aWrapperRef != *m_Association || aWrapperRef != m_Association )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] *aWrapperRef (" << *aWrapperRef;
|
||||
ostr << ") does not match *m_Association (" << *m_Association << ") in type ";
|
||||
ostr << node_names[ m_SGtype] << "\n";
|
||||
ostr << " * [INFO] OR aWrapperRef(" << aWrapperRef << ") != m_Association(";
|
||||
ostr << m_Association << ")\n";
|
||||
ostr << " * [INFO] node name: " << GetName();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_Association = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGNODE::ResetNodeIndex( void )
|
||||
{
|
||||
for( int i = 0; i < (int)S3D::SGTYPE_END; ++i )
|
||||
node_counts[i] = 1;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::GetMatIndex( MATLIST& aList, SGNODE* aNode, int& aIndex )
|
||||
{
|
||||
aIndex = 0;
|
||||
|
||||
if( NULL == aNode || S3D::SGTYPE_APPEARANCE != aNode->GetNodeType() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
ostr.str( "" );
|
||||
|
||||
if( NULL == aNode )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, " * [BUG] aNode is NULL\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
ostr << " * [BUG] invalid node type (" << aNode->GetNodeType();
|
||||
ostr << "), expected " << S3D::SGTYPE_APPEARANCE;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGAPPEARANCE* node = (SGAPPEARANCE*)aNode;
|
||||
|
||||
std::map< SGAPPEARANCE const*, int >::iterator it = aList.matmap.find( node );
|
||||
|
||||
if( it != aList.matmap.end() )
|
||||
{
|
||||
aIndex = it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
int idx = (int)aList.matorder.size();
|
||||
aList.matorder.push_back( node );
|
||||
aList.matmap.insert( std::pair< SGAPPEARANCE const*, int >( node, idx ) );
|
||||
aIndex = idx;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void S3D::INIT_SMATERIAL( SMATERIAL& aMaterial )
|
||||
{
|
||||
aMaterial = {};
|
||||
}
|
||||
|
||||
|
||||
void S3D::INIT_SMESH( SMESH& aMesh )
|
||||
{
|
||||
aMesh = {};
|
||||
}
|
||||
|
||||
|
||||
void S3D::INIT_S3DMODEL( S3DMODEL& aModel )
|
||||
{
|
||||
aModel = {};
|
||||
}
|
||||
|
||||
|
||||
void S3D::FREE_SMESH( SMESH& aMesh)
|
||||
{
|
||||
if( NULL != aMesh.m_Positions )
|
||||
{
|
||||
delete [] aMesh.m_Positions;
|
||||
aMesh.m_Positions = NULL;
|
||||
}
|
||||
|
||||
if( NULL != aMesh.m_Normals )
|
||||
{
|
||||
delete [] aMesh.m_Normals;
|
||||
aMesh.m_Normals = NULL;
|
||||
}
|
||||
|
||||
if( NULL != aMesh.m_Texcoords )
|
||||
{
|
||||
delete [] aMesh.m_Texcoords;
|
||||
aMesh.m_Texcoords = NULL;
|
||||
}
|
||||
|
||||
if( NULL != aMesh.m_Color )
|
||||
{
|
||||
delete [] aMesh.m_Color;
|
||||
aMesh.m_Color = NULL;
|
||||
}
|
||||
|
||||
if( NULL != aMesh.m_FaceIdx )
|
||||
{
|
||||
delete [] aMesh.m_FaceIdx;
|
||||
aMesh.m_FaceIdx = NULL;
|
||||
}
|
||||
|
||||
aMesh.m_VertexSize = 0;
|
||||
aMesh.m_FaceIdxSize = 0;
|
||||
aMesh.m_MaterialIdx = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D::FREE_S3DMODEL( S3DMODEL& aModel )
|
||||
{
|
||||
if( NULL != aModel.m_Materials )
|
||||
{
|
||||
delete [] aModel.m_Materials;
|
||||
aModel.m_Materials = NULL;
|
||||
}
|
||||
|
||||
aModel.m_MaterialsSize = 0;
|
||||
|
||||
if( NULL != aModel.m_Meshes )
|
||||
{
|
||||
for( unsigned int i = 0; i < aModel.m_MeshesSize; ++i )
|
||||
FREE_SMESH( aModel.m_Meshes[i] );
|
||||
|
||||
delete [] aModel.m_Meshes;
|
||||
aModel.m_Meshes = NULL;
|
||||
}
|
||||
|
||||
aModel.m_MeshesSize = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1,250 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file sg_node.h
|
||||
* defines the base class of the intermediate scene graph NODE
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SG_NODE_H
|
||||
#define SG_NODE_H
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "plugins/3dapi/c3dmodel.h"
|
||||
#include "plugins/3dapi/sg_base.h"
|
||||
#include "plugins/3dapi/sg_types.h"
|
||||
|
||||
class SGNODE;
|
||||
class SGAPPEARANCE;
|
||||
|
||||
namespace S3D
|
||||
{
|
||||
/**
|
||||
* Function GetNodeTypeName
|
||||
* returns the name of the given type of node
|
||||
*/
|
||||
char const* GetNodeTypeName( S3D::SGTYPES aType );
|
||||
|
||||
struct MATLIST
|
||||
{
|
||||
std::vector< SGAPPEARANCE const* > matorder; // materials in order of addition
|
||||
std::map< SGAPPEARANCE const*, int > matmap; // mapping from material to index
|
||||
};
|
||||
|
||||
bool GetMatIndex( MATLIST& aList, SGNODE* aNode, int& aIndex );
|
||||
|
||||
void INIT_SMATERIAL( SMATERIAL& aMaterial );
|
||||
void INIT_SMESH( SMESH& aMesh );
|
||||
void INIT_S3DMODEL( S3DMODEL& aModel );
|
||||
|
||||
void FREE_SMESH( SMESH& aMesh);
|
||||
void FREE_S3DMODEL( S3DMODEL& aModel );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class SGNODE
|
||||
* represents the base class of all Scene Graph nodes
|
||||
*/
|
||||
class SGNODE
|
||||
{
|
||||
private:
|
||||
SGNODE** m_Association; // handle to the instance held by a wrapper
|
||||
|
||||
protected:
|
||||
std::list< SGNODE* > m_BackPointers; // nodes which hold a reference to this
|
||||
SGNODE* m_Parent; // pointer to parent node; may be NULL for top level transform
|
||||
S3D::SGTYPES m_SGtype; // type of SG node
|
||||
std::string m_Name; // name to use for referencing the entity by name
|
||||
bool m_written; // set true when the object has been written after a ReNameNodes()
|
||||
|
||||
public:
|
||||
/**
|
||||
* Function unlinkChild
|
||||
* removes references to an owned child; it is invoked by the child upon destruction
|
||||
* to ensure that the parent has no invalid references.
|
||||
*
|
||||
* @param aNode is the child which is being deleted
|
||||
*/
|
||||
virtual void unlinkChildNode( const SGNODE* aNode ) = 0;
|
||||
|
||||
/**
|
||||
* Function unlinkRef
|
||||
* removes pointers to a referenced node; it is invoked by the referenced node
|
||||
* upon destruction to ensure that the referring node has no invalid references.
|
||||
*
|
||||
* @param aNode is the node which is being deleted
|
||||
*/
|
||||
virtual void unlinkRefNode( const SGNODE* aNode ) = 0;
|
||||
|
||||
/**
|
||||
* Function addNodeRef
|
||||
* adds a pointer to a node which references, but does not own, this node.
|
||||
* Such back-pointers are required to ensure that invalidated references
|
||||
* are removed when a node is deleted
|
||||
*
|
||||
* @param aNode is the node holding a reference to this object
|
||||
*/
|
||||
void addNodeRef( SGNODE* aNode );
|
||||
|
||||
/**
|
||||
* Function delNodeRef
|
||||
* removes a pointer to a node which references, but does not own, this node.
|
||||
*
|
||||
* @param aNode is the node holding a reference to this object
|
||||
*/
|
||||
void delNodeRef( const SGNODE* aNode );
|
||||
|
||||
/**
|
||||
* Function IsWritten
|
||||
* returns true if the object had already been written to a
|
||||
* cache file or VRML file; for internal use only.
|
||||
*/
|
||||
bool isWritten( void )
|
||||
{
|
||||
return m_written;
|
||||
}
|
||||
|
||||
public:
|
||||
SGNODE( SGNODE* aParent );
|
||||
virtual ~SGNODE();
|
||||
|
||||
/**
|
||||
* Function GetNodeType
|
||||
* returns the type of this node instance
|
||||
*/
|
||||
S3D::SGTYPES GetNodeType( void ) const;
|
||||
|
||||
/**
|
||||
* Function GetParent
|
||||
* returns a pointer to the parent SGNODE of this object
|
||||
* or NULL if the object has no parent (ie. top level transform)
|
||||
*/
|
||||
SGNODE* GetParent( void ) const;
|
||||
|
||||
/**
|
||||
* Function SetParent
|
||||
* sets the parent SGNODE of this object.
|
||||
*
|
||||
* @param aParent [in] is the desired parent node
|
||||
* @return true if the operation succeeds; false if
|
||||
* the given node is not allowed to be a parent to
|
||||
* the derived object.
|
||||
*/
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) = 0;
|
||||
|
||||
/**
|
||||
* Function SwapParent
|
||||
* swaps the ownership with the given parent. This operation
|
||||
* may be required when reordering nodes for optimization.
|
||||
*
|
||||
* @param aNewParent [in] will become the new parent to the
|
||||
* object; it must be the same type as the parent of this
|
||||
* instance.
|
||||
*/
|
||||
bool SwapParent( SGNODE* aNewParent );
|
||||
|
||||
const char* GetName( void );
|
||||
void SetName(const char *aName);
|
||||
|
||||
const char * GetNodeTypeName( S3D::SGTYPES aNodeType ) const;
|
||||
|
||||
/**
|
||||
* Function FindNode searches the tree of linked nodes and returns a
|
||||
* reference to the first node found with the given name. The reference
|
||||
* is then typically added to another node via AddRefNode().
|
||||
*
|
||||
* @param aNodeName is the name of the node to search for
|
||||
* @param aCaller is a pointer to the node invoking this function
|
||||
* @return is a valid node pointer on success, otherwise NULL
|
||||
*/
|
||||
virtual SGNODE* FindNode( const char *aNodeName, const SGNODE *aCaller ) = 0;
|
||||
|
||||
virtual bool AddRefNode( SGNODE* aNode ) = 0;
|
||||
|
||||
virtual bool AddChildNode( SGNODE* aNode ) = 0;
|
||||
|
||||
/**
|
||||
* Function AssociateWrapper
|
||||
* associates this object with a handle to itself; this handle
|
||||
* is typically held by an IFSG* wrapper and the pointer which
|
||||
* it refers to is set to NULL upon destruction of this object.
|
||||
* This mechanism provides a scheme by which a wrapper can be
|
||||
* notified of the destruction of the object which it wraps.
|
||||
*/
|
||||
void AssociateWrapper( SGNODE** aWrapperRef );
|
||||
|
||||
/**
|
||||
* Function DisassociateWrapper
|
||||
* removes the association between an IFSG* wrapper
|
||||
* object and this object.
|
||||
*/
|
||||
void DisassociateWrapper( SGNODE** aWrapperRef );
|
||||
|
||||
/**
|
||||
* Function ResetNodeIndex
|
||||
* resets the global SG* node indices in preparation for
|
||||
* Write() operations
|
||||
*/
|
||||
void ResetNodeIndex( void );
|
||||
|
||||
/**
|
||||
* Function ReNameNodes
|
||||
* renames a node and all its child nodes in preparation for
|
||||
* Write() operations
|
||||
*/
|
||||
virtual void ReNameNodes( void ) = 0;
|
||||
|
||||
/**
|
||||
* Function WriteVRML
|
||||
* writes this node's data to a VRML file; this includes
|
||||
* all data of child and referenced nodes.
|
||||
*/
|
||||
virtual bool WriteVRML( std::ostream& aFile, bool aReuseFlag ) = 0;
|
||||
|
||||
/**
|
||||
* Function WriteCache
|
||||
* write's this node's data to a binary cache file; the data
|
||||
* includes all data of children and references to children.
|
||||
* If this function is invoked by the user, parentNode must be
|
||||
* set to NULL in order to ensure coherent data.
|
||||
*/
|
||||
virtual bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) = 0;
|
||||
|
||||
/**
|
||||
* Function ReadCache
|
||||
* Reads binary format data from a cache file. To read a cache file,
|
||||
* open the file for reading and invoke this function from a new
|
||||
* SCENEGRAPH node.
|
||||
*/
|
||||
virtual bool ReadCache( std::istream& aFile, SGNODE* parentNode ) = 0;
|
||||
};
|
||||
|
||||
#endif // SG_NODE_H
|
||||
@@ -1,366 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "3d_cache/sg/sg_normals.h"
|
||||
#include "3d_cache/sg/sg_helpers.h"
|
||||
|
||||
|
||||
SGNORMALS::SGNORMALS( SGNODE* aParent ) : SGNODE( aParent )
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_NORMALS;
|
||||
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] inappropriate parent to SGNORMALS (type ";
|
||||
ostr << aParent->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
else if( NULL != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGNORMALS::~SGNORMALS()
|
||||
{
|
||||
norms.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGNORMALS::SetParent( SGNODE* aParent, bool notify )
|
||||
{
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
|
||||
// handle the change in parents
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = NULL;
|
||||
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a SGFACESET may be parent to a SGNORMALS
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
|
||||
if( m_Parent )
|
||||
m_Parent->AddChildNode( this );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGNORMALS::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void SGNORMALS::unlinkChildNode( const SGNODE* aCaller )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGNORMALS::unlinkRefNode( const SGNODE* aCaller )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGNORMALS::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SGNORMALS::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SGNORMALS::GetNormalList( size_t& aListSize, SGVECTOR*& aNormalList )
|
||||
{
|
||||
if( norms.empty() )
|
||||
{
|
||||
aListSize = 0;
|
||||
aNormalList = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
aListSize = norms.size();
|
||||
aNormalList = &norms[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void SGNORMALS::SetNormalList( size_t aListSize, const SGVECTOR* aNormalList )
|
||||
{
|
||||
norms.clear();
|
||||
|
||||
if( 0 == aListSize || NULL == aNormalList )
|
||||
return;
|
||||
|
||||
for( int i = 0; i < (int)aListSize; ++i )
|
||||
norms.push_back( aNormalList[i] );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGNORMALS::AddNormal( double aXValue, double aYValue, double aZValue )
|
||||
{
|
||||
norms.push_back( SGVECTOR( aXValue, aYValue, aZValue ) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGNORMALS::AddNormal( const SGVECTOR& aNormal )
|
||||
{
|
||||
norms.push_back( aNormal );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGNORMALS::ReNameNodes( void )
|
||||
{
|
||||
m_written = false;
|
||||
|
||||
// rename this node
|
||||
m_Name.clear();
|
||||
GetName();
|
||||
}
|
||||
|
||||
|
||||
bool SGNORMALS::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
{
|
||||
if( norms.empty() )
|
||||
return false;
|
||||
|
||||
if( aReuseFlag )
|
||||
{
|
||||
if( !m_written )
|
||||
{
|
||||
aFile << " normal DEF " << GetName() << " Normal { vector [\n ";
|
||||
m_written = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
aFile << " normal USE " << GetName() << "\n";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aFile << " normal Normal { vector [\n ";
|
||||
}
|
||||
|
||||
std::string tmp;
|
||||
size_t n = norms.size();
|
||||
bool nline = false;
|
||||
|
||||
for( size_t i = 0; i < n; )
|
||||
{
|
||||
S3D::FormatVector( tmp, norms[i] );
|
||||
aFile << tmp ;
|
||||
++i;
|
||||
|
||||
if( i < n )
|
||||
{
|
||||
aFile << ",";
|
||||
|
||||
if( nline )
|
||||
{
|
||||
aFile << "\n ";
|
||||
nline = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
nline = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
aFile << "] }\n";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGNORMALS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; m_aParent is NULL";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = m_Parent;
|
||||
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( parentNode != m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; parentNode != m_aParent";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !aFile.good() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
aFile << "[" << GetName() << "]";
|
||||
size_t npts = norms.size();
|
||||
aFile.write( (char*)&npts, sizeof(size_t) );
|
||||
|
||||
for( size_t i = 0; i < npts; ++i )
|
||||
S3D::WriteVector( aFile, norms[i] );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
m_written = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGNORMALS::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( !norms.empty() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] non-empty node";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t npts;
|
||||
aFile.read( (char*)&npts, sizeof(size_t) );
|
||||
SGVECTOR tmp;
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
for( size_t i = 0; i < npts; ++i )
|
||||
{
|
||||
if( !S3D::ReadVector( aFile, tmp ) || aFile.fail() )
|
||||
return false;
|
||||
|
||||
norms.push_back( tmp );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file sg_normals.h
|
||||
* defines a set of vertex normals for a scene graph object
|
||||
*/
|
||||
|
||||
#ifndef SG_NORMALS_H
|
||||
#define SG_NORMALS_H
|
||||
|
||||
#include <vector>
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
|
||||
class SGNORMALS : public SGNODE
|
||||
{
|
||||
public:
|
||||
std::vector< SGVECTOR > norms;
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
|
||||
public:
|
||||
SGNORMALS( SGNODE* aParent );
|
||||
virtual ~SGNORMALS();
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) override;
|
||||
bool AddRefNode( SGNODE* aNode ) override;
|
||||
bool AddChildNode( SGNODE* aNode ) override;
|
||||
|
||||
bool GetNormalList( size_t& aListSize, SGVECTOR*& aNormalList );
|
||||
void SetNormalList( size_t aListSize, const SGVECTOR* aNormalList );
|
||||
void AddNormal( double aXValue, double aYValue, double aZValue );
|
||||
void AddNormal( const SGVECTOR& aNormal );
|
||||
|
||||
void ReNameNodes( void ) override;
|
||||
bool WriteVRML( std::ostream& aFile, bool aReuseFlag ) override;
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
};
|
||||
|
||||
#endif // SG_NORMALS_H
|
||||
@@ -1,900 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "3d_cache/sg/sg_shape.h"
|
||||
#include "3d_cache/sg/sg_faceset.h"
|
||||
#include "3d_cache/sg/sg_appearance.h"
|
||||
#include "3d_cache/sg/sg_helpers.h"
|
||||
#include "3d_cache/sg/sg_coordindex.h"
|
||||
#include "3d_cache/sg/sg_coords.h"
|
||||
#include "3d_cache/sg/sg_colors.h"
|
||||
#include "3d_cache/sg/sg_normals.h"
|
||||
|
||||
|
||||
SGSHAPE::SGSHAPE( SGNODE* aParent ) : SGNODE( aParent )
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_SHAPE;
|
||||
m_Appearance = NULL;
|
||||
m_RAppearance = NULL;
|
||||
m_FaceSet = NULL;
|
||||
m_RFaceSet = NULL;
|
||||
|
||||
if( NULL != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] inappropriate parent to SGSHAPE (type ";
|
||||
ostr << aParent->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
else if( NULL != aParent && S3D::SGTYPE_TRANSFORM == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGSHAPE::~SGSHAPE()
|
||||
{
|
||||
// drop references
|
||||
if( m_RAppearance )
|
||||
{
|
||||
m_RAppearance->delNodeRef( this );
|
||||
m_RAppearance = NULL;
|
||||
}
|
||||
|
||||
if( m_RFaceSet )
|
||||
{
|
||||
m_RFaceSet->delNodeRef( this );
|
||||
m_RFaceSet = NULL;
|
||||
}
|
||||
|
||||
// delete objects
|
||||
if( m_Appearance )
|
||||
{
|
||||
m_Appearance->SetParent( NULL, false );
|
||||
delete m_Appearance;
|
||||
m_Appearance = NULL;
|
||||
}
|
||||
|
||||
if( m_FaceSet )
|
||||
{
|
||||
m_FaceSet->SetParent( NULL, false );
|
||||
delete m_FaceSet;
|
||||
m_FaceSet = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGSHAPE::SetParent( SGNODE* aParent, bool notify )
|
||||
{
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
|
||||
// handle the change in parents
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = NULL;
|
||||
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a SGTRANSFORM may be parent to a SGSHAPE
|
||||
if( NULL != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
|
||||
if( m_Parent )
|
||||
m_Parent->AddChildNode( this );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGSHAPE::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
SGNODE* tmp = NULL;
|
||||
|
||||
if( NULL != m_Appearance )
|
||||
{
|
||||
tmp = m_Appearance->FindNode( aNodeName, this );
|
||||
|
||||
if( tmp )
|
||||
{
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
if( NULL != m_FaceSet )
|
||||
{
|
||||
tmp = m_FaceSet->FindNode( aNodeName, this );
|
||||
|
||||
if( tmp )
|
||||
{
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
// query the parent if appropriate
|
||||
if( aCaller == m_Parent || NULL == m_Parent )
|
||||
return NULL;
|
||||
|
||||
return m_Parent->FindNode( aNodeName, this );
|
||||
}
|
||||
|
||||
|
||||
void SGSHAPE::unlinkNode( const SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( NULL == aNode )
|
||||
return;
|
||||
|
||||
if( isChild )
|
||||
{
|
||||
if( aNode == m_Appearance )
|
||||
{
|
||||
m_Appearance = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if( aNode == m_FaceSet )
|
||||
{
|
||||
m_FaceSet = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( aNode == m_RAppearance )
|
||||
{
|
||||
delNodeRef( this );
|
||||
m_RAppearance = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if( aNode == m_RFaceSet )
|
||||
{
|
||||
delNodeRef( this );
|
||||
m_RFaceSet = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unlinkNode() did not find its target";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGSHAPE::unlinkChildNode( const SGNODE* aNode )
|
||||
{
|
||||
unlinkNode( aNode, true );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGSHAPE::unlinkRefNode( const SGNODE* aNode )
|
||||
{
|
||||
unlinkNode( aNode, false );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGSHAPE::addNode( SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( NULL == aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aNode";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_APPEARANCE == aNode->GetNodeType() )
|
||||
{
|
||||
if( m_Appearance || m_RAppearance )
|
||||
{
|
||||
if( aNode != m_Appearance && aNode != m_RAppearance )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] assigning multiple Appearance nodes";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if( isChild )
|
||||
{
|
||||
m_Appearance = (SGAPPEARANCE*)aNode;
|
||||
m_Appearance->SetParent( this );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_RAppearance = (SGAPPEARANCE*)aNode;
|
||||
m_RAppearance->addNodeRef( this );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_FACESET == aNode->GetNodeType() )
|
||||
{
|
||||
if( m_FaceSet || m_RFaceSet )
|
||||
{
|
||||
if( aNode != m_FaceSet && aNode != m_RFaceSet )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] assigning multiple FaceSet nodes";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if( isChild )
|
||||
{
|
||||
m_FaceSet = (SGFACESET*)aNode;
|
||||
m_FaceSet->SetParent( this );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_RFaceSet = (SGFACESET*)aNode;
|
||||
m_RFaceSet->addNodeRef( this );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] object '" << aNode->GetName();
|
||||
ostr << "' is not a valid type for this object (" << aNode->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SGSHAPE::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
return addNode( aNode, false );
|
||||
}
|
||||
|
||||
|
||||
bool SGSHAPE::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
return addNode( aNode, true );
|
||||
}
|
||||
|
||||
|
||||
void SGSHAPE::ReNameNodes( void )
|
||||
{
|
||||
m_written = false;
|
||||
|
||||
// rename this node
|
||||
m_Name.clear();
|
||||
GetName();
|
||||
|
||||
// rename Appearance
|
||||
if( m_Appearance )
|
||||
m_Appearance->ReNameNodes();
|
||||
|
||||
// rename FaceSet
|
||||
if( m_FaceSet )
|
||||
m_FaceSet->ReNameNodes();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGSHAPE::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
{
|
||||
if( !m_Appearance && !m_RAppearance
|
||||
&& !m_FaceSet && !m_RFaceSet )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( aReuseFlag )
|
||||
{
|
||||
if( !m_written )
|
||||
{
|
||||
aFile << "DEF " << GetName() << " Shape {\n";
|
||||
m_written = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
aFile << " USE " << GetName() << "\n";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aFile << " Shape {\n";
|
||||
}
|
||||
|
||||
if( m_Appearance )
|
||||
m_Appearance->WriteVRML( aFile, aReuseFlag );
|
||||
|
||||
if( m_RAppearance )
|
||||
m_RAppearance->WriteVRML( aFile, aReuseFlag );
|
||||
|
||||
if( m_FaceSet )
|
||||
m_FaceSet->WriteVRML( aFile, aReuseFlag );
|
||||
|
||||
if( m_RFaceSet )
|
||||
m_RFaceSet->WriteVRML( aFile, aReuseFlag );
|
||||
|
||||
aFile << "}\n";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGSHAPE::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; m_aParent is NULL";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = m_Parent;
|
||||
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( parentNode != m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; parentNode != m_aParent";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !aFile.good() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if any references are unwritten and swap parents if so
|
||||
if( NULL != m_RAppearance && !m_RAppearance->isWritten() )
|
||||
m_RAppearance->SwapParent(this);
|
||||
|
||||
if( NULL != m_RFaceSet && !m_RFaceSet->isWritten() )
|
||||
m_RFaceSet->SwapParent( this );
|
||||
|
||||
aFile << "[" << GetName() << "]";
|
||||
#define NITEMS 4
|
||||
bool items[NITEMS];
|
||||
int i;
|
||||
|
||||
for( i = 0; i < NITEMS; ++i )
|
||||
items[i] = 0;
|
||||
|
||||
i = 0;
|
||||
if( NULL != m_Appearance )
|
||||
items[i] = true;
|
||||
|
||||
++i;
|
||||
if( NULL != m_RAppearance )
|
||||
items[i] = true;
|
||||
|
||||
++i;
|
||||
if( NULL != m_FaceSet )
|
||||
items[i] = true;
|
||||
|
||||
++i;
|
||||
if( NULL != m_RFaceSet )
|
||||
items[i] = true;
|
||||
|
||||
for( int jj = 0; jj < NITEMS; ++jj )
|
||||
aFile.write( (char*)&items[jj], sizeof(bool) );
|
||||
|
||||
if( items[0] )
|
||||
m_Appearance->WriteCache( aFile, this );
|
||||
|
||||
if( items[1] )
|
||||
aFile << "[" << m_RAppearance->GetName() << "]";
|
||||
|
||||
if( items[2] )
|
||||
m_FaceSet->WriteCache( aFile, this );
|
||||
|
||||
if( items[3] )
|
||||
aFile << "[" << m_RFaceSet->GetName() << "]";
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
m_written = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( m_Appearance || m_RAppearance || m_FaceSet || m_RFaceSet )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] non-empty node";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#define NITEMS 4
|
||||
bool items[NITEMS];
|
||||
|
||||
for( int i = 0; i < NITEMS; ++i )
|
||||
aFile.read( (char*)&items[i], sizeof(bool) );
|
||||
|
||||
if( ( items[0] && items[1] ) || ( items[2] && items[3] ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; multiple item definitions at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string name;
|
||||
|
||||
if( items[0] )
|
||||
{
|
||||
if( S3D::SGTYPE_APPEARANCE != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad child apperance tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
m_Appearance = new SGAPPEARANCE( this );
|
||||
m_Appearance->SetName( name.c_str() );
|
||||
|
||||
if( !m_Appearance->ReadCache( aFile, this ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data while reading appearance '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if( items[1] )
|
||||
{
|
||||
if( S3D::SGTYPE_APPEARANCE != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad ref appearance tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = FindNode( name.c_str(), this );
|
||||
|
||||
if( !np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: cannot find ref appearance '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_APPEARANCE != np->GetNodeType() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: type is not SGAPPEARANCE '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
m_RAppearance = (SGAPPEARANCE*)np;
|
||||
m_RAppearance->addNodeRef( this );
|
||||
}
|
||||
|
||||
if( items[2] )
|
||||
{
|
||||
if( S3D::SGTYPE_FACESET != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad child face set tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
m_FaceSet = new SGFACESET( this );
|
||||
m_FaceSet->SetName( name.c_str() );
|
||||
|
||||
if( !m_FaceSet->ReadCache( aFile, this ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data while reading face set '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if( items[3] )
|
||||
{
|
||||
if( S3D::SGTYPE_FACESET != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad ref face set tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = FindNode( name.c_str(), this );
|
||||
|
||||
if( !np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: cannot find ref face set '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_FACESET != np->GetNodeType() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: type is not SGFACESET '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
m_RFaceSet = (SGFACESET*)np;
|
||||
m_RFaceSet->addNodeRef( this );
|
||||
}
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SGSHAPE::Prepare( const glm::dmat4* aTransform,
|
||||
S3D::MATLIST& materials, std::vector< SMESH >& meshes )
|
||||
{
|
||||
SMESH m;
|
||||
S3D::INIT_SMESH( m );
|
||||
|
||||
SGAPPEARANCE* pa = m_Appearance;
|
||||
SGFACESET* pf = m_FaceSet;
|
||||
|
||||
if( NULL == pa )
|
||||
pa = m_RAppearance;
|
||||
|
||||
if( NULL == pf )
|
||||
pf = m_RFaceSet;
|
||||
|
||||
// no face sets = nothing to render, which is valid though pointless
|
||||
if( NULL == pf )
|
||||
return true;
|
||||
|
||||
if( !pf->validate() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad model; inconsistent data";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
if( NULL == pa )
|
||||
{
|
||||
m.m_MaterialIdx = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int idx;
|
||||
|
||||
if( !S3D::GetMatIndex( materials, pa, idx ) )
|
||||
{
|
||||
m.m_MaterialIdx = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m.m_MaterialIdx = idx;
|
||||
}
|
||||
}
|
||||
|
||||
SGCOLORS* pc = pf->m_Colors;
|
||||
SGCOORDS* pv = pf->m_Coords;
|
||||
SGCOORDINDEX* vidx = pf->m_CoordIndices;
|
||||
SGNORMALS* pn = pf->m_Normals;
|
||||
|
||||
if( NULL == pc )
|
||||
pc = pf->m_RColors;
|
||||
|
||||
if( NULL == pv )
|
||||
pv = pf->m_RCoords;
|
||||
|
||||
if( NULL == pn )
|
||||
pn = pf->m_RNormals;
|
||||
|
||||
// set the vertex points and indices
|
||||
size_t nCoords = 0;
|
||||
SGPOINT* pCoords = NULL;
|
||||
pv->GetCoordsList( nCoords, pCoords );
|
||||
|
||||
size_t nColors = 0;
|
||||
SGCOLOR* pColors = NULL;
|
||||
|
||||
if( pc )
|
||||
{
|
||||
// check the vertex colors
|
||||
pc->GetColorList( nColors, pColors );
|
||||
|
||||
if( nColors < nCoords )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad model; not enough colors per vertex (";
|
||||
ostr << nColors << " vs " << nCoords << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// set the vertex indices
|
||||
size_t nvidx = 0;
|
||||
int* lv = NULL;
|
||||
vidx->GetIndices( nvidx, lv );
|
||||
|
||||
// note: reduce the vertex set to include only the referenced vertices
|
||||
std::vector< int > vertices; // store the list of temp vertex indices
|
||||
std::map< int, unsigned int > indexmap; // map temp vertex to true vertex
|
||||
std::map< int, unsigned int >::iterator mit;
|
||||
|
||||
for( unsigned int i = 0; i < nvidx; ++i )
|
||||
{
|
||||
mit = indexmap.find( lv[i] );
|
||||
|
||||
if( mit == indexmap.end() )
|
||||
{
|
||||
indexmap.insert( std::pair< int, unsigned int >( lv[i], vertices.size() ) );
|
||||
vertices.push_back( lv[i] );
|
||||
}
|
||||
}
|
||||
|
||||
if( vertices.size() < 3 )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad model; not enough vertices";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
// construct the final vertex/color list
|
||||
SFVEC3F* lColors = NULL;
|
||||
SFVEC3F* lCoords = new SFVEC3F[ vertices.size() ];
|
||||
int ti;
|
||||
|
||||
if( pc )
|
||||
{
|
||||
lColors = new SFVEC3F[vertices.size()];
|
||||
m.m_Color = lColors;
|
||||
}
|
||||
|
||||
|
||||
if( pc )
|
||||
{
|
||||
for( size_t i = 0; i < vertices.size(); ++i )
|
||||
{
|
||||
ti = vertices[i];
|
||||
glm::dvec4 pt( pCoords[ti].x, pCoords[ti].y, pCoords[ti].z, 1.0 );
|
||||
pt = (*aTransform) * pt;
|
||||
pColors[ti].GetColor( lColors[i].x, lColors[i].y, lColors[i].z );
|
||||
lCoords[i] = SFVEC3F( pt.x, pt.y, pt.z );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( size_t i = 0; i < vertices.size(); ++i )
|
||||
{
|
||||
ti = vertices[i];
|
||||
glm::dvec4 pt( pCoords[ti].x, pCoords[ti].y, pCoords[ti].z, 1.0 );
|
||||
pt = (*aTransform) * pt;
|
||||
lCoords[i] = SFVEC3F( pt.x, pt.y, pt.z );
|
||||
}
|
||||
}
|
||||
|
||||
m.m_VertexSize = (unsigned int) vertices.size();
|
||||
m.m_Positions = lCoords;
|
||||
unsigned int* lvidx = new unsigned int[ nvidx ];
|
||||
|
||||
for( unsigned int i = 0; i < nvidx; ++i )
|
||||
{
|
||||
mit = indexmap.find( lv[i] );
|
||||
lvidx[i] = mit->second;
|
||||
}
|
||||
|
||||
m.m_FaceIdxSize = (unsigned int )nvidx;
|
||||
m.m_FaceIdx = lvidx;
|
||||
|
||||
// set the per-vertex normals
|
||||
size_t nNorms = 0;
|
||||
SGVECTOR* pNorms = NULL;
|
||||
double x, y, z;
|
||||
|
||||
pn->GetNormalList( nNorms, pNorms );
|
||||
SFVEC3F* lNorms = new SFVEC3F[ vertices.size() ];
|
||||
|
||||
for( size_t i = 0; i < vertices.size(); ++i )
|
||||
{
|
||||
ti = vertices[i];
|
||||
pNorms[ti].GetVector( x, y, z );
|
||||
glm::dvec4 pt( x, y, z, 0.0 );
|
||||
pt = (*aTransform) * pt;
|
||||
|
||||
lNorms[i] = SFVEC3F( pt.x, pt.y, pt.z );
|
||||
}
|
||||
|
||||
m.m_Normals = lNorms;
|
||||
meshes.push_back( m );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file sg_shape.h
|
||||
* defines a complex 3D shape for a scenegraph object
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SG_SHAPE_H
|
||||
#define SG_SHAPE_H
|
||||
|
||||
#include <vector>
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
|
||||
class SGAPPEARANCE;
|
||||
class SGFACESET;
|
||||
|
||||
class SGSHAPE : public SGNODE
|
||||
{
|
||||
private:
|
||||
void unlinkNode( const SGNODE* aNode, bool isChild );
|
||||
bool addNode( SGNODE* aNode, bool isChild );
|
||||
|
||||
public:
|
||||
// owned node
|
||||
SGAPPEARANCE* m_Appearance;
|
||||
SGFACESET* m_FaceSet;
|
||||
|
||||
// referenced nodes
|
||||
SGAPPEARANCE* m_RAppearance;
|
||||
SGFACESET* m_RFaceSet;
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
|
||||
public:
|
||||
SGSHAPE( SGNODE* aParent );
|
||||
virtual ~SGSHAPE();
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) override;
|
||||
bool AddRefNode( SGNODE* aNode ) override;
|
||||
bool AddChildNode( SGNODE* aNode ) override;
|
||||
|
||||
void ReNameNodes( void ) override;
|
||||
bool WriteVRML( std::ostream& aFile, bool aReuseFlag ) override;
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
|
||||
bool Prepare( const glm::dmat4* aTransform,
|
||||
S3D::MATLIST& materials, std::vector< SMESH >& meshes );
|
||||
};
|
||||
|
||||
/*
|
||||
p.107
|
||||
Shape {
|
||||
appearance NULL
|
||||
geometry NULL
|
||||
}
|
||||
*/
|
||||
|
||||
#endif // SG_SHAPE_H
|
||||
@@ -0,0 +1,689 @@
|
||||
/**
|
||||
* @file 3d_canvas.cpp
|
||||
*/
|
||||
#include <fctsys.h>
|
||||
#include <trigo.h>
|
||||
|
||||
#include <wx/image.h>
|
||||
|
||||
#if !wxUSE_GLCANVAS
|
||||
#error Please set wxUSE_GLCANVAS to 1 in setup.h.
|
||||
#endif
|
||||
|
||||
#include <wx/dataobj.h>
|
||||
#include <wx/clipbrd.h>
|
||||
#include <wx/wupdlock.h>
|
||||
|
||||
#include <gestfich.h>
|
||||
|
||||
#include <3d_viewer.h>
|
||||
#include <3d_canvas.h>
|
||||
#include <info3d_visu.h>
|
||||
#include <trackball.h>
|
||||
#include <3d_viewer_id.h>
|
||||
|
||||
|
||||
// -----------------
|
||||
// helper function (from wxWidgets, opengl/cube.cpp sample
|
||||
// -----------------
|
||||
void CheckGLError()
|
||||
{
|
||||
GLenum errLast = GL_NO_ERROR;
|
||||
|
||||
for ( ; ; )
|
||||
{
|
||||
GLenum err = glGetError();
|
||||
if ( err == GL_NO_ERROR )
|
||||
return;
|
||||
|
||||
// normally the error is reset by the call to glGetError() but if
|
||||
// glGetError() itself returns an error, we risk looping forever here
|
||||
// so check that we get a different error than the last time
|
||||
if ( err == errLast )
|
||||
{
|
||||
wxLogError(wxT("OpenGL error state couldn't be reset."));
|
||||
return;
|
||||
}
|
||||
|
||||
errLast = err;
|
||||
|
||||
wxLogError(wxT("OpenGL error %d"), err);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* EDA_3D_CANVAS implementation
|
||||
*/
|
||||
|
||||
BEGIN_EVENT_TABLE( EDA_3D_CANVAS, wxGLCanvas )
|
||||
EVT_PAINT( EDA_3D_CANVAS::OnPaint )
|
||||
|
||||
// key event:
|
||||
EVT_CHAR( EDA_3D_CANVAS::OnChar )
|
||||
|
||||
// mouse events
|
||||
EVT_RIGHT_DOWN( EDA_3D_CANVAS::OnRightClick )
|
||||
EVT_MOUSEWHEEL( EDA_3D_CANVAS::OnMouseWheel )
|
||||
EVT_MOTION( EDA_3D_CANVAS::OnMouseMove )
|
||||
|
||||
// other events
|
||||
EVT_ERASE_BACKGROUND( EDA_3D_CANVAS::OnEraseBackground )
|
||||
EVT_MENU_RANGE( ID_POPUP_3D_VIEW_START, ID_POPUP_3D_VIEW_END, EDA_3D_CANVAS::OnPopUpMenu )
|
||||
END_EVENT_TABLE()
|
||||
|
||||
|
||||
EDA_3D_CANVAS::EDA_3D_CANVAS( EDA_3D_FRAME* parent, int* attribList ) :
|
||||
wxGLCanvas( parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize,
|
||||
wxFULL_REPAINT_ON_RESIZE )
|
||||
{
|
||||
m_init = false;
|
||||
|
||||
// Clear all gl list identifiers:
|
||||
for( int ii = GL_ID_BEGIN; ii < GL_ID_END; ii++ )
|
||||
m_glLists[ii] = 0;
|
||||
|
||||
// Explicitly create a new rendering context instance for this canvas.
|
||||
m_glRC = new wxGLContext( this );
|
||||
|
||||
DisplayStatus();
|
||||
}
|
||||
|
||||
|
||||
EDA_3D_CANVAS::~EDA_3D_CANVAS()
|
||||
{
|
||||
ClearLists();
|
||||
m_init = false;
|
||||
delete m_glRC;
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_CANVAS::ClearLists( GLuint aGlList )
|
||||
{
|
||||
if( aGlList )
|
||||
{
|
||||
if( m_glLists[aGlList] > 0 )
|
||||
glDeleteLists( m_glLists[aGlList], 1 );
|
||||
|
||||
m_glLists[aGlList] = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for( int ii = GL_ID_BEGIN; ii < GL_ID_END; ii++ )
|
||||
{
|
||||
if( m_glLists[ii] > 0 )
|
||||
glDeleteLists( m_glLists[ii], 1 );
|
||||
|
||||
m_glLists[ii] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_CANVAS::OnChar( wxKeyEvent& event )
|
||||
{
|
||||
SetView3D( event.GetKeyCode() );
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_CANVAS::SetView3D( int keycode )
|
||||
{
|
||||
int ii;
|
||||
double delta_move = 0.7 * g_Parm_3D_Visu.m_Zoom;
|
||||
|
||||
switch( keycode )
|
||||
{
|
||||
case WXK_LEFT:
|
||||
m_draw3dOffset.x -= delta_move;
|
||||
break;
|
||||
|
||||
case WXK_RIGHT:
|
||||
m_draw3dOffset.x += delta_move;
|
||||
break;
|
||||
|
||||
case WXK_UP:
|
||||
m_draw3dOffset.y += delta_move;
|
||||
break;
|
||||
|
||||
case WXK_DOWN:
|
||||
m_draw3dOffset.y -= delta_move;
|
||||
break;
|
||||
|
||||
case WXK_HOME:
|
||||
g_Parm_3D_Visu.m_Zoom = 1.0;
|
||||
m_draw3dOffset.x = m_draw3dOffset.y = 0;
|
||||
trackball( g_Parm_3D_Visu.m_Quat, 0.0, 0.0, 0.0, 0.0 );
|
||||
break;
|
||||
|
||||
case WXK_END:
|
||||
break;
|
||||
|
||||
case WXK_F1:
|
||||
g_Parm_3D_Visu.m_Zoom /= 1.4;
|
||||
if( g_Parm_3D_Visu.m_Zoom <= 0.01 )
|
||||
g_Parm_3D_Visu.m_Zoom = 0.01;
|
||||
break;
|
||||
|
||||
case WXK_F2:
|
||||
g_Parm_3D_Visu.m_Zoom *= 1.4;
|
||||
break;
|
||||
|
||||
case '+':
|
||||
break;
|
||||
|
||||
case '-':
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
case 'R':
|
||||
m_draw3dOffset.x = m_draw3dOffset.y = 0;
|
||||
for( ii = 0; ii < 4; ii++ )
|
||||
g_Parm_3D_Visu.m_Rot[ii] = 0.0;
|
||||
|
||||
trackball( g_Parm_3D_Visu.m_Quat, 0.0, 0.0, 0.0, 0.0 );
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
for( ii = 0; ii < 4; ii++ )
|
||||
g_Parm_3D_Visu.m_Rot[ii] = 0.0;
|
||||
|
||||
trackball( g_Parm_3D_Visu.m_Quat, 0.0, 0.0, 0.0, 0.0 );
|
||||
g_Parm_3D_Visu.m_ROTZ = -90;
|
||||
g_Parm_3D_Visu.m_ROTX = -90;
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
for( ii = 0; ii < 4; ii++ )
|
||||
g_Parm_3D_Visu.m_Rot[ii] = 0.0;
|
||||
|
||||
trackball( g_Parm_3D_Visu.m_Quat, 0.0, 0.0, 0.0, 0.0 );
|
||||
g_Parm_3D_Visu.m_ROTZ = 90;
|
||||
g_Parm_3D_Visu.m_ROTX = -90;
|
||||
break;
|
||||
|
||||
case 'y':
|
||||
for( ii = 0; ii < 4; ii++ )
|
||||
g_Parm_3D_Visu.m_Rot[ii] = 0.0;
|
||||
|
||||
trackball( g_Parm_3D_Visu.m_Quat, 0.0, 0.0, 0.0, 0.0 );
|
||||
g_Parm_3D_Visu.m_ROTX = -90;
|
||||
break;
|
||||
|
||||
case 'Y':
|
||||
for( ii = 0; ii < 4; ii++ )
|
||||
g_Parm_3D_Visu.m_Rot[ii] = 0.0;
|
||||
|
||||
trackball( g_Parm_3D_Visu.m_Quat, 0.0, 0.0, 0.0, 0.0 );
|
||||
g_Parm_3D_Visu.m_ROTX = -90;
|
||||
g_Parm_3D_Visu.m_ROTZ = -180;
|
||||
break;
|
||||
|
||||
case 'z':
|
||||
for( ii = 0; ii < 4; ii++ )
|
||||
g_Parm_3D_Visu.m_Rot[ii] = 0.0;
|
||||
|
||||
trackball( g_Parm_3D_Visu.m_Quat, 0.0, 0.0, 0.0, 0.0 );
|
||||
break;
|
||||
|
||||
case 'Z':
|
||||
for( ii = 0; ii < 4; ii++ )
|
||||
g_Parm_3D_Visu.m_Rot[ii] = 0.0;
|
||||
|
||||
trackball( g_Parm_3D_Visu.m_Quat, 0.0, 0.0, 0.0, 0.0 );
|
||||
g_Parm_3D_Visu.m_ROTX = -180;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
DisplayStatus();
|
||||
Refresh( false );
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_CANVAS::OnMouseWheel( wxMouseEvent& event )
|
||||
{
|
||||
if( event.ShiftDown() )
|
||||
{
|
||||
if( event.GetWheelRotation() < 0 )
|
||||
{
|
||||
/* up */
|
||||
SetView3D( WXK_UP );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* down */
|
||||
SetView3D( WXK_DOWN );
|
||||
}
|
||||
}
|
||||
else if( event.ControlDown() )
|
||||
{
|
||||
if( event.GetWheelRotation() > 0 )
|
||||
{
|
||||
/* right */
|
||||
SetView3D( WXK_RIGHT );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* left */
|
||||
SetView3D( WXK_LEFT );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( event.GetWheelRotation() > 0 )
|
||||
{
|
||||
g_Parm_3D_Visu.m_Zoom /= 1.4;
|
||||
|
||||
if( g_Parm_3D_Visu.m_Zoom <= 0.01 )
|
||||
g_Parm_3D_Visu.m_Zoom = 0.01;
|
||||
}
|
||||
else
|
||||
g_Parm_3D_Visu.m_Zoom *= 1.4;
|
||||
|
||||
DisplayStatus();
|
||||
Refresh( false );
|
||||
}
|
||||
|
||||
g_Parm_3D_Visu.m_Beginx = event.GetX();
|
||||
g_Parm_3D_Visu.m_Beginy = event.GetY();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_CANVAS::OnMouseMove( wxMouseEvent& event )
|
||||
{
|
||||
wxSize size( GetClientSize() );
|
||||
double spin_quat[4];
|
||||
|
||||
if( event.Dragging() )
|
||||
{
|
||||
if( event.LeftIsDown() )
|
||||
{
|
||||
/* drag in progress, simulate trackball */
|
||||
trackball( spin_quat,
|
||||
(2.0 * g_Parm_3D_Visu.m_Beginx - size.x) / size.x,
|
||||
(size.y - 2.0 * g_Parm_3D_Visu.m_Beginy) / size.y,
|
||||
( 2.0 * event.GetX() - size.x) / size.x,
|
||||
( size.y - 2.0 * event.GetY() ) / size.y );
|
||||
|
||||
add_quats( spin_quat, g_Parm_3D_Visu.m_Quat, g_Parm_3D_Visu.m_Quat );
|
||||
}
|
||||
else if( event.MiddleIsDown() )
|
||||
{
|
||||
/* middle button drag -> pan */
|
||||
|
||||
/* Current zoom and an additional factor are taken into account
|
||||
* for the amount of panning. */
|
||||
const double PAN_FACTOR = 8.0 * g_Parm_3D_Visu.m_Zoom;
|
||||
m_draw3dOffset.x -= PAN_FACTOR *
|
||||
( g_Parm_3D_Visu.m_Beginx - event.GetX() ) / size.x;
|
||||
m_draw3dOffset.y -= PAN_FACTOR *
|
||||
(event.GetY() - g_Parm_3D_Visu.m_Beginy) / size.y;
|
||||
}
|
||||
|
||||
/* orientation has changed, redraw mesh */
|
||||
DisplayStatus();
|
||||
Refresh( false );
|
||||
}
|
||||
|
||||
g_Parm_3D_Visu.m_Beginx = event.GetX();
|
||||
g_Parm_3D_Visu.m_Beginy = event.GetY();
|
||||
}
|
||||
|
||||
|
||||
/* Construct and display a popup menu when the right button is clicked.
|
||||
*/
|
||||
void EDA_3D_CANVAS::OnRightClick( wxMouseEvent& event )
|
||||
{
|
||||
wxPoint pos;
|
||||
wxMenu PopUpMenu;
|
||||
|
||||
pos.x = event.GetX();
|
||||
pos.y = event.GetY();
|
||||
|
||||
wxMenuItem* item = new wxMenuItem( &PopUpMenu, ID_POPUP_ZOOMIN, _( "Zoom +" ) );
|
||||
item->SetBitmap( KiBitmap( zoom_in_xpm ));
|
||||
PopUpMenu.Append( item );
|
||||
|
||||
item = new wxMenuItem( &PopUpMenu, ID_POPUP_ZOOMOUT, _( "Zoom -" ) );
|
||||
item->SetBitmap( KiBitmap( zoom_out_xpm ));
|
||||
PopUpMenu.Append( item );
|
||||
|
||||
PopUpMenu.AppendSeparator();
|
||||
item = new wxMenuItem( &PopUpMenu, ID_POPUP_VIEW_ZPOS, _( "Top View" ) );
|
||||
item->SetBitmap( KiBitmap( axis3d_top_xpm ));
|
||||
PopUpMenu.Append( item );
|
||||
|
||||
item = new wxMenuItem( &PopUpMenu, ID_POPUP_VIEW_ZNEG, _( "Bottom View" ) );
|
||||
item->SetBitmap( KiBitmap( axis3d_bottom_xpm ));
|
||||
PopUpMenu.Append( item );
|
||||
|
||||
PopUpMenu.AppendSeparator();
|
||||
item = new wxMenuItem( &PopUpMenu, ID_POPUP_VIEW_XPOS, _( "Right View" ) );
|
||||
item->SetBitmap( KiBitmap( axis3d_right_xpm ));
|
||||
PopUpMenu.Append( item );
|
||||
|
||||
item = new wxMenuItem( &PopUpMenu, ID_POPUP_VIEW_XNEG, _( "Left View" ) );
|
||||
item->SetBitmap( KiBitmap( axis3d_left_xpm ));
|
||||
PopUpMenu.Append( item );
|
||||
|
||||
PopUpMenu.AppendSeparator();
|
||||
item = new wxMenuItem( &PopUpMenu, ID_POPUP_VIEW_YPOS, _( "Front View" ) );
|
||||
item->SetBitmap( KiBitmap( axis3d_front_xpm ));
|
||||
PopUpMenu.Append( item );
|
||||
|
||||
item = new wxMenuItem( &PopUpMenu, ID_POPUP_VIEW_YNEG, _( "Back View" ) );
|
||||
item->SetBitmap( KiBitmap( axis3d_back_xpm ));
|
||||
PopUpMenu.Append( item );
|
||||
|
||||
PopUpMenu.AppendSeparator();
|
||||
item = new wxMenuItem( &PopUpMenu, ID_POPUP_MOVE3D_LEFT, _( "Move left <-" ) );
|
||||
item->SetBitmap( KiBitmap( left_xpm ));
|
||||
PopUpMenu.Append( item );
|
||||
|
||||
item = new wxMenuItem( &PopUpMenu, ID_POPUP_MOVE3D_RIGHT, _( "Move right ->" ) );
|
||||
item->SetBitmap( KiBitmap( right_xpm ));
|
||||
PopUpMenu.Append( item );
|
||||
|
||||
item = new wxMenuItem( &PopUpMenu, ID_POPUP_MOVE3D_UP, _( "Move Up ^" ) );
|
||||
item->SetBitmap( KiBitmap( up_xpm ));
|
||||
PopUpMenu.Append( item );
|
||||
|
||||
item = new wxMenuItem( &PopUpMenu, ID_POPUP_MOVE3D_DOWN, _( "Move Down" ) );
|
||||
item->SetBitmap( KiBitmap( down_xpm ));
|
||||
PopUpMenu.Append( item );
|
||||
|
||||
PopupMenu( &PopUpMenu, pos );
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_CANVAS::OnPopUpMenu( wxCommandEvent& event )
|
||||
{
|
||||
int key = 0;
|
||||
|
||||
switch( event.GetId() )
|
||||
{
|
||||
case ID_POPUP_ZOOMIN:
|
||||
key = WXK_F1;
|
||||
break;
|
||||
|
||||
case ID_POPUP_ZOOMOUT:
|
||||
key = WXK_F2;
|
||||
break;
|
||||
|
||||
case ID_POPUP_VIEW_XPOS:
|
||||
key = 'x';
|
||||
break;
|
||||
|
||||
case ID_POPUP_VIEW_XNEG:
|
||||
key = 'X';
|
||||
break;
|
||||
|
||||
case ID_POPUP_VIEW_YPOS:
|
||||
key = 'y';
|
||||
break;
|
||||
|
||||
case ID_POPUP_VIEW_YNEG:
|
||||
key = 'Y';
|
||||
break;
|
||||
|
||||
case ID_POPUP_VIEW_ZPOS:
|
||||
key = 'z';
|
||||
break;
|
||||
|
||||
case ID_POPUP_VIEW_ZNEG:
|
||||
key = 'Z';
|
||||
break;
|
||||
|
||||
case ID_POPUP_MOVE3D_LEFT:
|
||||
key = WXK_LEFT;
|
||||
break;
|
||||
|
||||
case ID_POPUP_MOVE3D_RIGHT:
|
||||
key = WXK_RIGHT;
|
||||
break;
|
||||
|
||||
case ID_POPUP_MOVE3D_UP:
|
||||
key = WXK_UP;
|
||||
break;
|
||||
|
||||
case ID_POPUP_MOVE3D_DOWN:
|
||||
key = WXK_DOWN;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
SetView3D( key );
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_CANVAS::DisplayStatus()
|
||||
{
|
||||
wxString msg;
|
||||
|
||||
msg.Printf( wxT( "dx %3.2f" ), m_draw3dOffset.x );
|
||||
Parent()->SetStatusText( msg, 1 );
|
||||
|
||||
msg.Printf( wxT( "dy %3.2f" ), m_draw3dOffset.y );
|
||||
Parent()->SetStatusText( msg, 2 );
|
||||
|
||||
msg.Printf( wxT( "View: %3.1f" ), 45 * g_Parm_3D_Visu.m_Zoom );
|
||||
Parent()->SetStatusText( msg, 3 );
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_CANVAS::OnPaint( wxPaintEvent& event )
|
||||
{
|
||||
wxPaintDC dc( this );
|
||||
|
||||
Redraw();
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_CANVAS::OnEraseBackground( wxEraseEvent& event )
|
||||
{
|
||||
// Do nothing, to avoid flashing.
|
||||
}
|
||||
|
||||
|
||||
/* Initialize broad parameters for OpenGL */
|
||||
void EDA_3D_CANVAS::InitGL()
|
||||
{
|
||||
wxSize size = GetClientSize();
|
||||
|
||||
if( !m_init )
|
||||
{
|
||||
m_init = true;
|
||||
g_Parm_3D_Visu.m_Zoom = 1.0;
|
||||
m_ZBottom = 1.0;
|
||||
m_ZTop = 10.0;
|
||||
|
||||
glDisable( GL_CULL_FACE ); // show back faces
|
||||
glEnable( GL_DEPTH_TEST ); // Enable z-buferring
|
||||
glEnable( GL_ALPHA_TEST );
|
||||
glEnable( GL_LINE_SMOOTH );
|
||||
// glEnable(GL_POLYGON_SMOOTH); // creates issues with some graphic cards
|
||||
glShadeModel( GL_SMOOTH );
|
||||
glEnable( GL_COLOR_MATERIAL );
|
||||
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
|
||||
|
||||
// speedups
|
||||
glEnable( GL_DITHER );
|
||||
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_DONT_CARE );
|
||||
glHint( GL_LINE_SMOOTH_HINT, GL_NICEST );
|
||||
glHint( GL_POLYGON_SMOOTH_HINT, GL_NICEST );
|
||||
|
||||
// Initialize alpha blending function.
|
||||
glEnable( GL_BLEND );
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
}
|
||||
|
||||
// set viewing projection
|
||||
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glLoadIdentity();
|
||||
|
||||
#define MAX_VIEW_ANGLE 160.0 / 45.0
|
||||
if( g_Parm_3D_Visu.m_Zoom > MAX_VIEW_ANGLE )
|
||||
g_Parm_3D_Visu.m_Zoom = MAX_VIEW_ANGLE;
|
||||
|
||||
if( Parent()->ModeIsOrtho() )
|
||||
{
|
||||
// OrthoReductionFactor is chosen so as to provide roughly the same size as
|
||||
// Perspective View
|
||||
const double orthoReductionFactor = 400 / g_Parm_3D_Visu.m_Zoom;
|
||||
|
||||
// Initialize Projection Matrix for Ortographic View
|
||||
glOrtho( -size.x / orthoReductionFactor, size.x / orthoReductionFactor,
|
||||
-size.y / orthoReductionFactor, size.y / orthoReductionFactor, 1, 10 );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ratio width / height of the window display
|
||||
double ratio_HV = (double) size.x / size.y;
|
||||
|
||||
// Initialize Projection Matrix for Perspective View
|
||||
gluPerspective( 45.0 * g_Parm_3D_Visu.m_Zoom, ratio_HV, 1, 10 );
|
||||
}
|
||||
|
||||
|
||||
// position viewer
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glLoadIdentity();
|
||||
glTranslatef( 0.0F, 0.0F, -( m_ZBottom + m_ZTop) / 2 );
|
||||
|
||||
// clear color and depth buffers
|
||||
glClearColor( g_Parm_3D_Visu.m_BgColor.m_Red,
|
||||
g_Parm_3D_Visu.m_BgColor.m_Green,
|
||||
g_Parm_3D_Visu.m_BgColor.m_Blue, 1 );
|
||||
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||
|
||||
// Setup light sources:
|
||||
SetLights();
|
||||
|
||||
CheckGLError();
|
||||
}
|
||||
|
||||
|
||||
/* Initialize OpenGL light sources. */
|
||||
void EDA_3D_CANVAS::SetLights()
|
||||
{
|
||||
double light;
|
||||
GLfloat light_color[4];
|
||||
|
||||
/* set viewing projection */
|
||||
light_color[3] = 1.0;
|
||||
GLfloat Z_axis_pos[4] = { 0.0, 0.0, 3.0, 0.0 };
|
||||
GLfloat lowZ_axis_pos[4] = { 0.0, 0.0, -3.0, 0.5 };
|
||||
|
||||
/* activate light */
|
||||
light = 1.0;
|
||||
light_color[0] = light_color[1] = light_color[2] = light;
|
||||
glLightfv( GL_LIGHT0, GL_POSITION, Z_axis_pos );
|
||||
glLightfv( GL_LIGHT0, GL_DIFFUSE, light_color );
|
||||
light = 0.3;
|
||||
light_color[0] = light_color[1] = light_color[2] = light;
|
||||
glLightfv( GL_LIGHT1, GL_POSITION, lowZ_axis_pos );
|
||||
glLightfv( GL_LIGHT1, GL_DIFFUSE, light_color );
|
||||
glEnable( GL_LIGHT0 ); // White spot on Z axis
|
||||
glEnable( GL_LIGHT1 ); // White spot on Z axis ( bottom)
|
||||
glEnable( GL_LIGHTING );
|
||||
}
|
||||
|
||||
|
||||
/* Create a Screenshot of the current 3D view.
|
||||
* Output file format is png or jpeg, or image is copied to the clipboard
|
||||
*/
|
||||
void EDA_3D_CANVAS::TakeScreenshot( wxCommandEvent& event )
|
||||
{
|
||||
wxFileName fn( Parent()->GetDefaultFileName() );
|
||||
wxString FullFileName;
|
||||
wxString file_ext, mask;
|
||||
bool fmt_is_jpeg = false;
|
||||
|
||||
if( event.GetId() == ID_MENU_SCREENCOPY_JPEG )
|
||||
fmt_is_jpeg = true;
|
||||
|
||||
if( event.GetId() != ID_TOOL_SCREENCOPY_TOCLIBBOARD )
|
||||
{
|
||||
file_ext = fmt_is_jpeg ? wxT( "jpg" ) : wxT( "png" );
|
||||
mask = wxT( "*." ) + file_ext;
|
||||
FullFileName = Parent()->GetDefaultFileName();
|
||||
fn.SetExt( file_ext );
|
||||
|
||||
FullFileName = EDA_FileSelector( _( "3D Image filename:" ), wxEmptyString,
|
||||
fn.GetFullName(), file_ext, mask, this,
|
||||
wxFD_SAVE, true );
|
||||
|
||||
if( FullFileName.IsEmpty() )
|
||||
return;
|
||||
|
||||
// Be sure the screen area destroyed by the file dialog is redrawn before making
|
||||
// a screen copy.
|
||||
// Without this call, under Linux the screen refresh is made to late.
|
||||
wxYield();
|
||||
}
|
||||
|
||||
struct vieport_params
|
||||
{
|
||||
GLint originx;
|
||||
GLint originy;
|
||||
GLint x;
|
||||
GLint y;
|
||||
} viewport;
|
||||
|
||||
// Build image from the 3D buffer
|
||||
wxWindowUpdateLocker noUpdates( this );
|
||||
glGetIntegerv( GL_VIEWPORT, (GLint*) &viewport );
|
||||
|
||||
unsigned char* pixelbuffer = (unsigned char*) malloc( viewport.x * viewport.y * 3 );
|
||||
unsigned char* alphabuffer = (unsigned char*) malloc( viewport.x * viewport.y );
|
||||
wxImage image( viewport.x, viewport.y );
|
||||
|
||||
glPixelStorei( GL_PACK_ALIGNMENT, 1 );
|
||||
glReadBuffer( GL_BACK_LEFT );
|
||||
glReadPixels( viewport.originx, viewport.originy,
|
||||
viewport.x, viewport.y,
|
||||
GL_RGB, GL_UNSIGNED_BYTE, pixelbuffer );
|
||||
glReadPixels( viewport.originx, viewport.originy,
|
||||
viewport.x, viewport.y,
|
||||
GL_ALPHA, GL_UNSIGNED_BYTE, alphabuffer );
|
||||
|
||||
|
||||
image.SetData( pixelbuffer );
|
||||
image.SetAlpha( alphabuffer );
|
||||
image = image.Mirror( false );
|
||||
wxBitmap bitmap( image );
|
||||
|
||||
if( event.GetId() == ID_TOOL_SCREENCOPY_TOCLIBBOARD )
|
||||
{
|
||||
wxBitmapDataObject* dobjBmp = new wxBitmapDataObject;
|
||||
dobjBmp->SetBitmap( bitmap );
|
||||
|
||||
if( wxTheClipboard->Open() )
|
||||
{
|
||||
if( !wxTheClipboard->SetData( dobjBmp ) )
|
||||
wxMessageBox( _( "Failed to copy image to clipboard" ) );
|
||||
|
||||
wxTheClipboard->Flush(); /* the data in clipboard will stay
|
||||
* available after the
|
||||
* application exits */
|
||||
wxTheClipboard->Close();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wxImage image = bitmap.ConvertToImage();
|
||||
|
||||
if( !image.SaveFile( FullFileName,
|
||||
fmt_is_jpeg ? wxBITMAP_TYPE_JPEG : wxBITMAP_TYPE_PNG ) )
|
||||
wxMessageBox( _( "Can't save file" ) );
|
||||
|
||||
image.Destroy();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2012 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2012 Wayne Stambaugh <stambaughw@verizon.net>
|
||||
* Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_viewer.h
|
||||
*/
|
||||
|
||||
#ifndef _3D_CANVAS_H_
|
||||
#define _3D_CANVAS_H_
|
||||
|
||||
#include <wx/glcanvas.h>
|
||||
|
||||
#ifdef __WXMAC__
|
||||
# ifdef __DARWIN__
|
||||
# include <OpenGL/glu.h>
|
||||
# else
|
||||
# include <glu.h>
|
||||
# endif
|
||||
#else
|
||||
# include <GL/glu.h>
|
||||
#endif
|
||||
|
||||
#include <3d_struct.h>
|
||||
|
||||
class BOARD_DESIGN_SETTINGS;
|
||||
class EDA_3D_FRAME;
|
||||
class S3D_VERTEX;
|
||||
class VIA;
|
||||
class D_PAD;
|
||||
|
||||
// We are using GL lists to store layers and other items
|
||||
// to draw or not
|
||||
// GL_LIST_ID are the GL lists indexes in m_glLists
|
||||
enum GL_LIST_ID
|
||||
{
|
||||
GL_ID_BEGIN = 0,
|
||||
GL_ID_AXIS = GL_ID_BEGIN, // list id for 3D axis
|
||||
GL_ID_GRID, // list id for 3D grid
|
||||
GL_ID_BOARD, // List id for copper layers
|
||||
GL_ID_TECH_LAYERS, // List id for non copper layers (masks...)
|
||||
GL_ID_AUX_LAYERS, // List id for user layers (draw, eco, comment)
|
||||
GL_ID_3DSHAPES_SOLID, // List id for 3D shapes, non transparent entities
|
||||
GL_ID_3DSHAPES_TRANSP, // List id for 3D shapes, transparent entities
|
||||
GL_ID_END
|
||||
};
|
||||
|
||||
class EDA_3D_CANVAS : public wxGLCanvas
|
||||
{
|
||||
private:
|
||||
bool m_init;
|
||||
GLuint m_glLists[GL_ID_END]; // GL lists
|
||||
wxGLContext* m_glRC;
|
||||
wxRealPoint m_draw3dOffset; // offset to draw the 3D mesh.
|
||||
double m_ZBottom; // position of the back layer
|
||||
double m_ZTop; // position of the front layer
|
||||
|
||||
public:
|
||||
EDA_3D_CANVAS( EDA_3D_FRAME* parent, int* attribList = 0 );
|
||||
~EDA_3D_CANVAS();
|
||||
|
||||
EDA_3D_FRAME* Parent() const { return static_cast<EDA_3D_FRAME*>( GetParent() ); }
|
||||
|
||||
BOARD* GetBoard() { return Parent()->GetBoard(); }
|
||||
|
||||
/**
|
||||
* Function ClearLists
|
||||
* Clear the display list.
|
||||
* @param aGlList = the list to clear.
|
||||
* if 0 (default) all lists are cleared
|
||||
*/
|
||||
void ClearLists( GLuint aGlList = 0 );
|
||||
|
||||
// Event functions:
|
||||
void OnPaint( wxPaintEvent& event );
|
||||
void OnEraseBackground( wxEraseEvent& event );
|
||||
void OnChar( wxKeyEvent& event );
|
||||
void OnMouseWheel( wxMouseEvent& event );
|
||||
void OnMouseMove( wxMouseEvent& event );
|
||||
void OnRightClick( wxMouseEvent& event );
|
||||
void OnPopUpMenu( wxCommandEvent& event );
|
||||
void TakeScreenshot( wxCommandEvent& event );
|
||||
void OnEnterWindow( wxMouseEvent& event );
|
||||
|
||||
// Display functions
|
||||
void SetView3D( int keycode );
|
||||
void DisplayStatus();
|
||||
void Redraw();
|
||||
void Render();
|
||||
|
||||
/**
|
||||
* Function CreateDrawGL_List
|
||||
* Prepares the parameters of the OpenGL draw list
|
||||
* creates the OpenGL draw list items (board, grid ...
|
||||
*/
|
||||
void CreateDrawGL_List();
|
||||
void InitGL();
|
||||
void SetLights();
|
||||
void SetOffset(double aPosX, double aPosY)
|
||||
{
|
||||
m_draw3dOffset.x = aPosX;
|
||||
m_draw3dOffset.y = aPosY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function BuildBoard3DView
|
||||
* Called by CreateDrawGL_List()
|
||||
* Populates the OpenGL GL_ID_BOARD draw list with board items only on copper layers.
|
||||
* 3D footprint shapes, tech layers and aux layers are not on this list
|
||||
*/
|
||||
void BuildBoard3DView();
|
||||
|
||||
/**
|
||||
* Function BuildTechLayers3DView
|
||||
* Called by CreateDrawGL_List()
|
||||
* Populates the OpenGL GL_ID_BOARD draw list with items on tech layers
|
||||
*/
|
||||
void BuildTechLayers3DView();
|
||||
|
||||
/**
|
||||
* Function BuildFootprintShape3DList
|
||||
* Called by CreateDrawGL_List()
|
||||
* Fills the OpenGL GL_ID_3DSHAPES_SOLID and GL_ID_3DSHAPES_TRANSP
|
||||
* draw lists with 3D footprint shapes
|
||||
* @param aOpaqueList is the gl list for non transparent items
|
||||
* @param aTransparentList is the gl list for non transparent items,
|
||||
* which need to be drawn after all other items
|
||||
*/
|
||||
void BuildFootprintShape3DList( GLuint aOpaqueList,
|
||||
GLuint aTransparentList);
|
||||
/**
|
||||
* Function BuildBoard3DAuxLayers
|
||||
* Called by CreateDrawGL_List()
|
||||
* Fills the OpenGL GL_ID_AUX_LAYERS draw list
|
||||
* with items on aux layers only
|
||||
*/
|
||||
void BuildBoard3DAuxLayers();
|
||||
|
||||
void Draw3DGrid( double aGriSizeMM );
|
||||
void Draw3DAxis();
|
||||
|
||||
void Draw3DViaHole( const VIA * aVia );
|
||||
void Draw3DPadHole( const D_PAD * aPad );
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
#endif /* _3D_CANVAS_H_ */
|
||||
@@ -1,524 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file cinfo3d_visu.cpp
|
||||
* @brief Handles data related with the board to be visualized
|
||||
*/
|
||||
|
||||
#include "../3d_rendering/ccamera.h"
|
||||
#include "cinfo3d_visu.h"
|
||||
#include <3d_rendering/3d_render_raytracing/shapes2D/cpolygon2d.h>
|
||||
#include <class_board.h>
|
||||
#include <3d_math.h>
|
||||
#include "3d_fastmath.h"
|
||||
#include <geometry/geometry_utils.h>
|
||||
|
||||
/**
|
||||
* Trace mask used to enable or disable the trace output of this class.
|
||||
* The debug output can be turned on by setting the WXTRACE environment variable to
|
||||
* "KI_TRACE_EDA_CINFO3D_VISU". See the wxWidgets documentation on wxLogTrace for
|
||||
* more information.
|
||||
*/
|
||||
const wxChar *CINFO3D_VISU::m_logTrace = wxT( "KI_TRACE_EDA_CINFO3D_VISU" );
|
||||
|
||||
|
||||
CINFO3D_VISU G_null_CINFO3D_VISU;
|
||||
|
||||
|
||||
CINFO3D_VISU::CINFO3D_VISU() :
|
||||
m_currentCamera( m_trackBallCamera ),
|
||||
m_trackBallCamera( RANGE_SCALE_3D )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "CINFO3D_VISU::CINFO3D_VISU" ) );
|
||||
|
||||
m_board = NULL;
|
||||
m_3d_model_manager = NULL;
|
||||
m_3D_grid_type = GRID3D_NONE;
|
||||
m_drawFlags.resize( FL_LAST, false );
|
||||
|
||||
m_render_engine = RENDER_ENGINE_OPENGL_LEGACY;
|
||||
m_material_mode = MATERIAL_MODE_NORMAL;
|
||||
|
||||
m_boardPos = wxPoint();
|
||||
m_boardSize = wxSize();
|
||||
m_boardCenter = SFVEC3F( 0.0f );
|
||||
|
||||
m_boardBoudingBox.Reset();
|
||||
m_board2dBBox3DU.Reset();
|
||||
|
||||
m_layers_container2D.clear();
|
||||
m_layers_holes2D.clear();
|
||||
m_through_holes_inner.Clear();
|
||||
m_through_holes_outer.Clear();
|
||||
|
||||
m_copperLayersCount = -1;
|
||||
m_epoxyThickness3DU = 0.0f;
|
||||
m_copperThickness3DU = 0.0f;
|
||||
m_nonCopperLayerThickness3DU = 0.0f;
|
||||
m_biuTo3Dunits = 1.0;
|
||||
|
||||
m_stats_nr_tracks = 0;
|
||||
m_stats_nr_vias = 0;
|
||||
m_stats_via_med_hole_diameter = 0.0f;
|
||||
m_stats_nr_holes = 0;
|
||||
m_stats_hole_med_diameter = 0.0f;
|
||||
m_stats_track_med_width = 0.0f;
|
||||
|
||||
m_calc_seg_min_factor3DU = 0.0f;
|
||||
m_calc_seg_max_factor3DU = 0.0f;
|
||||
|
||||
|
||||
memset( m_layerZcoordTop, 0, sizeof( m_layerZcoordTop ) );
|
||||
memset( m_layerZcoordBottom, 0, sizeof( m_layerZcoordBottom ) );
|
||||
|
||||
SetFlag( FL_USE_REALISTIC_MODE, true );
|
||||
SetFlag( FL_MODULE_ATTRIBUTES_NORMAL, true );
|
||||
SetFlag( FL_SHOW_BOARD_BODY, true );
|
||||
SetFlag( FL_RENDER_OPENGL_COPPER_THICKNESS, true );
|
||||
SetFlag( FL_MODULE_ATTRIBUTES_NORMAL, true );
|
||||
SetFlag( FL_MODULE_ATTRIBUTES_NORMAL_INSERT, true );
|
||||
SetFlag( FL_MODULE_ATTRIBUTES_VIRTUAL, true );
|
||||
SetFlag( FL_ZONE, true );
|
||||
SetFlag( FL_SILKSCREEN, true );
|
||||
SetFlag( FL_SOLDERMASK, true );
|
||||
|
||||
m_BgColorBot = SFVEC3D( 0.4, 0.4, 0.5 );
|
||||
m_BgColorTop = SFVEC3D( 0.8, 0.8, 0.9 );
|
||||
m_BoardBodyColor = SFVEC3D( 0.4, 0.4, 0.5 );
|
||||
m_SolderMaskColor = SFVEC3D( 0.1, 0.2, 0.1 );
|
||||
m_SolderPasteColor = SFVEC3D( 0.4, 0.4, 0.4 );
|
||||
m_SilkScreenColor = SFVEC3D( 0.9, 0.9, 0.9 );
|
||||
m_CopperColor = SFVEC3D( 0.75, 0.61, 0.23 );
|
||||
}
|
||||
|
||||
|
||||
CINFO3D_VISU::~CINFO3D_VISU()
|
||||
{
|
||||
destroyLayers();
|
||||
}
|
||||
|
||||
|
||||
bool CINFO3D_VISU::Is3DLayerEnabled( PCB_LAYER_ID aLayer ) const
|
||||
{
|
||||
wxASSERT( aLayer < PCB_LAYER_ID_COUNT );
|
||||
|
||||
DISPLAY3D_FLG flg;
|
||||
|
||||
// see if layer needs to be shown
|
||||
// check the flags
|
||||
switch( aLayer )
|
||||
{
|
||||
case B_Adhes:
|
||||
case F_Adhes:
|
||||
flg = FL_ADHESIVE;
|
||||
break;
|
||||
|
||||
case B_Paste:
|
||||
case F_Paste:
|
||||
flg = FL_SOLDERPASTE;
|
||||
break;
|
||||
|
||||
case B_SilkS:
|
||||
case F_SilkS:
|
||||
flg = FL_SILKSCREEN;
|
||||
break;
|
||||
|
||||
case B_Mask:
|
||||
case F_Mask:
|
||||
flg = FL_SOLDERMASK;
|
||||
break;
|
||||
|
||||
case Dwgs_User:
|
||||
case Cmts_User:
|
||||
if( GetFlag( FL_USE_REALISTIC_MODE ) )
|
||||
return false;
|
||||
|
||||
flg = FL_COMMENTS;
|
||||
break;
|
||||
|
||||
case Eco1_User:
|
||||
case Eco2_User:
|
||||
if( GetFlag( FL_USE_REALISTIC_MODE ) )
|
||||
return false;
|
||||
|
||||
flg = FL_ECO;
|
||||
break;
|
||||
|
||||
case Edge_Cuts:
|
||||
if( GetFlag( FL_SHOW_BOARD_BODY ) || GetFlag( FL_USE_REALISTIC_MODE ) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
break;
|
||||
|
||||
case Margin:
|
||||
if( GetFlag( FL_USE_REALISTIC_MODE ) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
break;
|
||||
|
||||
case B_Cu:
|
||||
case F_Cu:
|
||||
return m_board->GetDesignSettings().IsLayerVisible( aLayer ) ||
|
||||
GetFlag( FL_USE_REALISTIC_MODE );
|
||||
break;
|
||||
|
||||
default:
|
||||
// the layer is an internal copper layer, used the visibility
|
||||
if( GetFlag( FL_SHOW_BOARD_BODY ) &&
|
||||
(m_render_engine == RENDER_ENGINE_OPENGL_LEGACY) )
|
||||
{
|
||||
// Do not render internal layers if it is overlap with the board
|
||||
// (on OpenGL render)
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_board->GetDesignSettings().IsLayerVisible( aLayer );
|
||||
}
|
||||
|
||||
// The layer has a flag, return the flag
|
||||
return GetFlag( flg );
|
||||
}
|
||||
|
||||
|
||||
bool CINFO3D_VISU::GetFlag( DISPLAY3D_FLG aFlag ) const
|
||||
{
|
||||
wxASSERT( aFlag < FL_LAST );
|
||||
|
||||
return m_drawFlags[aFlag];
|
||||
}
|
||||
|
||||
|
||||
void CINFO3D_VISU::SetFlag( DISPLAY3D_FLG aFlag, bool aState )
|
||||
{
|
||||
wxASSERT( aFlag < FL_LAST );
|
||||
|
||||
m_drawFlags[aFlag] = aState;
|
||||
}
|
||||
|
||||
bool CINFO3D_VISU::ShouldModuleBeDisplayed( MODULE_ATTR_T aModuleAttributs ) const
|
||||
{
|
||||
if( ( ( aModuleAttributs == MOD_DEFAULT ) &&
|
||||
GetFlag( FL_MODULE_ATTRIBUTES_NORMAL ) ) ||
|
||||
( ( ( aModuleAttributs & MOD_CMS) == MOD_CMS ) &&
|
||||
GetFlag( FL_MODULE_ATTRIBUTES_NORMAL_INSERT ) ) ||
|
||||
( ( ( aModuleAttributs & MOD_VIRTUAL) == MOD_VIRTUAL ) &&
|
||||
GetFlag( FL_MODULE_ATTRIBUTES_VIRTUAL ) ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// !TODO: define the actual copper thickness by user
|
||||
#define COPPER_THICKNESS KiROUND( 0.035 * IU_PER_MM ) // for 35 um
|
||||
#define TECH_LAYER_THICKNESS KiROUND( 0.04 * IU_PER_MM )
|
||||
|
||||
int CINFO3D_VISU::GetCopperThicknessBIU() const
|
||||
{
|
||||
return COPPER_THICKNESS;
|
||||
}
|
||||
|
||||
unsigned int CINFO3D_VISU::GetNrSegmentsCircle( float aDiameter3DU ) const
|
||||
{
|
||||
wxASSERT( aDiameter3DU > 0.0f );
|
||||
|
||||
return GetNrSegmentsCircle( (int)( aDiameter3DU / m_biuTo3Dunits ) );
|
||||
}
|
||||
|
||||
|
||||
unsigned int CINFO3D_VISU::GetNrSegmentsCircle( int aDiameterBIU ) const
|
||||
{
|
||||
wxASSERT( aDiameterBIU > 0 );
|
||||
|
||||
// Require at least 3 segments for a circle
|
||||
return std::max( GetArcToSegmentCount( aDiameterBIU / 2, ARC_HIGH_DEF, 360.0 ), 3 );
|
||||
}
|
||||
|
||||
|
||||
double CINFO3D_VISU::GetCircleCorrectionFactor( int aNrSides ) const
|
||||
{
|
||||
wxASSERT( aNrSides >= 3 );
|
||||
|
||||
return GetCircletoPolyCorrectionFactor( aNrSides );
|
||||
}
|
||||
|
||||
|
||||
void CINFO3D_VISU::InitSettings( REPORTER *aStatusTextReporter )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "CINFO3D_VISU::InitSettings" ) );
|
||||
|
||||
// Calculates the board bounding box
|
||||
// First, use only the board outlines
|
||||
EDA_RECT bbbox = m_board->ComputeBoundingBox( true );
|
||||
|
||||
// If no outlines, use the board with items
|
||||
if( ( bbbox.GetWidth() == 0 ) && ( bbbox.GetHeight() == 0 ) )
|
||||
bbbox = m_board->ComputeBoundingBox( false );
|
||||
|
||||
// Gives a non null size to avoid issues in zoom / scale calculations
|
||||
if( ( bbbox.GetWidth() == 0 ) && ( bbbox.GetHeight() == 0 ) )
|
||||
bbbox.Inflate( Millimeter2iu( 10 ) );
|
||||
|
||||
m_boardSize = bbbox.GetSize();
|
||||
m_boardPos = bbbox.Centre();
|
||||
|
||||
wxASSERT( (m_boardSize.x > 0) && (m_boardSize.y > 0) );
|
||||
|
||||
m_boardPos.y = -m_boardPos.y; // The y coord is inverted in 3D viewer
|
||||
|
||||
m_copperLayersCount = m_board->GetCopperLayerCount();
|
||||
|
||||
// Ensure the board has 2 sides for 3D views, because it is hard to find
|
||||
// a *really* single side board in the true life...
|
||||
if( m_copperLayersCount < 2 )
|
||||
m_copperLayersCount = 2;
|
||||
|
||||
// Calculate the convertion to apply to all positions.
|
||||
m_biuTo3Dunits = RANGE_SCALE_3D / std::max( m_boardSize.x, m_boardSize.y );
|
||||
|
||||
m_epoxyThickness3DU = m_board->GetDesignSettings().GetBoardThickness() *
|
||||
m_biuTo3Dunits;
|
||||
|
||||
// !TODO: use value defined by user (currently use default values by ctor
|
||||
m_copperThickness3DU = COPPER_THICKNESS * m_biuTo3Dunits;
|
||||
m_nonCopperLayerThickness3DU = TECH_LAYER_THICKNESS * m_biuTo3Dunits;
|
||||
|
||||
// Init Z position of each layer
|
||||
// calculate z position for each copper layer
|
||||
// Zstart = -m_epoxyThickness / 2.0 is the z position of the back (bottom layer) (layer id = 31)
|
||||
// Zstart = +m_epoxyThickness / 2.0 is the z position of the front (top layer) (layer id = 0)
|
||||
// all unused copper layer z position are set to 0
|
||||
|
||||
// ____==__________==________==______ <- Bottom = +m_epoxyThickness / 2.0,
|
||||
// | | Top = Bottom + m_copperThickness
|
||||
// |__________________________________|
|
||||
// == == == == <- Bottom = -m_epoxyThickness / 2.0,
|
||||
// Top = Bottom - m_copperThickness
|
||||
|
||||
unsigned int layer;
|
||||
|
||||
for( layer = 0; layer < m_copperLayersCount; ++layer )
|
||||
{
|
||||
m_layerZcoordBottom[layer] = m_epoxyThickness3DU / 2.0f -
|
||||
(m_epoxyThickness3DU * layer / (m_copperLayersCount - 1) );
|
||||
|
||||
if( layer < (m_copperLayersCount / 2) )
|
||||
m_layerZcoordTop[layer] = m_layerZcoordBottom[layer] + m_copperThickness3DU;
|
||||
else
|
||||
m_layerZcoordTop[layer] = m_layerZcoordBottom[layer] - m_copperThickness3DU;
|
||||
}
|
||||
|
||||
#define layerThicknessMargin 1.1
|
||||
const float zpos_offset = m_nonCopperLayerThickness3DU * layerThicknessMargin;
|
||||
|
||||
// Fill remaining unused copper layers and back layer zpos
|
||||
// with -m_epoxyThickness / 2.0
|
||||
for( ; layer < MAX_CU_LAYERS; layer++ )
|
||||
{
|
||||
m_layerZcoordBottom[layer] = -(m_epoxyThickness3DU / 2.0f);
|
||||
m_layerZcoordTop[layer] = -(m_epoxyThickness3DU / 2.0f) - m_copperThickness3DU;
|
||||
}
|
||||
|
||||
// This is the top of the copper layer thickness.
|
||||
const float zpos_copperTop_back = m_layerZcoordTop[B_Cu];
|
||||
const float zpos_copperTop_front = m_layerZcoordTop[F_Cu];
|
||||
|
||||
// calculate z position for each non copper layer
|
||||
// Solder mask and Solder paste have the same Z position
|
||||
for( int layer_id = MAX_CU_LAYERS; layer_id < PCB_LAYER_ID_COUNT; ++layer_id )
|
||||
{
|
||||
float zposTop;
|
||||
float zposBottom;
|
||||
|
||||
switch( layer_id )
|
||||
{
|
||||
case B_Adhes:
|
||||
zposBottom = zpos_copperTop_back - 2.0f * zpos_offset;
|
||||
zposTop = zposBottom - m_nonCopperLayerThickness3DU;
|
||||
break;
|
||||
|
||||
case F_Adhes:
|
||||
zposBottom = zpos_copperTop_front + 2.0f * zpos_offset;
|
||||
zposTop = zposBottom + m_nonCopperLayerThickness3DU;
|
||||
break;
|
||||
|
||||
case B_Mask:
|
||||
case B_Paste:
|
||||
zposBottom = zpos_copperTop_back;
|
||||
zposTop = zpos_copperTop_back - m_nonCopperLayerThickness3DU;
|
||||
break;
|
||||
|
||||
case F_Mask:
|
||||
case F_Paste:
|
||||
zposTop = zpos_copperTop_front + m_nonCopperLayerThickness3DU;
|
||||
zposBottom = zpos_copperTop_front;
|
||||
break;
|
||||
|
||||
case B_SilkS:
|
||||
zposBottom = zpos_copperTop_back - 1.0f * zpos_offset;
|
||||
zposTop = zposBottom - m_nonCopperLayerThickness3DU;
|
||||
break;
|
||||
|
||||
case F_SilkS:
|
||||
zposBottom = zpos_copperTop_front + 1.0f * zpos_offset;
|
||||
zposTop = zposBottom + m_nonCopperLayerThickness3DU;
|
||||
break;
|
||||
|
||||
// !TODO: review
|
||||
default:
|
||||
zposTop = zpos_copperTop_front + (layer_id - MAX_CU_LAYERS + 3.0f) * zpos_offset;
|
||||
zposBottom = zposTop - m_nonCopperLayerThickness3DU;
|
||||
break;
|
||||
}
|
||||
|
||||
m_layerZcoordTop[layer_id] = zposTop;
|
||||
m_layerZcoordBottom[layer_id] = zposBottom;
|
||||
}
|
||||
|
||||
m_boardCenter = SFVEC3F( m_boardPos.x * m_biuTo3Dunits,
|
||||
m_boardPos.y * m_biuTo3Dunits,
|
||||
0.0f );
|
||||
|
||||
SFVEC3F boardSize = SFVEC3F( m_boardSize.x * m_biuTo3Dunits,
|
||||
m_boardSize.y * m_biuTo3Dunits,
|
||||
0.0f );
|
||||
boardSize /= 2.0f;
|
||||
|
||||
SFVEC3F boardMin = (m_boardCenter - boardSize);
|
||||
SFVEC3F boardMax = (m_boardCenter + boardSize);
|
||||
|
||||
boardMin.z = m_layerZcoordTop[B_Adhes];
|
||||
boardMax.z = m_layerZcoordTop[F_Adhes];
|
||||
|
||||
m_boardBoudingBox = CBBOX( boardMin, boardMax );
|
||||
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
unsigned stats_startCreateBoardPolyTime = GetRunningMicroSecs();
|
||||
#endif
|
||||
|
||||
if( aStatusTextReporter )
|
||||
aStatusTextReporter->Report( _( "Build board body" ) );
|
||||
|
||||
createBoardPolygon();
|
||||
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
unsigned stats_stopCreateBoardPolyTime = GetRunningMicroSecs();
|
||||
unsigned stats_startCreateLayersTime = stats_stopCreateBoardPolyTime;
|
||||
#endif
|
||||
|
||||
if( aStatusTextReporter )
|
||||
aStatusTextReporter->Report( _( "Create layers" ) );
|
||||
|
||||
createLayers( aStatusTextReporter );
|
||||
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
unsigned stats_stopCreateLayersTime = GetRunningMicroSecs();
|
||||
|
||||
printf( "CINFO3D_VISU::InitSettings times\n" );
|
||||
printf( " CreateBoardPoly: %.3f ms\n",
|
||||
(float)( stats_stopCreateBoardPolyTime - stats_startCreateBoardPolyTime ) / 1e3 );
|
||||
printf( " CreateLayers and holes: %.3f ms\n",
|
||||
(float)( stats_stopCreateLayersTime - stats_startCreateLayersTime ) / 1e3 );
|
||||
printf( "\n" );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void CINFO3D_VISU::createBoardPolygon()
|
||||
{
|
||||
m_board_poly.RemoveAllContours();
|
||||
|
||||
wxString errmsg;
|
||||
|
||||
if( !m_board->GetBoardPolygonOutlines( m_board_poly, /*allLayerHoles,*/ &errmsg ) )
|
||||
{
|
||||
errmsg.append( wxT( "\n\n" ) );
|
||||
errmsg.append( _( "Cannot determine the board outline." ) );
|
||||
wxLogMessage( errmsg );
|
||||
}
|
||||
|
||||
Polygon_Calc_BBox_3DU( m_board_poly, m_board2dBBox3DU, m_biuTo3Dunits );
|
||||
}
|
||||
|
||||
|
||||
float CINFO3D_VISU::GetModulesZcoord3DIU( bool aIsFlipped ) const
|
||||
{
|
||||
if( aIsFlipped )
|
||||
{
|
||||
if( GetFlag( FL_SOLDERPASTE ) )
|
||||
return m_layerZcoordBottom[B_SilkS];
|
||||
else
|
||||
return m_layerZcoordBottom[B_Paste];
|
||||
}
|
||||
else
|
||||
{
|
||||
if( GetFlag( FL_SOLDERPASTE ) )
|
||||
return m_layerZcoordTop[F_SilkS];
|
||||
else
|
||||
return m_layerZcoordTop[F_Paste];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CINFO3D_VISU::CameraSetType( CAMERA_TYPE aCameraType )
|
||||
{
|
||||
switch( aCameraType )
|
||||
{
|
||||
case CAMERA_TRACKBALL:
|
||||
m_currentCamera = m_trackBallCamera;
|
||||
break;
|
||||
|
||||
default:
|
||||
wxLogMessage( wxT( "CINFO3D_VISU::CameraSetType() error: unknown camera type %d" ),
|
||||
(int)aCameraType );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SFVEC3F CINFO3D_VISU::GetLayerColor( PCB_LAYER_ID aLayerId ) const
|
||||
{
|
||||
wxASSERT( aLayerId < PCB_LAYER_ID_COUNT );
|
||||
|
||||
const COLOR4D color = m_board->Colors().GetLayerColor( aLayerId );
|
||||
|
||||
return SFVEC3F( color.r, color.g, color.b );
|
||||
}
|
||||
|
||||
|
||||
SFVEC3F CINFO3D_VISU::GetItemColor( int aItemId ) const
|
||||
{
|
||||
return GetColor( m_board->Colors().GetItemColor( aItemId ) );
|
||||
}
|
||||
|
||||
|
||||
SFVEC3F CINFO3D_VISU::GetColor( COLOR4D aColor ) const
|
||||
{
|
||||
return SFVEC3F( aColor.r, aColor.g, aColor.b );
|
||||
}
|
||||
@@ -1,680 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file cinfo3d_visu.h
|
||||
* @brief Handles data related with the board to be visualized
|
||||
*/
|
||||
|
||||
#ifndef CINFO3D_VISU_H
|
||||
#define CINFO3D_VISU_H
|
||||
|
||||
#include <vector>
|
||||
#include "../3d_rendering/3d_render_raytracing/accelerators/ccontainer2d.h"
|
||||
#include "../3d_rendering/3d_render_raytracing/accelerators/ccontainer.h"
|
||||
#include "../3d_rendering/3d_render_raytracing/shapes3D/cbbox.h"
|
||||
#include "../3d_rendering/ccamera.h"
|
||||
#include "../3d_rendering/ctrack_ball.h"
|
||||
#include "../3d_enums.h"
|
||||
#include "../3d_cache/3d_cache.h"
|
||||
|
||||
#include <layers_id_colors_and_visibility.h>
|
||||
#include <class_pad.h>
|
||||
#include <class_track.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <pcb_base_frame.h>
|
||||
#include <class_pcb_text.h>
|
||||
#include <class_drawsegment.h>
|
||||
#include <class_dimension.h>
|
||||
#include <class_zone.h>
|
||||
#include <class_module.h>
|
||||
#include <reporter.h>
|
||||
|
||||
/// A type that stores a container of 2d objects for each layer id
|
||||
typedef std::map< PCB_LAYER_ID, CBVHCONTAINER2D *> MAP_CONTAINER_2D;
|
||||
|
||||
/// A type that stores polysets for each layer id
|
||||
typedef std::map< PCB_LAYER_ID, SHAPE_POLY_SET *> MAP_POLY;
|
||||
|
||||
/// This defines the range that all coord will have to be rendered.
|
||||
/// It will use this value to convert to a normalized value between
|
||||
/// -(RANGE_SCALE_3D/2) .. +(RANGE_SCALE_3D/2)
|
||||
#define RANGE_SCALE_3D 8.0f
|
||||
|
||||
|
||||
/**
|
||||
* Class CINFO3D_VISU
|
||||
* Helper class to handle information needed to display 3D board
|
||||
*/
|
||||
class CINFO3D_VISU
|
||||
{
|
||||
public:
|
||||
|
||||
CINFO3D_VISU();
|
||||
|
||||
~CINFO3D_VISU();
|
||||
|
||||
/**
|
||||
* @brief Set3DCacheManager - Update the Cache manager pointer
|
||||
* @param aCachePointer: the pointer to the 3d cache manager
|
||||
*/
|
||||
void Set3DCacheManager( S3D_CACHE *aCachePointer ) { m_3d_model_manager = aCachePointer; }
|
||||
|
||||
/**
|
||||
* @brief Get3DCacheManager - Return the 3d cache manager pointer
|
||||
* @return
|
||||
*/
|
||||
S3D_CACHE *Get3DCacheManager( ) const { return m_3d_model_manager; }
|
||||
|
||||
/**
|
||||
* @brief GetFlag - get a configuration status of a flag
|
||||
* @param aFlag: the flag to get the status
|
||||
* @return true if flag is set, false if not
|
||||
*/
|
||||
bool GetFlag( DISPLAY3D_FLG aFlag ) const ;
|
||||
|
||||
/**
|
||||
* @brief SetFlag - set the status of a flag
|
||||
* @param aFlag: the flag to get the status
|
||||
* @param aState: status to set
|
||||
*/
|
||||
void SetFlag( DISPLAY3D_FLG aFlag, bool aState );
|
||||
|
||||
/**
|
||||
* @brief Is3DLayerEnabled - Check if a layer is enabled
|
||||
* @param aLayer: layer ID to get status
|
||||
* @return true if layer should be displayed, false if not
|
||||
*/
|
||||
bool Is3DLayerEnabled( PCB_LAYER_ID aLayer ) const;
|
||||
|
||||
/**
|
||||
* @brief ShouldModuleBeDisplayed - Test if module should be displayed in
|
||||
* relation to attributs and the flags
|
||||
* @return true if module should be displayed, false if not
|
||||
*/
|
||||
bool ShouldModuleBeDisplayed( MODULE_ATTR_T aModuleAttributs ) const;
|
||||
|
||||
/**
|
||||
* @brief SetBoard - Set current board to be rendered
|
||||
* @param aBoard: board to process
|
||||
*/
|
||||
void SetBoard( BOARD *aBoard ) { m_board = aBoard; }
|
||||
|
||||
/**
|
||||
* @brief GetBoard - Get current board to be rendered
|
||||
* @return BOARD pointer
|
||||
*/
|
||||
const BOARD *GetBoard() const { return m_board; }
|
||||
|
||||
/**
|
||||
* @brief InitSettings - Function to be called by the render when it need to
|
||||
* reload the settings for the board.
|
||||
* @param aStatusTextReporter: the pointer for the status reporter
|
||||
*/
|
||||
void InitSettings( REPORTER *aStatusTextReporter );
|
||||
|
||||
/**
|
||||
* @brief BiuTo3Dunits - Board integer units To 3D units
|
||||
* @return the conversion factor to transform a position from the board to 3d units
|
||||
*/
|
||||
double BiuTo3Dunits() const { return m_biuTo3Dunits; }
|
||||
|
||||
/**
|
||||
* @brief GetBBox3DU - Get the bbox of the pcb board
|
||||
* @return the board bbox in 3d units
|
||||
*/
|
||||
const CBBOX &GetBBox3DU() const { return m_boardBoudingBox; }
|
||||
|
||||
/**
|
||||
* @brief GetEpoxyThickness3DU - Get the current epoxy thickness
|
||||
* @return thickness in 3d unities
|
||||
*/
|
||||
float GetEpoxyThickness3DU() const { return m_epoxyThickness3DU; }
|
||||
|
||||
/**
|
||||
* @brief GetNonCopperLayerThickness3DU - Get the current non copper layers thickness
|
||||
* @return thickness in 3d unities of non copperlayers
|
||||
*/
|
||||
float GetNonCopperLayerThickness3DU() const { return m_nonCopperLayerThickness3DU; }
|
||||
|
||||
/**
|
||||
* @brief GetCopperThickness3DU - Get the current copper layer thickness
|
||||
* @return thickness in 3d unities of copperlayers
|
||||
*/
|
||||
float GetCopperThickness3DU() const { return m_copperThickness3DU; }
|
||||
|
||||
/**
|
||||
* @brief GetCopperThicknessBIU - Get the current copper layer thickness
|
||||
* @return thickness in board unities
|
||||
*/
|
||||
int GetCopperThicknessBIU() const;
|
||||
|
||||
/**
|
||||
* @brief GetBoardSizeBIU - Get the board size
|
||||
* @return size in BIU unities
|
||||
*/
|
||||
wxSize GetBoardSizeBIU() const { return m_boardSize; }
|
||||
|
||||
/**
|
||||
* @brief GetBoardPosBIU - Get the board size
|
||||
* @return size in BIU unities
|
||||
*/
|
||||
wxPoint GetBoardPosBIU() const { return m_boardPos; }
|
||||
|
||||
/**
|
||||
* @brief GetBoardCenter - the board center position in 3d units
|
||||
* @return board center vector position in 3d units
|
||||
*/
|
||||
const SFVEC3F &GetBoardCenter3DU() const { return m_boardCenter; }
|
||||
|
||||
/**
|
||||
* @brief GetModulesZcoord3DIU - Get the position of the module in 3d integer units
|
||||
* considering if it is flipped or not.
|
||||
* @param aIsFlipped: true for use in modules on Front (top) layer, false
|
||||
* if module is on back (bottom) layer
|
||||
* @return the Z position of 3D shapes, in 3D integer units
|
||||
*/
|
||||
float GetModulesZcoord3DIU( bool aIsFlipped ) const ;
|
||||
|
||||
/**
|
||||
* @brief CameraSetType - Set the camera type to use
|
||||
* @param aCameraType: camera type to use in this canvas
|
||||
*/
|
||||
void CameraSetType( CAMERA_TYPE aCameraType );
|
||||
|
||||
/**
|
||||
* @brief CameraGet - get current camera in use
|
||||
* @return a camera
|
||||
*/
|
||||
CCAMERA &CameraGet() const { return m_currentCamera; }
|
||||
|
||||
/**
|
||||
* @brief GridGet - get the current grid
|
||||
* @return space type of the grid
|
||||
*/
|
||||
GRID3D_TYPE GridGet() const { return m_3D_grid_type; }
|
||||
|
||||
/**
|
||||
* @brief GridSet - set the current grid
|
||||
* @param aGridType = the type space of the grid
|
||||
*/
|
||||
void GridSet( GRID3D_TYPE aGridType ) { m_3D_grid_type = aGridType; }
|
||||
|
||||
/**
|
||||
* @brief RenderEngineSet
|
||||
* @param aRenderEngine = the render engine mode selected
|
||||
*/
|
||||
void RenderEngineSet( RENDER_ENGINE aRenderEngine ) { m_render_engine = aRenderEngine; }
|
||||
|
||||
/**
|
||||
* @brief RenderEngineGet
|
||||
* @return render engine on use
|
||||
*/
|
||||
RENDER_ENGINE RenderEngineGet() const { return m_render_engine; }
|
||||
|
||||
/**
|
||||
* @brief MaterialModeSet
|
||||
* @param aMaterialMode = the render material mode
|
||||
*/
|
||||
void MaterialModeSet( MATERIAL_MODE aMaterialMode ) { m_material_mode = aMaterialMode; }
|
||||
|
||||
/**
|
||||
* @brief MaterialModeGet
|
||||
* @return material rendering mode
|
||||
*/
|
||||
MATERIAL_MODE MaterialModeGet() const { return m_material_mode; }
|
||||
|
||||
/**
|
||||
* @brief GetBoardPoly - Get the current polygon of the epoxy board
|
||||
* @return the shape polygon
|
||||
*/
|
||||
const SHAPE_POLY_SET &GetBoardPoly() const { return m_board_poly; }
|
||||
|
||||
/**
|
||||
* @brief GetLayerColor - get the technical color of a layer
|
||||
* @param aLayerId: the layer to get the color information
|
||||
* @return the color in SFVEC3F format
|
||||
*/
|
||||
SFVEC3F GetLayerColor( PCB_LAYER_ID aLayerId ) const;
|
||||
|
||||
/**
|
||||
* @brief GetItemColor - get the technical color of a layer
|
||||
* @param aItemId: the item id to get the color information
|
||||
* @return the color in SFVEC3F format
|
||||
*/
|
||||
SFVEC3F GetItemColor( int aItemId ) const;
|
||||
|
||||
/**
|
||||
* @brief GetColor
|
||||
* @param aColor: the color mapped
|
||||
* @return the color in SFVEC3F format
|
||||
*/
|
||||
SFVEC3F GetColor( COLOR4D aColor ) const;
|
||||
|
||||
/**
|
||||
* @brief GetLayerTopZpos3DU - Get the top z position
|
||||
* @param aLayerId: layer id
|
||||
* @return position in 3D unities
|
||||
*/
|
||||
float GetLayerTopZpos3DU( PCB_LAYER_ID aLayerId ) const { return m_layerZcoordTop[aLayerId]; }
|
||||
|
||||
/**
|
||||
* @brief GetLayerBottomZpos3DU - Get the bottom z position
|
||||
* @param aLayerId: layer id
|
||||
* @return position in 3D unities
|
||||
*/
|
||||
float GetLayerBottomZpos3DU( PCB_LAYER_ID aLayerId ) const { return m_layerZcoordBottom[aLayerId]; }
|
||||
|
||||
/**
|
||||
* @brief GetMapLayers - Get the map of container that have the objects per layer
|
||||
* @return the map containers of this board
|
||||
*/
|
||||
const MAP_CONTAINER_2D &GetMapLayers() const { return m_layers_container2D; }
|
||||
|
||||
/**
|
||||
* @brief GetMapLayersHoles -Get the map of container that have the holes per layer
|
||||
* @return the map containers of holes from this board
|
||||
*/
|
||||
const MAP_CONTAINER_2D &GetMapLayersHoles() const { return m_layers_holes2D; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Outer - Get the inflated ThroughHole container
|
||||
* @return a container with holes
|
||||
*/
|
||||
const CBVHCONTAINER2D &GetThroughHole_Outer() const { return m_through_holes_outer; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Outer_poly -
|
||||
* @return
|
||||
*/
|
||||
const SHAPE_POLY_SET &GetThroughHole_Outer_poly() const { return m_through_outer_holes_poly; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Outer_poly_NPTH -
|
||||
* @return
|
||||
*/
|
||||
const SHAPE_POLY_SET &GetThroughHole_Outer_poly_NPTH() const {
|
||||
return m_through_outer_holes_poly_NPTH; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Vias_Outer -
|
||||
* @return a container with via THT holes only
|
||||
*/
|
||||
const CBVHCONTAINER2D &GetThroughHole_Vias_Outer() const { return m_through_holes_vias_outer; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Vias_Inner -
|
||||
* @return a container with via THT holes only
|
||||
*/
|
||||
const CBVHCONTAINER2D &GetThroughHole_Vias_Inner() const { return m_through_holes_vias_inner; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Vias_Outer_poly -
|
||||
* @return
|
||||
*/
|
||||
const SHAPE_POLY_SET &GetThroughHole_Vias_Outer_poly() const {
|
||||
return m_through_outer_holes_vias_poly; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Vias_Inner_poly -
|
||||
* @return
|
||||
*/
|
||||
const SHAPE_POLY_SET &GetThroughHole_Vias_Inner_poly() const {
|
||||
return m_through_inner_holes_vias_poly; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Inner - Get the ThroughHole container
|
||||
* @return a container with holes
|
||||
*/
|
||||
const CBVHCONTAINER2D &GetThroughHole_Inner() const { return m_through_holes_inner; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Inner_poly -
|
||||
* @return
|
||||
*/
|
||||
const SHAPE_POLY_SET &GetThroughHole_Inner_poly() const { return m_through_inner_holes_poly; }
|
||||
|
||||
/**
|
||||
* @brief GetStats_Nr_Vias - Get statistics of the nr of vias
|
||||
* @return number of vias
|
||||
*/
|
||||
unsigned int GetStats_Nr_Vias() const { return m_stats_nr_vias; }
|
||||
|
||||
/**
|
||||
* @brief GetStats_Nr_Holes - Get statistics of the nr of holes
|
||||
* @return number of holes
|
||||
*/
|
||||
unsigned int GetStats_Nr_Holes() const { return m_stats_nr_holes; }
|
||||
|
||||
/**
|
||||
* @brief GetStats_Med_Via_Hole_Diameter3DU - Average diameter of the via holes
|
||||
* @return dimension in 3D units
|
||||
*/
|
||||
float GetStats_Med_Via_Hole_Diameter3DU() const { return m_stats_via_med_hole_diameter; }
|
||||
|
||||
/**
|
||||
* @brief GetStats_Med_Hole_Diameter3DU - Average diameter of holes
|
||||
* @return dimension in 3D units
|
||||
*/
|
||||
float GetStats_Med_Hole_Diameter3DU() const { return m_stats_hole_med_diameter; }
|
||||
|
||||
/**
|
||||
* @brief GetStats_Med_Track_Width - Average width of the tracks
|
||||
* @return dimensions in 3D units
|
||||
*/
|
||||
float GetStats_Med_Track_Width() const { return m_stats_track_med_width; }
|
||||
|
||||
/**
|
||||
* @brief GetNrSegmentsCircle
|
||||
* @param aDiameter3DU: diameter in 3DU
|
||||
* @return number of sides that should be used in that circle
|
||||
*/
|
||||
unsigned int GetNrSegmentsCircle( float aDiameter3DU ) const;
|
||||
|
||||
/**
|
||||
* @brief GetNrSegmentsCircle
|
||||
* @param aDiameterBIU: diameter in board internal units
|
||||
* @return number of sides that should be used in that circle
|
||||
*/
|
||||
unsigned int GetNrSegmentsCircle( int aDiameterBIU ) const;
|
||||
|
||||
/**
|
||||
* @brief GetCircleCorrectionFactor - computes a angle correction
|
||||
* factor used when creating circles
|
||||
* @param aNrSides: the number of segments sides of the circle
|
||||
* @return a factor to apply to contour creation
|
||||
*/
|
||||
double GetCircleCorrectionFactor( int aNrSides ) const;
|
||||
|
||||
/**
|
||||
* @brief GetPolyMap - Get maps of polygons's layers
|
||||
* @return the map with polygons's layers
|
||||
*/
|
||||
const MAP_POLY &GetPolyMap() const { return m_layers_poly; }
|
||||
|
||||
const MAP_POLY &GetPolyMapHoles_Inner() const { return m_layers_inner_holes_poly; }
|
||||
|
||||
const MAP_POLY &GetPolyMapHoles_Outer() const { return m_layers_outer_holes_poly; }
|
||||
|
||||
private:
|
||||
void createBoardPolygon();
|
||||
void createLayers( REPORTER *aStatusTextReporter );
|
||||
void destroyLayers();
|
||||
|
||||
// Helper functions to create the board
|
||||
COBJECT2D *createNewTrack( const TRACK* aTrack , int aClearanceValue ) const;
|
||||
|
||||
void createNewPad( const D_PAD* aPad,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
wxSize aInflateValue ) const;
|
||||
|
||||
void createNewPadWithClearance( const D_PAD *aPad,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
wxSize aClearanceValue ) const;
|
||||
|
||||
COBJECT2D *createNewPadDrill( const D_PAD* aPad, int aInflateValue );
|
||||
|
||||
void AddPadsShapesWithClearanceToContainer( const MODULE *aModule,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId,
|
||||
int aInflateValue,
|
||||
bool aSkipNPTHPadsWihNoCopper );
|
||||
|
||||
void AddGraphicsShapesWithClearanceToContainer( const MODULE *aModule,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId,
|
||||
int aInflateValue );
|
||||
|
||||
void AddShapeWithClearanceToContainer( const TEXTE_PCB *aTextPCB,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId,
|
||||
int aClearanceValue );
|
||||
|
||||
void AddShapeWithClearanceToContainer( const DRAWSEGMENT *aDrawSegment,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId,
|
||||
int aClearanceValue );
|
||||
|
||||
void AddShapeWithClearanceToContainer( const DIMENSION *aDimension,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId,
|
||||
int aClearanceValue );
|
||||
|
||||
void AddSolidAreasShapesToContainer( const ZONE_CONTAINER *aZoneContainer,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId );
|
||||
|
||||
void TransformArcToSegments( const wxPoint &aCentre,
|
||||
const wxPoint &aStart,
|
||||
double aArcAngle,
|
||||
int aCircleToSegmentsCount,
|
||||
int aWidth,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
const BOARD_ITEM &aBoardItem );
|
||||
|
||||
void buildPadShapeThickOutlineAsSegments( const D_PAD *aPad,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
int aWidth );
|
||||
|
||||
// Helper functions to create poly contours
|
||||
void buildPadShapeThickOutlineAsPolygon( const D_PAD *aPad,
|
||||
SHAPE_POLY_SET &aCornerBuffer,
|
||||
int aWidth) const;
|
||||
|
||||
void transformPadsShapesWithClearanceToPolygon( const DLIST<D_PAD> &aPads,
|
||||
PCB_LAYER_ID aLayer,
|
||||
SHAPE_POLY_SET &aCornerBuffer,
|
||||
int aInflateValue,
|
||||
bool aSkipNPTHPadsWihNoCopper) const;
|
||||
|
||||
void transformGraphicModuleEdgeToPolygonSet( const MODULE *aModule,
|
||||
PCB_LAYER_ID aLayer,
|
||||
SHAPE_POLY_SET& aCornerBuffer ) const;
|
||||
|
||||
void buildPadShapePolygon( const D_PAD *aPad,
|
||||
SHAPE_POLY_SET &aCornerBuffer,
|
||||
wxSize aInflateValue,
|
||||
int aSegmentsPerCircle,
|
||||
double aCorrectionFactor ) const;
|
||||
|
||||
|
||||
public:
|
||||
SFVEC3D m_BgColorBot; ///< background bottom color
|
||||
SFVEC3D m_BgColorTop; ///< background top color
|
||||
SFVEC3D m_BoardBodyColor; ///< in realistic mode: FR4 board color
|
||||
SFVEC3D m_SolderMaskColor; ///< in realistic mode: solder mask color
|
||||
SFVEC3D m_SolderPasteColor; ///< in realistic mode: solder paste color
|
||||
SFVEC3D m_SilkScreenColor; ///< in realistic mode: SilkScreen color
|
||||
SFVEC3D m_CopperColor; ///< in realistic mode: copper color
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/// Current board
|
||||
BOARD *m_board;
|
||||
|
||||
/// pointer to the 3d model manager
|
||||
S3D_CACHE *m_3d_model_manager;
|
||||
|
||||
|
||||
// Render options
|
||||
|
||||
/// options flags to render the board
|
||||
std::vector< bool > m_drawFlags;
|
||||
|
||||
/// Stores the current grid type
|
||||
GRID3D_TYPE m_3D_grid_type;
|
||||
|
||||
/// render engine currently on use
|
||||
RENDER_ENGINE m_render_engine;
|
||||
|
||||
/// mode to render the 3d shape models material
|
||||
MATERIAL_MODE m_material_mode;
|
||||
|
||||
|
||||
// Pcb board position
|
||||
|
||||
/// center board actual position in board units
|
||||
wxPoint m_boardPos;
|
||||
|
||||
/// board actual size in board units
|
||||
wxSize m_boardSize;
|
||||
|
||||
/// 3d center position of the pcb board in 3d units
|
||||
SFVEC3F m_boardCenter;
|
||||
|
||||
|
||||
// Pcb board bounding boxes
|
||||
|
||||
/// 3d bouding box of the pcb board in 3d units
|
||||
CBBOX m_boardBoudingBox;
|
||||
|
||||
/// 2d bouding box of the pcb board in 3d units
|
||||
CBBOX2D m_board2dBBox3DU;
|
||||
|
||||
/// It contains polygon contours for each layer
|
||||
MAP_POLY m_layers_poly;
|
||||
|
||||
/// It contains polygon contours for holes of each layer (outer holes)
|
||||
MAP_POLY m_layers_outer_holes_poly;
|
||||
|
||||
/// It contains polygon contours for holes of each layer (inner holes)
|
||||
MAP_POLY m_layers_inner_holes_poly;
|
||||
|
||||
/// It contains polygon contours for (just) non plated through holes (outer cylinder)
|
||||
SHAPE_POLY_SET m_through_outer_holes_poly_NPTH;
|
||||
|
||||
/// It contains polygon contours for through holes (outer cylinder)
|
||||
SHAPE_POLY_SET m_through_outer_holes_poly;
|
||||
|
||||
/// It contains polygon contours for through holes (inner cylinder)
|
||||
SHAPE_POLY_SET m_through_inner_holes_poly;
|
||||
|
||||
/// It contains polygon contours for through holes vias (outer cylinder)
|
||||
SHAPE_POLY_SET m_through_outer_holes_vias_poly;
|
||||
|
||||
/// It contains polygon contours for through holes vias (inner cylinder)
|
||||
SHAPE_POLY_SET m_through_inner_holes_vias_poly;
|
||||
|
||||
/// PCB board outline polygon
|
||||
SHAPE_POLY_SET m_board_poly;
|
||||
|
||||
|
||||
// 2D element containers
|
||||
|
||||
/// It contains the 2d elements of each layer
|
||||
MAP_CONTAINER_2D m_layers_container2D;
|
||||
|
||||
/// It contains the holes per each layer
|
||||
MAP_CONTAINER_2D m_layers_holes2D;
|
||||
|
||||
/// It contains the list of throughHoles of the board,
|
||||
/// the radius of the hole is inflated with the copper tickness
|
||||
CBVHCONTAINER2D m_through_holes_outer;
|
||||
|
||||
/// It contains the list of throughHoles of the board,
|
||||
/// the radius is the inner hole
|
||||
CBVHCONTAINER2D m_through_holes_inner;
|
||||
|
||||
/// It contains the list of throughHoles vias of the board,
|
||||
/// the radius of the hole is inflated with the copper tickness
|
||||
CBVHCONTAINER2D m_through_holes_vias_outer;
|
||||
|
||||
/// It contains the list of throughHoles vias of the board,
|
||||
/// the radius of the hole
|
||||
CBVHCONTAINER2D m_through_holes_vias_inner;
|
||||
|
||||
|
||||
// Layers information
|
||||
|
||||
/// Number of copper layers actually used by the board
|
||||
unsigned int m_copperLayersCount;
|
||||
|
||||
/// Normalization scale to convert board internal units to 3D units to
|
||||
/// normalize 3D units between -1.0 and +1.0
|
||||
double m_biuTo3Dunits;
|
||||
|
||||
/// Top (End) Z position of each layer (normalized)
|
||||
float m_layerZcoordTop[PCB_LAYER_ID_COUNT];
|
||||
|
||||
/// Bottom (Start) Z position of each layer (normalized)
|
||||
float m_layerZcoordBottom[PCB_LAYER_ID_COUNT];
|
||||
|
||||
/// Copper thickness (normalized)
|
||||
float m_copperThickness3DU;
|
||||
|
||||
/// Epoxy thickness (normalized)
|
||||
float m_epoxyThickness3DU;
|
||||
|
||||
/// Non copper layers thickness
|
||||
float m_nonCopperLayerThickness3DU;
|
||||
|
||||
|
||||
// Cameras
|
||||
|
||||
/// Holds a pointer to current camera in use.
|
||||
CCAMERA &m_currentCamera;
|
||||
CTRACK_BALL m_trackBallCamera;
|
||||
|
||||
/// min factor used for cicle segment approximation calculation
|
||||
float m_calc_seg_min_factor3DU;
|
||||
|
||||
/// max factor used for cicle segment approximation calculation
|
||||
float m_calc_seg_max_factor3DU;
|
||||
|
||||
|
||||
// Statistics
|
||||
|
||||
/// Number of tracks in the board
|
||||
unsigned int m_stats_nr_tracks;
|
||||
|
||||
/// Track average width
|
||||
float m_stats_track_med_width;
|
||||
|
||||
/// Nr of vias
|
||||
unsigned int m_stats_nr_vias;
|
||||
|
||||
/// Computed medium diameter of the via holes in 3D units
|
||||
float m_stats_via_med_hole_diameter;
|
||||
|
||||
/// number of holes in the board
|
||||
unsigned int m_stats_nr_holes;
|
||||
|
||||
/// Computed medium diameter of the holes in 3D units
|
||||
float m_stats_hole_med_diameter;
|
||||
|
||||
/**
|
||||
* Trace mask used to enable or disable the trace output of this class.
|
||||
* The debug output can be turned on by setting the WXTRACE environment variable to
|
||||
* "KI_TRACE_EDA_CINFO3D_VISU". See the wxWidgets documentation on wxLogTrace for
|
||||
* more information.
|
||||
*/
|
||||
static const wxChar *m_logTrace;
|
||||
|
||||
};
|
||||
|
||||
/// This is a dummy visualization configuration
|
||||
extern CINFO3D_VISU G_null_CINFO3D_VISU;
|
||||
|
||||
#endif // CINFO3D_VISU_H
|
||||
@@ -1,986 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file create_graphic_brd_items.cpp
|
||||
* @brief This file implements the creation of 2D graphic primitives of pcb items:
|
||||
* pads, tracks, drawsegments, texts....
|
||||
* It is based on the function found in the files:
|
||||
* board_items_to_polygon_shape_transform.cpp
|
||||
*/
|
||||
|
||||
#include "cinfo3d_visu.h"
|
||||
#include "../3d_rendering/3d_render_raytracing/shapes2D/cring2d.h"
|
||||
#include "../3d_rendering/3d_render_raytracing/shapes2D/cfilledcircle2d.h"
|
||||
#include "../3d_rendering/3d_render_raytracing/shapes2D/croundsegment2d.h"
|
||||
#include "../3d_rendering/3d_render_raytracing/shapes2D/cpolygon4pts2d.h"
|
||||
#include "../3d_rendering/3d_render_raytracing/shapes2D/cpolygon2d.h"
|
||||
#include "../3d_rendering/3d_render_raytracing/shapes2D/ctriangle2d.h"
|
||||
#include "../3d_rendering/3d_render_raytracing/accelerators/ccontainer2d.h"
|
||||
#include "../3d_rendering/3d_render_raytracing/shapes3D/ccylinder.h"
|
||||
#include "../3d_rendering/3d_render_raytracing/shapes3D/clayeritem.h"
|
||||
|
||||
#include <class_board.h>
|
||||
#include <class_module.h>
|
||||
#include <class_pad.h>
|
||||
#include <class_pcb_text.h>
|
||||
#include <class_edge_mod.h>
|
||||
#include <class_zone.h>
|
||||
#include <class_text_mod.h>
|
||||
#include <convert_basic_shapes_to_polygon.h>
|
||||
#include <trigo.h>
|
||||
#include <draw_graphic_text.h>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
|
||||
|
||||
// These variables are parameters used in addTextSegmToContainer.
|
||||
// But addTextSegmToContainer is a call-back function,
|
||||
// so we cannot send them as arguments.
|
||||
static int s_textWidth;
|
||||
static CGENERICCONTAINER2D *s_dstcontainer = NULL;
|
||||
static float s_biuTo3Dunits;
|
||||
static const CBBOX2D *s_boardBBox3DU = NULL;
|
||||
static const BOARD_ITEM *s_boardItem = NULL;
|
||||
|
||||
// This is a call back function, used by DrawGraphicText to draw the 3D text shape:
|
||||
void addTextSegmToContainer( int x0, int y0, int xf, int yf, void* aData )
|
||||
{
|
||||
wxASSERT( s_boardBBox3DU != NULL );
|
||||
wxASSERT( s_dstcontainer != NULL );
|
||||
|
||||
const SFVEC2F start3DU( x0 * s_biuTo3Dunits, -y0 * s_biuTo3Dunits );
|
||||
const SFVEC2F end3DU ( xf * s_biuTo3Dunits, -yf * s_biuTo3Dunits );
|
||||
|
||||
if( Is_segment_a_circle( start3DU, end3DU ) )
|
||||
s_dstcontainer->Add( new CFILLEDCIRCLE2D( start3DU,
|
||||
s_textWidth * s_biuTo3Dunits,
|
||||
*s_boardItem) );
|
||||
else
|
||||
s_dstcontainer->Add( new CROUNDSEGMENT2D( start3DU,
|
||||
end3DU,
|
||||
s_textWidth * s_biuTo3Dunits,
|
||||
*s_boardItem ) );
|
||||
}
|
||||
|
||||
|
||||
// Based on
|
||||
// void TEXTE_PCB::TransformShapeWithClearanceToPolygonSet
|
||||
// board_items_to_polygon_shape_transform.cpp
|
||||
void CINFO3D_VISU::AddShapeWithClearanceToContainer( const TEXTE_PCB* aTextPCB,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId,
|
||||
int aClearanceValue )
|
||||
{
|
||||
wxSize size = aTextPCB->GetTextSize();
|
||||
|
||||
if( aTextPCB->IsMirrored() )
|
||||
size.x = -size.x;
|
||||
|
||||
s_boardItem = (const BOARD_ITEM *)&aTextPCB;
|
||||
s_dstcontainer = aDstContainer;
|
||||
s_textWidth = aTextPCB->GetThickness() + ( 2 * aClearanceValue );
|
||||
s_biuTo3Dunits = m_biuTo3Dunits;
|
||||
s_boardBBox3DU = &m_board2dBBox3DU;
|
||||
|
||||
// not actually used, but needed by DrawGraphicText
|
||||
const COLOR4D dummy_color = COLOR4D::BLACK;
|
||||
|
||||
if( aTextPCB->IsMultilineAllowed() )
|
||||
{
|
||||
wxArrayString strings_list;
|
||||
wxStringSplit( aTextPCB->GetShownText(), strings_list, '\n' );
|
||||
std::vector<wxPoint> positions;
|
||||
positions.reserve( strings_list.Count() );
|
||||
aTextPCB->GetPositionsOfLinesOfMultilineText( positions,
|
||||
strings_list.Count() );
|
||||
|
||||
for( unsigned ii = 0; ii < strings_list.Count(); ++ii )
|
||||
{
|
||||
wxString txt = strings_list.Item( ii );
|
||||
|
||||
DrawGraphicText( NULL, NULL, positions[ii], dummy_color,
|
||||
txt, aTextPCB->GetTextAngle(), size,
|
||||
aTextPCB->GetHorizJustify(), aTextPCB->GetVertJustify(),
|
||||
aTextPCB->GetThickness(), aTextPCB->IsItalic(),
|
||||
true, addTextSegmToContainer );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawGraphicText( NULL, NULL, aTextPCB->GetTextPos(), dummy_color,
|
||||
aTextPCB->GetShownText(), aTextPCB->GetTextAngle(), size,
|
||||
aTextPCB->GetHorizJustify(), aTextPCB->GetVertJustify(),
|
||||
aTextPCB->GetThickness(), aTextPCB->IsItalic(),
|
||||
true, addTextSegmToContainer );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CINFO3D_VISU::AddShapeWithClearanceToContainer( const DIMENSION* aDimension,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId,
|
||||
int aClearanceValue )
|
||||
{
|
||||
AddShapeWithClearanceToContainer(&aDimension->Text(), aDstContainer, aLayerId, aClearanceValue);
|
||||
|
||||
const int linewidth = aDimension->GetWidth() + (2 * aClearanceValue);
|
||||
|
||||
std::pair<wxPoint const *, wxPoint const *> segs[] = {
|
||||
{&aDimension->m_crossBarO, &aDimension->m_crossBarF},
|
||||
{&aDimension->m_featureLineGO, &aDimension->m_featureLineGF},
|
||||
{&aDimension->m_featureLineDO, &aDimension->m_featureLineDF},
|
||||
{&aDimension->m_crossBarF, &aDimension->m_arrowD1F},
|
||||
{&aDimension->m_crossBarF, &aDimension->m_arrowD2F},
|
||||
{&aDimension->m_crossBarO, &aDimension->m_arrowG1F},
|
||||
{&aDimension->m_crossBarO, &aDimension->m_arrowG2F}};
|
||||
|
||||
for( auto const & ii : segs )
|
||||
{
|
||||
const SFVEC2F start3DU( ii.first->x * m_biuTo3Dunits,
|
||||
-ii.first->y * m_biuTo3Dunits );
|
||||
|
||||
const SFVEC2F end3DU ( ii.second->x * m_biuTo3Dunits,
|
||||
-ii.second->y * m_biuTo3Dunits );
|
||||
|
||||
aDstContainer->Add( new CROUNDSEGMENT2D( start3DU,
|
||||
end3DU,
|
||||
linewidth * m_biuTo3Dunits,
|
||||
*aDimension ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Based on
|
||||
// void MODULE::TransformGraphicShapesWithClearanceToPolygonSet
|
||||
// board_items_to_polygon_shape_transform.cpp#L204
|
||||
void CINFO3D_VISU::AddGraphicsShapesWithClearanceToContainer( const MODULE* aModule,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId,
|
||||
int aInflateValue )
|
||||
{
|
||||
std::vector<TEXTE_MODULE *> texts; // List of TEXTE_MODULE to convert
|
||||
EDGE_MODULE* outline;
|
||||
|
||||
for( EDA_ITEM* item = aModule->GraphicalItemsList();
|
||||
item != NULL;
|
||||
item = item->Next() )
|
||||
{
|
||||
switch( item->Type() )
|
||||
{
|
||||
case PCB_MODULE_TEXT_T:
|
||||
{
|
||||
TEXTE_MODULE* text = static_cast<TEXTE_MODULE*>( item );
|
||||
|
||||
if( text->GetLayer() == aLayerId && text->IsVisible() )
|
||||
texts.push_back( text );
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case PCB_MODULE_EDGE_T:
|
||||
{
|
||||
outline = (EDGE_MODULE*) item;
|
||||
|
||||
if( outline->GetLayer() != aLayerId )
|
||||
break;
|
||||
|
||||
AddShapeWithClearanceToContainer( (const DRAWSEGMENT *)outline,
|
||||
aDstContainer,
|
||||
aLayerId, 0 );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert texts sur modules
|
||||
if( aModule->Reference().GetLayer() == aLayerId && aModule->Reference().IsVisible() )
|
||||
texts.push_back( &aModule->Reference() );
|
||||
|
||||
if( aModule->Value().GetLayer() == aLayerId && aModule->Value().IsVisible() )
|
||||
texts.push_back( &aModule->Value() );
|
||||
|
||||
s_boardItem = (const BOARD_ITEM *)&aModule->Value();
|
||||
s_dstcontainer = aDstContainer;
|
||||
s_biuTo3Dunits = m_biuTo3Dunits;
|
||||
s_boardBBox3DU = &m_board2dBBox3DU;
|
||||
|
||||
for( unsigned ii = 0; ii < texts.size(); ++ii )
|
||||
{
|
||||
TEXTE_MODULE *textmod = texts[ii];
|
||||
s_textWidth = textmod->GetThickness() + ( 2 * aInflateValue );
|
||||
wxSize size = textmod->GetTextSize();
|
||||
|
||||
if( textmod->IsMirrored() )
|
||||
size.x = -size.x;
|
||||
|
||||
DrawGraphicText( NULL, NULL, textmod->GetTextPos(), BLACK,
|
||||
textmod->GetShownText(), textmod->GetDrawRotation(), size,
|
||||
textmod->GetHorizJustify(), textmod->GetVertJustify(),
|
||||
textmod->GetThickness(), textmod->IsItalic(),
|
||||
true, addTextSegmToContainer );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
COBJECT2D *CINFO3D_VISU::createNewTrack( const TRACK* aTrack,
|
||||
int aClearanceValue ) const
|
||||
{
|
||||
SFVEC2F start3DU( aTrack->GetStart().x * m_biuTo3Dunits,
|
||||
-aTrack->GetStart().y * m_biuTo3Dunits ); // y coord is inverted
|
||||
|
||||
switch( aTrack->Type() )
|
||||
{
|
||||
case PCB_VIA_T:
|
||||
{
|
||||
const float radius = ( ( aTrack->GetWidth() / 2 ) + aClearanceValue ) * m_biuTo3Dunits;
|
||||
|
||||
return new CFILLEDCIRCLE2D( start3DU, radius, *aTrack );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
wxASSERT( aTrack->Type() == PCB_TRACE_T );
|
||||
|
||||
SFVEC2F end3DU ( aTrack->GetEnd().x * m_biuTo3Dunits,
|
||||
-aTrack->GetEnd().y * m_biuTo3Dunits );
|
||||
|
||||
// Cannot add segments that have the same start and end point
|
||||
if( Is_segment_a_circle( start3DU, end3DU ) )
|
||||
{
|
||||
const float radius = ((aTrack->GetWidth() / 2) + aClearanceValue) * m_biuTo3Dunits;
|
||||
|
||||
return new CFILLEDCIRCLE2D( start3DU, radius, *aTrack );
|
||||
}
|
||||
else
|
||||
{
|
||||
const float width = (aTrack->GetWidth() + 2 * aClearanceValue ) * m_biuTo3Dunits;
|
||||
|
||||
return new CROUNDSEGMENT2D( start3DU, end3DU, width, *aTrack );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// Based on:
|
||||
// void D_PAD:: TransformShapeWithClearanceToPolygon(
|
||||
// board_items_to_polygon_shape_transform.cpp
|
||||
void CINFO3D_VISU::createNewPadWithClearance( const D_PAD* aPad,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
wxSize aClearanceValue ) const
|
||||
{
|
||||
// note: for most of shapes, aClearanceValue.x = aClearanceValue.y
|
||||
// only rectangular and oval shapes can have different values
|
||||
// when drawn on the solder paste layer, because we can have a margin that is a
|
||||
// percent of pad size
|
||||
const int dx = (aPad->GetSize().x / 2) + aClearanceValue.x;
|
||||
const int dy = (aPad->GetSize().y / 2) + aClearanceValue.y;
|
||||
|
||||
if( !dx || !dy )
|
||||
{
|
||||
wxLogTrace( m_logTrace,
|
||||
wxT( "CINFO3D_VISU::createNewPadWithClearance - found an invalid pad" ) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
wxPoint PadShapePos = aPad->ShapePos(); // Note: for pad having a shape offset,
|
||||
// the pad position is NOT the shape position
|
||||
|
||||
switch( aPad->GetShape() )
|
||||
{
|
||||
case PAD_SHAPE_CIRCLE:
|
||||
{
|
||||
const float radius = dx * m_biuTo3Dunits;
|
||||
|
||||
const SFVEC2F center( PadShapePos.x * m_biuTo3Dunits,
|
||||
-PadShapePos.y * m_biuTo3Dunits );
|
||||
|
||||
aDstContainer->Add( new CFILLEDCIRCLE2D( center, radius, *aPad ) );
|
||||
}
|
||||
break;
|
||||
|
||||
case PAD_SHAPE_OVAL:
|
||||
{
|
||||
if( dx == dy )
|
||||
{
|
||||
// The segment object cannot store start and end the same position,
|
||||
// so add a circle instead
|
||||
const float radius = dx * m_biuTo3Dunits;
|
||||
|
||||
const SFVEC2F center( PadShapePos.x * m_biuTo3Dunits,
|
||||
-PadShapePos.y * m_biuTo3Dunits );
|
||||
|
||||
aDstContainer->Add( new CFILLEDCIRCLE2D( center, radius, *aPad ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// An oval pad has the same shape as a segment with rounded ends
|
||||
|
||||
int iwidth;
|
||||
wxPoint shape_offset = wxPoint( 0, 0 );
|
||||
|
||||
if( dy > dx ) // Oval pad X/Y ratio for choosing translation axis
|
||||
{
|
||||
shape_offset.y = dy - dx;
|
||||
iwidth = dx * 2;
|
||||
}
|
||||
else //if( dy < dx )
|
||||
{
|
||||
shape_offset.x = dy - dx;
|
||||
iwidth = dy * 2;
|
||||
}
|
||||
|
||||
RotatePoint( &shape_offset, aPad->GetOrientation() );
|
||||
|
||||
const wxPoint start = PadShapePos - shape_offset;
|
||||
const wxPoint end = PadShapePos + shape_offset;
|
||||
|
||||
const SFVEC2F start3DU( start.x * m_biuTo3Dunits, -start.y * m_biuTo3Dunits );
|
||||
const SFVEC2F end3DU ( end.x * m_biuTo3Dunits, -end.y * m_biuTo3Dunits );
|
||||
|
||||
// Cannot add segments that have the same start and end point
|
||||
if( Is_segment_a_circle( start3DU, end3DU ) )
|
||||
{
|
||||
aDstContainer->Add( new CFILLEDCIRCLE2D( start3DU,
|
||||
(iwidth / 2) * m_biuTo3Dunits,
|
||||
*aPad ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
aDstContainer->Add( new CROUNDSEGMENT2D( start3DU, end3DU,
|
||||
iwidth * m_biuTo3Dunits,
|
||||
*aPad ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PAD_SHAPE_TRAPEZOID:
|
||||
case PAD_SHAPE_RECT:
|
||||
{
|
||||
// see pcbnew/board_items_to_polygon_shape_transform.cpp
|
||||
|
||||
wxPoint corners[4];
|
||||
aPad->BuildPadPolygon( corners, wxSize( 0, 0), aPad->GetOrientation() );
|
||||
|
||||
SFVEC2F corners3DU[4];
|
||||
|
||||
// Note: for pad having a shape offset,
|
||||
// the pad position is NOT the shape position
|
||||
for( unsigned int ii = 0; ii < 4; ++ii )
|
||||
{
|
||||
corners[ii] += aPad->ShapePos(); // Shift origin to position
|
||||
|
||||
corners3DU[ii] = SFVEC2F( corners[ii].x * m_biuTo3Dunits,
|
||||
-corners[ii].y * m_biuTo3Dunits );
|
||||
}
|
||||
|
||||
|
||||
// Learn more at:
|
||||
// https://lists.launchpad.net/kicad-developers/msg18729.html
|
||||
|
||||
// Add the PAD polygon
|
||||
aDstContainer->Add( new CPOLYGON4PTS2D( corners3DU[0],
|
||||
corners3DU[1],
|
||||
corners3DU[2],
|
||||
corners3DU[3],
|
||||
*aPad ) );
|
||||
|
||||
// Add the PAD contours
|
||||
// Round segments cannot have 0-length elements, so we approximate them
|
||||
// as a small circle
|
||||
for( int i = 1; i <= 4; i++ )
|
||||
{
|
||||
if( Is_segment_a_circle( corners3DU[i - 1], corners3DU[i & 3] ) )
|
||||
{
|
||||
aDstContainer->Add( new CFILLEDCIRCLE2D( corners3DU[i - 1],
|
||||
aClearanceValue.x * m_biuTo3Dunits,
|
||||
*aPad ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
aDstContainer->Add( new CROUNDSEGMENT2D( corners3DU[i - 1],
|
||||
corners3DU[i & 3],
|
||||
aClearanceValue.x * 2.0f * m_biuTo3Dunits,
|
||||
*aPad ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PAD_SHAPE_ROUNDRECT:
|
||||
{
|
||||
wxSize shapesize( aPad->GetSize() );
|
||||
shapesize.x += aClearanceValue.x * 2;
|
||||
shapesize.y += aClearanceValue.y * 2;
|
||||
|
||||
int rounding_radius = aPad->GetRoundRectCornerRadius( shapesize );
|
||||
|
||||
wxPoint corners[4];
|
||||
|
||||
GetRoundRectCornerCenters( corners,
|
||||
rounding_radius,
|
||||
PadShapePos,
|
||||
shapesize,
|
||||
aPad->GetOrientation() );
|
||||
|
||||
SFVEC2F corners3DU[4];
|
||||
|
||||
for( unsigned int ii = 0; ii < 4; ++ii )
|
||||
corners3DU[ii] = SFVEC2F( corners[ii].x * m_biuTo3Dunits,
|
||||
-corners[ii].y * m_biuTo3Dunits );
|
||||
|
||||
// Add the PAD polygon (For some reason the corners need
|
||||
// to be inverted to display with the correctly orientation)
|
||||
aDstContainer->Add( new CPOLYGON4PTS2D( corners3DU[0],
|
||||
corners3DU[3],
|
||||
corners3DU[2],
|
||||
corners3DU[1],
|
||||
*aPad ) );
|
||||
|
||||
// Add the PAD contours
|
||||
// Round segments cannot have 0-length elements, so we approximate them
|
||||
// as a small circle
|
||||
for( int i = 1; i <= 4; i++ )
|
||||
{
|
||||
if( Is_segment_a_circle( corners3DU[i - 1], corners3DU[i & 3] ) )
|
||||
{
|
||||
aDstContainer->Add( new CFILLEDCIRCLE2D( corners3DU[i - 1],
|
||||
rounding_radius * m_biuTo3Dunits,
|
||||
*aPad ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
aDstContainer->Add( new CROUNDSEGMENT2D( corners3DU[i - 1],
|
||||
corners3DU[i & 3],
|
||||
rounding_radius * 2.0f * m_biuTo3Dunits,
|
||||
*aPad ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PAD_SHAPE_CUSTOM:
|
||||
{
|
||||
SHAPE_POLY_SET polyList; // Will contain the pad outlines in board coordinates
|
||||
polyList.Append( aPad->GetCustomShapeAsPolygon() );
|
||||
aPad->CustomShapeAsPolygonToBoardPosition( &polyList, aPad->ShapePos(), aPad->GetOrientation() );
|
||||
|
||||
if( aClearanceValue.x )
|
||||
polyList.Inflate( aClearanceValue.x, 32 );
|
||||
|
||||
// Add the PAD polygon
|
||||
Convert_shape_line_polygon_to_triangles( polyList, *aDstContainer, m_biuTo3Dunits, *aPad );
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Based on:
|
||||
// BuildPadDrillShapePolygon
|
||||
// board_items_to_polygon_shape_transform.cpp
|
||||
COBJECT2D *CINFO3D_VISU::createNewPadDrill( const D_PAD* aPad, int aInflateValue )
|
||||
{
|
||||
wxSize drillSize = aPad->GetDrillSize();
|
||||
|
||||
if( !drillSize.x || !drillSize.y )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "CINFO3D_VISU::createNewPadDrill - found an invalid pad" ) );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( drillSize.x == drillSize.y ) // usual round hole
|
||||
{
|
||||
const int radius = (drillSize.x / 2) + aInflateValue;
|
||||
|
||||
const SFVEC2F center( aPad->GetPosition().x * m_biuTo3Dunits,
|
||||
-aPad->GetPosition().y * m_biuTo3Dunits );
|
||||
|
||||
return new CFILLEDCIRCLE2D( center, radius * m_biuTo3Dunits, *aPad );
|
||||
|
||||
}
|
||||
else // Oblong hole
|
||||
{
|
||||
wxPoint start, end;
|
||||
int width;
|
||||
|
||||
aPad->GetOblongDrillGeometry( start, end, width );
|
||||
|
||||
width += aInflateValue * 2;
|
||||
start += aPad->GetPosition();
|
||||
end += aPad->GetPosition();
|
||||
|
||||
SFVEC2F start3DU( start.x * m_biuTo3Dunits,
|
||||
-start.y * m_biuTo3Dunits );
|
||||
|
||||
SFVEC2F end3DU ( end.x * m_biuTo3Dunits,
|
||||
-end.y * m_biuTo3Dunits );
|
||||
|
||||
if( Is_segment_a_circle( start3DU, end3DU ) )
|
||||
{
|
||||
return new CFILLEDCIRCLE2D( start3DU, (width / 2) * m_biuTo3Dunits, *aPad );
|
||||
}
|
||||
else
|
||||
{
|
||||
return new CROUNDSEGMENT2D( start3DU, end3DU, width * m_biuTo3Dunits, *aPad );
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// This function pretends to be like the
|
||||
// void D_PAD::BuildPadShapePolygon(
|
||||
// board_items_to_polygon_shape_transform.cpp
|
||||
void CINFO3D_VISU::createNewPad( const D_PAD* aPad,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
wxSize aInflateValue ) const
|
||||
{
|
||||
switch( aPad->GetShape() )
|
||||
{
|
||||
case PAD_SHAPE_CIRCLE:
|
||||
case PAD_SHAPE_OVAL:
|
||||
case PAD_SHAPE_ROUNDRECT:
|
||||
case PAD_SHAPE_CUSTOM:
|
||||
createNewPadWithClearance( aPad, aDstContainer, aInflateValue );
|
||||
break;
|
||||
|
||||
case PAD_SHAPE_TRAPEZOID:
|
||||
case PAD_SHAPE_RECT:
|
||||
wxPoint corners[4];
|
||||
aPad->BuildPadPolygon( corners, aInflateValue, aPad->GetOrientation() );
|
||||
|
||||
// Note: for pad having a shape offset,
|
||||
// the pad position is NOT the shape position
|
||||
for( unsigned int ii = 0; ii < 4; ++ii )
|
||||
corners[ii] += aPad->ShapePos(); // Shift origin to position
|
||||
|
||||
aDstContainer->Add( new CPOLYGON4PTS2D(
|
||||
SFVEC2F( corners[0].x * m_biuTo3Dunits,
|
||||
-corners[0].y * m_biuTo3Dunits ),
|
||||
SFVEC2F( corners[1].x * m_biuTo3Dunits,
|
||||
-corners[1].y * m_biuTo3Dunits ),
|
||||
SFVEC2F( corners[2].x * m_biuTo3Dunits,
|
||||
-corners[2].y * m_biuTo3Dunits ),
|
||||
SFVEC2F( corners[3].x * m_biuTo3Dunits,
|
||||
-corners[3].y * m_biuTo3Dunits ),
|
||||
*aPad ) );
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CINFO3D_VISU::AddPadsShapesWithClearanceToContainer( const MODULE* aModule,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId,
|
||||
int aInflateValue,
|
||||
bool aSkipNPTHPadsWihNoCopper )
|
||||
{
|
||||
const D_PAD* pad = aModule->PadsList();
|
||||
|
||||
wxSize margin;
|
||||
|
||||
for( ; pad != NULL; pad = pad->Next() )
|
||||
{
|
||||
if( !pad->IsOnLayer( aLayerId ) )
|
||||
continue;
|
||||
|
||||
// NPTH pads are not drawn on layers if the
|
||||
// shape size and pos is the same as their hole:
|
||||
if( aSkipNPTHPadsWihNoCopper && (pad->GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED) )
|
||||
{
|
||||
if( (pad->GetDrillSize() == pad->GetSize()) &&
|
||||
(pad->GetOffset() == wxPoint( 0, 0 )) )
|
||||
{
|
||||
switch( pad->GetShape() )
|
||||
{
|
||||
case PAD_SHAPE_CIRCLE:
|
||||
if( pad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
|
||||
continue;
|
||||
break;
|
||||
|
||||
case PAD_SHAPE_OVAL:
|
||||
if( pad->GetDrillShape() != PAD_DRILL_SHAPE_CIRCLE )
|
||||
continue;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch( aLayerId )
|
||||
{
|
||||
case F_Mask:
|
||||
case B_Mask:
|
||||
margin.x = margin.y = pad->GetSolderMaskMargin() + aInflateValue;
|
||||
break;
|
||||
|
||||
case F_Paste:
|
||||
case B_Paste:
|
||||
margin = pad->GetSolderPasteMargin();
|
||||
margin.x += aInflateValue;
|
||||
margin.y += aInflateValue;
|
||||
break;
|
||||
|
||||
default:
|
||||
margin.x = margin.y = aInflateValue;
|
||||
break;
|
||||
}
|
||||
|
||||
createNewPad( pad, aDstContainer, margin );
|
||||
}
|
||||
}
|
||||
|
||||
// based on TransformArcToPolygon function from
|
||||
// common/convert_basic_shapes_to_polygon.cpp
|
||||
void CINFO3D_VISU::TransformArcToSegments( const wxPoint &aCentre,
|
||||
const wxPoint &aStart,
|
||||
double aArcAngle,
|
||||
int aCircleToSegmentsCount,
|
||||
int aWidth,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
const BOARD_ITEM &aBoardItem )
|
||||
{
|
||||
wxPoint arc_start, arc_end;
|
||||
int delta = 3600 / aCircleToSegmentsCount; // rotate angle in 0.1 degree
|
||||
|
||||
arc_end = arc_start = aStart;
|
||||
|
||||
if( aArcAngle != 3600 )
|
||||
{
|
||||
RotatePoint( &arc_end, aCentre, -aArcAngle );
|
||||
}
|
||||
|
||||
if( aArcAngle < 0 )
|
||||
{
|
||||
std::swap( arc_start, arc_end );
|
||||
aArcAngle = -aArcAngle;
|
||||
}
|
||||
|
||||
// Compute the ends of segments and creates poly
|
||||
wxPoint curr_end = arc_start;
|
||||
wxPoint curr_start = arc_start;
|
||||
|
||||
for( int ii = delta; ii < aArcAngle; ii += delta )
|
||||
{
|
||||
curr_end = arc_start;
|
||||
RotatePoint( &curr_end, aCentre, -ii );
|
||||
|
||||
const SFVEC2F start3DU( curr_start.x * m_biuTo3Dunits, -curr_start.y * m_biuTo3Dunits );
|
||||
const SFVEC2F end3DU ( curr_end.x * m_biuTo3Dunits, -curr_end.y * m_biuTo3Dunits );
|
||||
|
||||
if( Is_segment_a_circle( start3DU, end3DU ) )
|
||||
{
|
||||
aDstContainer->Add( new CFILLEDCIRCLE2D( start3DU,
|
||||
( aWidth / 2 ) * m_biuTo3Dunits,
|
||||
aBoardItem ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
aDstContainer->Add( new CROUNDSEGMENT2D( start3DU,
|
||||
end3DU,
|
||||
aWidth * m_biuTo3Dunits,
|
||||
aBoardItem ) );
|
||||
}
|
||||
|
||||
curr_start = curr_end;
|
||||
}
|
||||
|
||||
if( curr_end != arc_end )
|
||||
{
|
||||
const SFVEC2F start3DU( curr_end.x * m_biuTo3Dunits, -curr_end.y * m_biuTo3Dunits );
|
||||
const SFVEC2F end3DU ( arc_end.x * m_biuTo3Dunits, -arc_end.y * m_biuTo3Dunits );
|
||||
|
||||
if( Is_segment_a_circle( start3DU, end3DU ) )
|
||||
{
|
||||
aDstContainer->Add( new CFILLEDCIRCLE2D( start3DU,
|
||||
( aWidth / 2 ) * m_biuTo3Dunits,
|
||||
aBoardItem ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
aDstContainer->Add( new CROUNDSEGMENT2D( start3DU,
|
||||
end3DU,
|
||||
aWidth * m_biuTo3Dunits,
|
||||
aBoardItem ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Based on
|
||||
// TransformShapeWithClearanceToPolygon
|
||||
// board_items_to_polygon_shape_transform.cpp#L431
|
||||
void CINFO3D_VISU::AddShapeWithClearanceToContainer( const DRAWSEGMENT* aDrawSegment,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId,
|
||||
int aClearanceValue )
|
||||
{
|
||||
// The full width of the lines to create
|
||||
// The extra 1 protects the inner/outer radius values from degeneracy
|
||||
const int linewidth = aDrawSegment->GetWidth() + (2 * aClearanceValue) + 1;
|
||||
|
||||
switch( aDrawSegment->GetShape() )
|
||||
{
|
||||
case S_CIRCLE:
|
||||
{
|
||||
const SFVEC2F center3DU( aDrawSegment->GetCenter().x * m_biuTo3Dunits,
|
||||
-aDrawSegment->GetCenter().y * m_biuTo3Dunits );
|
||||
|
||||
const float inner_radius =
|
||||
std::max<float>( (aDrawSegment->GetRadius() - linewidth / 2) * m_biuTo3Dunits, 0.0 );
|
||||
const float outter_radius = (aDrawSegment->GetRadius() + linewidth / 2) * m_biuTo3Dunits;
|
||||
|
||||
aDstContainer->Add( new CRING2D( center3DU,
|
||||
inner_radius,
|
||||
outter_radius,
|
||||
*aDrawSegment ) );
|
||||
}
|
||||
break;
|
||||
|
||||
case S_ARC:
|
||||
{
|
||||
const unsigned int nr_segments =
|
||||
GetNrSegmentsCircle( aDrawSegment->GetBoundingBox().GetSizeMax() );
|
||||
|
||||
TransformArcToSegments( aDrawSegment->GetCenter(),
|
||||
aDrawSegment->GetArcStart(),
|
||||
aDrawSegment->GetAngle(),
|
||||
nr_segments,
|
||||
aDrawSegment->GetWidth(),
|
||||
aDstContainer,
|
||||
*aDrawSegment );
|
||||
}
|
||||
break;
|
||||
|
||||
case S_SEGMENT:
|
||||
{
|
||||
const SFVEC2F start3DU( aDrawSegment->GetStart().x * m_biuTo3Dunits,
|
||||
-aDrawSegment->GetStart().y * m_biuTo3Dunits );
|
||||
|
||||
const SFVEC2F end3DU ( aDrawSegment->GetEnd().x * m_biuTo3Dunits,
|
||||
-aDrawSegment->GetEnd().y * m_biuTo3Dunits );
|
||||
|
||||
if( Is_segment_a_circle( start3DU, end3DU ) )
|
||||
{
|
||||
aDstContainer->Add( new CFILLEDCIRCLE2D( start3DU,
|
||||
( linewidth / 2 ) * m_biuTo3Dunits,
|
||||
*aDrawSegment ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
aDstContainer->Add( new CROUNDSEGMENT2D( start3DU,
|
||||
end3DU,
|
||||
linewidth * m_biuTo3Dunits,
|
||||
*aDrawSegment ) );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case S_CURVE:
|
||||
case S_POLYGON:
|
||||
{
|
||||
const int segcountforcircle = ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF;
|
||||
const double correctionFactor = GetCircleCorrectionFactor( segcountforcircle );
|
||||
SHAPE_POLY_SET polyList;
|
||||
|
||||
aDrawSegment->TransformShapeWithClearanceToPolygon( polyList, aClearanceValue,
|
||||
segcountforcircle, correctionFactor );
|
||||
|
||||
polyList.Simplify( SHAPE_POLY_SET::PM_FAST );
|
||||
|
||||
if( polyList.IsEmpty() ) // Just for caution
|
||||
break;
|
||||
|
||||
Convert_shape_line_polygon_to_triangles( polyList, *aDstContainer,
|
||||
m_biuTo3Dunits, *aDrawSegment );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Based on
|
||||
// TransformSolidAreasShapesToPolygonSet
|
||||
// board_items_to_polygon_shape_transform.cpp
|
||||
void CINFO3D_VISU::AddSolidAreasShapesToContainer( const ZONE_CONTAINER* aZoneContainer,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId )
|
||||
{
|
||||
// Copy the polys list because we have to simplify it
|
||||
SHAPE_POLY_SET polyList = SHAPE_POLY_SET( aZoneContainer->GetFilledPolysList(), true );
|
||||
|
||||
// This convert the poly in outline and holes
|
||||
Convert_shape_line_polygon_to_triangles( polyList,
|
||||
*aDstContainer,
|
||||
m_biuTo3Dunits,
|
||||
*aZoneContainer );
|
||||
|
||||
// add filled areas outlines, which are drawn with thick lines segments
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
for( int i = 0; i < polyList.OutlineCount(); ++i )
|
||||
{
|
||||
// Add outline
|
||||
const SHAPE_LINE_CHAIN& pathOutline = polyList.COutline( i );
|
||||
|
||||
for( int j = 0; j < pathOutline.PointCount(); ++j )
|
||||
{
|
||||
const VECTOR2I& a = pathOutline.CPoint( j );
|
||||
const VECTOR2I& b = pathOutline.CPoint( j + 1 );
|
||||
|
||||
SFVEC2F start3DU( a.x * m_biuTo3Dunits, -a.y * m_biuTo3Dunits );
|
||||
SFVEC2F end3DU ( b.x * m_biuTo3Dunits, -b.y * m_biuTo3Dunits );
|
||||
|
||||
if( Is_segment_a_circle( start3DU, end3DU ) )
|
||||
{
|
||||
float radius = (aZoneContainer->GetMinThickness() / 2) * m_biuTo3Dunits;
|
||||
|
||||
if( radius > 0.0 ) // degenerated circles crash 3D viewer
|
||||
aDstContainer->Add( new CFILLEDCIRCLE2D( start3DU, radius ,
|
||||
*aZoneContainer ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
aDstContainer->Add( new CROUNDSEGMENT2D( start3DU, end3DU,
|
||||
aZoneContainer->GetMinThickness() *
|
||||
m_biuTo3Dunits,
|
||||
*aZoneContainer ) );
|
||||
}
|
||||
}
|
||||
|
||||
// Add holes (of the poly, ie: the open parts) for this outline
|
||||
for( int h = 0; h < polyList.HoleCount( i ); ++h )
|
||||
{
|
||||
const SHAPE_LINE_CHAIN& pathHole = polyList.CHole( i, h );
|
||||
|
||||
for( int j = 0; j < pathHole.PointCount(); j++ )
|
||||
{
|
||||
const VECTOR2I& a = pathHole.CPoint( j );
|
||||
const VECTOR2I& b = pathHole.CPoint( j + 1 );
|
||||
|
||||
SFVEC2F start3DU( a.x * m_biuTo3Dunits, -a.y * m_biuTo3Dunits );
|
||||
SFVEC2F end3DU ( b.x * m_biuTo3Dunits, -b.y * m_biuTo3Dunits );
|
||||
|
||||
if( Is_segment_a_circle( start3DU, end3DU ) )
|
||||
{
|
||||
float radius = (aZoneContainer->GetMinThickness() / 2) * m_biuTo3Dunits;
|
||||
|
||||
if( radius > 0.0 ) // degenerated circles crash 3D viewer
|
||||
aDstContainer->Add(
|
||||
new CFILLEDCIRCLE2D( start3DU, radius,
|
||||
*aZoneContainer ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
aDstContainer->Add(
|
||||
new CROUNDSEGMENT2D( start3DU, end3DU,
|
||||
aZoneContainer->GetMinThickness() *
|
||||
m_biuTo3Dunits,
|
||||
*aZoneContainer ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CINFO3D_VISU::buildPadShapeThickOutlineAsSegments( const D_PAD* aPad,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
int aWidth )
|
||||
{
|
||||
if( aPad->GetShape() == PAD_SHAPE_CIRCLE ) // Draw a ring
|
||||
{
|
||||
const SFVEC2F center3DU( aPad->ShapePos().x * m_biuTo3Dunits,
|
||||
-aPad->ShapePos().y * m_biuTo3Dunits );
|
||||
|
||||
const int radius = aPad->GetSize().x / 2;
|
||||
const float inner_radius = (radius - aWidth / 2) * m_biuTo3Dunits;
|
||||
const float outter_radius = (radius + aWidth / 2) * m_biuTo3Dunits;
|
||||
|
||||
aDstContainer->Add( new CRING2D( center3DU,
|
||||
inner_radius,
|
||||
outter_radius,
|
||||
*aPad ) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// For other shapes, draw polygon outlines
|
||||
SHAPE_POLY_SET corners;
|
||||
|
||||
const int segcountforcircle = GetNrSegmentsCircle( glm::min( aPad->GetSize().x,
|
||||
aPad->GetSize().y) );
|
||||
|
||||
const double correctionFactor = GetCircleCorrectionFactor( segcountforcircle );
|
||||
|
||||
aPad->BuildPadShapePolygon( corners, wxSize( 0, 0 ),
|
||||
// This two factors are only expected to be used if render an oval
|
||||
segcountforcircle, correctionFactor );
|
||||
|
||||
|
||||
// Add outlines as thick segments in polygon buffer
|
||||
|
||||
const SHAPE_LINE_CHAIN& path = corners.COutline( 0 );
|
||||
|
||||
for( int j = 0; j < path.PointCount(); j++ )
|
||||
{
|
||||
const VECTOR2I& a = path.CPoint( j );
|
||||
const VECTOR2I& b = path.CPoint( j + 1 );
|
||||
|
||||
SFVEC2F start3DU( a.x * m_biuTo3Dunits, -a.y * m_biuTo3Dunits );
|
||||
SFVEC2F end3DU ( b.x * m_biuTo3Dunits, -b.y * m_biuTo3Dunits );
|
||||
|
||||
if( Is_segment_a_circle( start3DU, end3DU ) )
|
||||
{
|
||||
aDstContainer->Add( new CFILLEDCIRCLE2D( start3DU,
|
||||
(aWidth / 2) * m_biuTo3Dunits,
|
||||
*aPad ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
aDstContainer->Add( new CROUNDSEGMENT2D( start3DU, end3DU,
|
||||
aWidth * m_biuTo3Dunits,
|
||||
*aPad ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,243 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file create_layer_poly.cpp
|
||||
* @brief This file implements the creation of the pcb board items in the poly
|
||||
* contours format. It is based on the function found in the files:
|
||||
* board_items_to_polygon_shape_transform.cpp
|
||||
* board_items_to_polygon_shape_transform.cpp
|
||||
*/
|
||||
|
||||
#include "cinfo3d_visu.h"
|
||||
#include <convert_basic_shapes_to_polygon.h>
|
||||
#include <class_edge_mod.h>
|
||||
#include <class_module.h>
|
||||
|
||||
|
||||
// This is the same function as in board_items_to_polygon_shape_transform.cpp
|
||||
// but it adds the rect/trapezoid shapes with a different winding
|
||||
void CINFO3D_VISU::buildPadShapePolygon( const D_PAD* aPad,
|
||||
SHAPE_POLY_SET& aCornerBuffer,
|
||||
wxSize aInflateValue,
|
||||
int aSegmentsPerCircle,
|
||||
double aCorrectionFactor ) const
|
||||
{
|
||||
wxPoint corners[4];
|
||||
wxPoint PadShapePos = aPad->ShapePos(); /* Note: for pad having a shape offset,
|
||||
* the pad position is NOT the shape position */
|
||||
switch( aPad->GetShape() )
|
||||
{
|
||||
case PAD_SHAPE_CIRCLE:
|
||||
case PAD_SHAPE_OVAL:
|
||||
case PAD_SHAPE_ROUNDRECT:
|
||||
{
|
||||
// We are using TransformShapeWithClearanceToPolygon to build the shape.
|
||||
// Currently, this method uses only the same inflate value for X and Y dirs.
|
||||
// so because here this is not the case, we use a inflated dummy pad to build
|
||||
// the polygonal shape
|
||||
// TODO: remove this dummy pad when TransformShapeWithClearanceToPolygon will use
|
||||
// a wxSize to inflate the pad size
|
||||
D_PAD dummy( *aPad );
|
||||
wxSize new_size = aPad->GetSize() + aInflateValue + aInflateValue;
|
||||
dummy.SetSize( new_size );
|
||||
dummy.TransformShapeWithClearanceToPolygon( aCornerBuffer, 0,
|
||||
aSegmentsPerCircle, aCorrectionFactor );
|
||||
}
|
||||
break;
|
||||
|
||||
case PAD_SHAPE_TRAPEZOID:
|
||||
case PAD_SHAPE_RECT:
|
||||
{
|
||||
SHAPE_LINE_CHAIN aLineChain;
|
||||
|
||||
aPad->BuildPadPolygon( corners, aInflateValue, aPad->GetOrientation() );
|
||||
|
||||
for( int ii = 0; ii < 4; ++ii )
|
||||
{
|
||||
corners[3-ii] += PadShapePos; // Shift origin to position
|
||||
aLineChain.Append( corners[3-ii].x, corners[3-ii].y );
|
||||
}
|
||||
|
||||
aLineChain.SetClosed( true );
|
||||
|
||||
aCornerBuffer.AddOutline( aLineChain );
|
||||
}
|
||||
break;
|
||||
|
||||
case PAD_SHAPE_CUSTOM:
|
||||
{
|
||||
SHAPE_POLY_SET polyList; // Will contain the pad outlines in board coordinates
|
||||
polyList.Append( aPad->GetCustomShapeAsPolygon() );
|
||||
aPad->CustomShapeAsPolygonToBoardPosition( &polyList, aPad->ShapePos(), aPad->GetOrientation() );
|
||||
aCornerBuffer.Append( polyList );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CINFO3D_VISU::buildPadShapeThickOutlineAsPolygon( const D_PAD* aPad,
|
||||
SHAPE_POLY_SET& aCornerBuffer,
|
||||
int aWidth ) const
|
||||
{
|
||||
if( aPad->GetShape() == PAD_SHAPE_CIRCLE ) // Draw a ring
|
||||
{
|
||||
unsigned int nr_sides_per_circle = GetNrSegmentsCircle( ( aPad->GetSize().x / 2 +
|
||||
aWidth / 2 ) * 2 );
|
||||
|
||||
TransformRingToPolygon( aCornerBuffer, aPad->ShapePos(),
|
||||
aPad->GetSize().x / 2, nr_sides_per_circle, aWidth );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// For other shapes, draw polygon outlines
|
||||
SHAPE_POLY_SET corners;
|
||||
|
||||
unsigned int nr_sides_per_circle = GetNrSegmentsCircle( glm::min( aPad->GetSize().x,
|
||||
aPad->GetSize().y) );
|
||||
buildPadShapePolygon( aPad, corners, wxSize( 0, 0 ),
|
||||
nr_sides_per_circle,
|
||||
GetCircleCorrectionFactor( nr_sides_per_circle ) );
|
||||
|
||||
// Add outlines as thick segments in polygon buffer
|
||||
|
||||
const SHAPE_LINE_CHAIN& path = corners.COutline( 0 );
|
||||
|
||||
for( int ii = 0; ii < path.PointCount(); ++ii )
|
||||
{
|
||||
const VECTOR2I& a = path.CPoint( ii );
|
||||
const VECTOR2I& b = path.CPoint( ii + 1 );
|
||||
|
||||
TransformRoundedEndsSegmentToPolygon( aCornerBuffer,
|
||||
wxPoint( a.x, a.y ),
|
||||
wxPoint( b.x, b.y ),
|
||||
nr_sides_per_circle,
|
||||
aWidth );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Based on the same function name in board_items_to_polyshape_transform.cpp
|
||||
// It was implemented here to allow dynamic segments count per pad shape
|
||||
void CINFO3D_VISU::transformPadsShapesWithClearanceToPolygon( const DLIST<D_PAD>& aPads, PCB_LAYER_ID aLayer,
|
||||
SHAPE_POLY_SET& aCornerBuffer,
|
||||
int aInflateValue,
|
||||
bool aSkipNPTHPadsWihNoCopper ) const
|
||||
{
|
||||
const D_PAD* pad = aPads;
|
||||
|
||||
wxSize margin;
|
||||
for( ; pad != NULL; pad = pad->Next() )
|
||||
{
|
||||
if( !pad->IsOnLayer(aLayer) )
|
||||
continue;
|
||||
|
||||
// NPTH pads are not drawn on layers if the shape size and pos is the same
|
||||
// as their hole:
|
||||
if( aSkipNPTHPadsWihNoCopper && (pad->GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED) )
|
||||
{
|
||||
if( (pad->GetDrillSize() == pad->GetSize()) &&
|
||||
(pad->GetOffset() == wxPoint( 0, 0 )) )
|
||||
{
|
||||
switch( pad->GetShape() )
|
||||
{
|
||||
case PAD_SHAPE_CIRCLE:
|
||||
if( pad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
|
||||
continue;
|
||||
break;
|
||||
|
||||
case PAD_SHAPE_OVAL:
|
||||
if( pad->GetDrillShape() != PAD_DRILL_SHAPE_CIRCLE )
|
||||
continue;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch( aLayer )
|
||||
{
|
||||
case F_Mask:
|
||||
case B_Mask:
|
||||
margin.x = margin.y = pad->GetSolderMaskMargin() + aInflateValue;
|
||||
break;
|
||||
|
||||
case F_Paste:
|
||||
case B_Paste:
|
||||
margin = pad->GetSolderPasteMargin();
|
||||
margin.x += aInflateValue;
|
||||
margin.y += aInflateValue;
|
||||
break;
|
||||
|
||||
default:
|
||||
margin.x = margin.y = aInflateValue;
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned int aCircleToSegmentsCount = GetNrSegmentsCircle( pad->GetSize().x );
|
||||
double aCorrectionFactor = GetCircleCorrectionFactor( aCircleToSegmentsCount );
|
||||
|
||||
buildPadShapePolygon( pad, aCornerBuffer, margin,
|
||||
aCircleToSegmentsCount, aCorrectionFactor );
|
||||
}
|
||||
}
|
||||
|
||||
void CINFO3D_VISU::transformGraphicModuleEdgeToPolygonSet( const MODULE *aModule,
|
||||
PCB_LAYER_ID aLayer,
|
||||
SHAPE_POLY_SET& aCornerBuffer ) const
|
||||
{
|
||||
for( const EDA_ITEM* item = aModule->GraphicalItemsList();
|
||||
item != NULL;
|
||||
item = item->Next() )
|
||||
{
|
||||
switch( item->Type() )
|
||||
{
|
||||
case PCB_MODULE_EDGE_T:
|
||||
{
|
||||
EDGE_MODULE*outline = (EDGE_MODULE*) item;
|
||||
|
||||
if( outline->GetLayer() != aLayer )
|
||||
break;
|
||||
|
||||
unsigned int aCircleToSegmentsCount =
|
||||
GetNrSegmentsCircle( outline->GetBoundingBox().GetSizeMax() );
|
||||
|
||||
double aCorrectionFactor = GetCircleCorrectionFactor( aCircleToSegmentsCount );
|
||||
|
||||
outline->TransformShapeWithClearanceToPolygon( aCornerBuffer,
|
||||
0,
|
||||
aCircleToSegmentsCount,
|
||||
aCorrectionFactor );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,293 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file eda_3d_canvas.h
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef EDA_3D_CANVAS_H
|
||||
#define EDA_3D_CANVAS_H
|
||||
|
||||
|
||||
#include "cinfo3d_visu.h"
|
||||
#include "3d_rendering/c3d_render_base.h"
|
||||
#include "3d_rendering/3d_render_ogl_legacy/c3d_render_ogl_legacy.h"
|
||||
#include "3d_rendering/3d_render_raytracing/c3d_render_raytracing.h"
|
||||
#include "3d_cache/3d_cache.h"
|
||||
#include <gal/hidpi_gl_canvas.h>
|
||||
#include <wx/clipbrd.h>
|
||||
#include <wx/dataobj.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/wupdlock.h>
|
||||
#include <wx/timer.h>
|
||||
#include <wx/statusbr.h>
|
||||
#include <pcb_base_frame.h>
|
||||
|
||||
|
||||
/**
|
||||
* Implement a canvas based on a wxGLCanvas
|
||||
*/
|
||||
class EDA_3D_CANVAS : public HIDPI_GL_CANVAS
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* @brief EDA_3D_CANVAS - Creates a new 3D Canvas with a attribute list
|
||||
* @param aParent: the parent creator of this canvas
|
||||
* @param aAttribList: a list of openGL options created by GetOpenGL_AttributesList
|
||||
* @param aBoard: The board
|
||||
* @param aSettings: the settings options to be used by this canvas
|
||||
*/
|
||||
EDA_3D_CANVAS( wxWindow *aParent,
|
||||
const int *aAttribList = 0,
|
||||
BOARD *aBoard = NULL,
|
||||
CINFO3D_VISU &aSettings = G_null_CINFO3D_VISU,
|
||||
S3D_CACHE *a3DCachePointer = NULL );
|
||||
|
||||
~EDA_3D_CANVAS();
|
||||
|
||||
void SetStatusBar( wxStatusBar *aStatusBar ) { m_parentStatusBar = aStatusBar; }
|
||||
|
||||
void ReloadRequest( BOARD *aBoard = NULL, S3D_CACHE *aCachePointer = NULL );
|
||||
|
||||
/**
|
||||
* @brief IsReloadRequestPending - Query if there is a pending reload request
|
||||
* @return true if it wants to reload, false if there is no reload pending
|
||||
*/
|
||||
bool IsReloadRequestPending() const
|
||||
{
|
||||
if( m_3d_render )
|
||||
return m_3d_render->IsReloadRequestPending();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RenderRaytracingRequest - Request to render the current view in Raytracing mode
|
||||
*/
|
||||
void RenderRaytracingRequest();
|
||||
|
||||
/**
|
||||
* Request a screenshot and output it to the aDstImage
|
||||
* @param aDstImage - Screenshot destination image
|
||||
*/
|
||||
void GetScreenshot( wxImage &aDstImage );
|
||||
|
||||
/**
|
||||
* @brief SetView3D - Helper function to call view commands
|
||||
* @param aKeycode: ascii key commands
|
||||
* @return true if the key code was handled,
|
||||
* false if no command found for this code.
|
||||
*/
|
||||
bool SetView3D( int aKeycode );
|
||||
|
||||
/**
|
||||
* @brief RenderEngineChanged - Notify that the render engine was changed
|
||||
*/
|
||||
void RenderEngineChanged();
|
||||
|
||||
/**
|
||||
* @brief DisplayStatus - Update the status bar with the position information
|
||||
*/
|
||||
void DisplayStatus();
|
||||
|
||||
/**
|
||||
* @brief Request_refresh - Schedule a refresh update of the canvas
|
||||
* @param aRedrawImmediately - true will request a redraw, false will
|
||||
* schedule a redraw, after a short timeout.
|
||||
*/
|
||||
void Request_refresh( bool aRedrawImmediately = true );
|
||||
|
||||
void OnKeyEvent( wxKeyEvent& event );
|
||||
|
||||
bool SupportsRayTracing() const { return m_opengl_supports_raytracing; }
|
||||
|
||||
bool IsOpenGLInitialized() const { return m_is_opengl_initialized; }
|
||||
|
||||
/**
|
||||
* Return a structure containing currently used hotkey mapping.
|
||||
*/
|
||||
EDA_HOTKEY_CONFIG* GetHotkeyConfig() const;
|
||||
|
||||
private:
|
||||
|
||||
void OnPaint( wxPaintEvent &event );
|
||||
|
||||
void OnEraseBackground( wxEraseEvent &event );
|
||||
|
||||
void OnMouseWheel( wxMouseEvent &event );
|
||||
|
||||
#if wxCHECK_VERSION( 3, 1, 0 ) || defined( USE_OSX_MAGNIFY_EVENT )
|
||||
void OnMagnify( wxMouseEvent& event );
|
||||
#endif
|
||||
|
||||
void OnMouseMove( wxMouseEvent &event );
|
||||
|
||||
void OnLeftDown( wxMouseEvent &event );
|
||||
|
||||
void OnLeftUp( wxMouseEvent &event );
|
||||
|
||||
void OnMiddleUp( wxMouseEvent &event );
|
||||
|
||||
void OnMiddleDown( wxMouseEvent &event );
|
||||
|
||||
void OnRightClick( wxMouseEvent &event );
|
||||
|
||||
void OnPopUpMenu( wxCommandEvent &event );
|
||||
|
||||
void OnCharHook( wxKeyEvent& event );
|
||||
|
||||
void OnTimerTimeout_Editing( wxTimerEvent& event );
|
||||
|
||||
/**
|
||||
* @brief OnCloseWindow - called when the frame is closed
|
||||
* @param event
|
||||
*/
|
||||
void OnCloseWindow( wxCloseEvent &event );
|
||||
|
||||
void OnResize( wxSizeEvent &event );
|
||||
|
||||
void OnTimerTimeout_Redraw( wxTimerEvent& event );
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief stop_editingTimeOut_Timer - stop the editing time, so it will not timeout
|
||||
*/
|
||||
void stop_editingTimeOut_Timer();
|
||||
|
||||
|
||||
/**
|
||||
* @brief restart_editingTimeOut_Timer - reset the editing timer
|
||||
*/
|
||||
void restart_editingTimeOut_Timer();
|
||||
|
||||
|
||||
/**
|
||||
* @brief request_start_moving_camera - start a camera movement
|
||||
* @param aMovingSpeed: the time speed
|
||||
* @param aRenderPivot: if it should display pivot cursor while move
|
||||
*/
|
||||
void request_start_moving_camera( float aMovingSpeed = 2.0f,
|
||||
bool aRenderPivot = true );
|
||||
|
||||
|
||||
/**
|
||||
* @brief move_pivot_based_on_cur_mouse_position -
|
||||
* This function hits a ray to the board and start a moviment
|
||||
*/
|
||||
void move_pivot_based_on_cur_mouse_position();
|
||||
|
||||
|
||||
/**
|
||||
* @brief render_pivot - render the pivot cursor
|
||||
* @param t: time between 0.0 and 1.0
|
||||
* @param aScale: scale to apply on the cursor
|
||||
*/
|
||||
void render_pivot( float t, float aScale );
|
||||
|
||||
/**
|
||||
* @brief initializeOpenGL
|
||||
* @return if OpenGL initialization succeed
|
||||
*/
|
||||
bool initializeOpenGL();
|
||||
|
||||
/**
|
||||
* @brief releaseOpenGL - free created targets and openGL context
|
||||
*/
|
||||
void releaseOpenGL();
|
||||
|
||||
private:
|
||||
|
||||
/// current OpenGL context
|
||||
wxGLContext *m_glRC;
|
||||
|
||||
/// Parent statusbar to report progress
|
||||
wxStatusBar *m_parentStatusBar;
|
||||
|
||||
/// Time timeout will expires after some time sinalizing that the mouse /
|
||||
/// keyboard movements are over.
|
||||
wxTimer m_editing_timeout_timer;
|
||||
|
||||
/// This timer will be used to schedule a redraw event
|
||||
wxTimer m_redraw_trigger_timer;
|
||||
|
||||
/// true if mouse activity is on progress
|
||||
bool m_mouse_is_moving;
|
||||
|
||||
/// true if there was some type of activity, it will be used to render in
|
||||
/// preview mode
|
||||
bool m_mouse_was_moved;
|
||||
|
||||
/// true if camera animation is ongoing
|
||||
bool m_camera_is_moving;
|
||||
|
||||
/// activated the render of pivot while camera moving
|
||||
bool m_render_pivot;
|
||||
|
||||
/// 1.0f will be 1:1
|
||||
float m_camera_moving_speed;
|
||||
|
||||
/// Stores the ticktime when the camera star its movement
|
||||
unsigned m_strtime_camera_movement;
|
||||
|
||||
/// Stores all pre-computed 3D information and visualization settings to render the board
|
||||
CINFO3D_VISU &m_settings;
|
||||
|
||||
/// The current render in used for this canvas
|
||||
C3D_RENDER_BASE *m_3d_render;
|
||||
|
||||
/// Raytracing render class
|
||||
C3D_RENDER_RAYTRACING *m_3d_render_raytracing;
|
||||
|
||||
/// OpenGL legacy render class
|
||||
C3D_RENDER_OGL_LEGACY *m_3d_render_ogl_legacy;
|
||||
|
||||
/// Flag to store if opengl was initialized already
|
||||
bool m_is_opengl_initialized;
|
||||
|
||||
/// Step factor to used with cursor on relation to the current zoom
|
||||
static const float m_delta_move_step_factor;
|
||||
|
||||
/// Flags that the user requested the current view to be render with raytracing
|
||||
bool m_render_raytracing_was_requested;
|
||||
|
||||
bool m_opengl_supports_raytracing;
|
||||
|
||||
/**
|
||||
* Trace mask used to enable or disable the trace output of this class.
|
||||
* The debug output can be turned on by setting the WXTRACE environment variable to
|
||||
* "KI_TRACE_EDA_3D_CANVAS". See the wxWidgets documentation on wxLogTrace for
|
||||
* more information.
|
||||
*/
|
||||
static const wxChar *m_logTrace;
|
||||
};
|
||||
|
||||
|
||||
#endif // EDA_3D_CANVAS_H
|
||||
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file eda_3d_canvas_pivot.cpp
|
||||
* @brief Implementation of a 3d cursor
|
||||
*/
|
||||
|
||||
#include "../common_ogl/openGL_includes.h"
|
||||
#include "../common_ogl/ogl_utils.h"
|
||||
#include "eda_3d_canvas.h"
|
||||
|
||||
|
||||
static void pivot_render_triangles( float t )
|
||||
{
|
||||
wxASSERT( t >= 0.0f );
|
||||
|
||||
SFVEC3F vertexPointer[12];
|
||||
|
||||
const float u = 1.0f / 6.0f;
|
||||
|
||||
vertexPointer[0] = SFVEC3F( (-3.0f + t) * u, -2.0f * u, 0.0f );
|
||||
vertexPointer[1] = SFVEC3F( (-3.0f + t) * u, 2.0f * u, 0.0f );
|
||||
vertexPointer[2] = SFVEC3F( (-1.0f + t) * u, 0.0f * u, 0.0f );
|
||||
|
||||
vertexPointer[3] = SFVEC3F( -2.0f * u, (-3.0f + t) * u, 0.0f );
|
||||
vertexPointer[4] = SFVEC3F( 2.0f * u, (-3.0f + t) * u, 0.0f );
|
||||
vertexPointer[5] = SFVEC3F( 0.0f * u, (-1.0f + t) * u, 0.0f );
|
||||
|
||||
vertexPointer[6] = SFVEC3F( (3.0f - t) * u, -2.0f * u, 0.0f );
|
||||
vertexPointer[7] = SFVEC3F( (3.0f - t) * u, 2.0f * u, 0.0f );
|
||||
vertexPointer[8] = SFVEC3F( (1.0f - t) * u, 0.0f * u, 0.0f );
|
||||
|
||||
vertexPointer[9] = SFVEC3F( 2.0f * u, (3.0f - t) * u, 0.0f );
|
||||
vertexPointer[10] = SFVEC3F( -2.0f * u, (3.0f - t) * u, 0.0f );
|
||||
vertexPointer[11] = SFVEC3F( 0.0f * u, (1.0f - t) * u, 0.0f );
|
||||
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
glDisableClientState( GL_COLOR_ARRAY );
|
||||
glDisableClientState( GL_NORMAL_ARRAY );
|
||||
glEnableClientState( GL_VERTEX_ARRAY );
|
||||
glVertexPointer( 3, GL_FLOAT, 0, vertexPointer );
|
||||
|
||||
glEnable( GL_BLEND );
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
|
||||
glDrawArrays( GL_TRIANGLES, 0, 4 * 3 );
|
||||
|
||||
glDisable( GL_BLEND );
|
||||
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_CANVAS::render_pivot( float t , float aScale )
|
||||
{
|
||||
wxASSERT( aScale >= 0.0f );
|
||||
wxASSERT( t >= 0.0f );
|
||||
|
||||
if( t > 1.0f )
|
||||
t = 1.0f;
|
||||
|
||||
const SFVEC3F &lookAtPos = m_settings.CameraGet().GetLookAtPos_T1();
|
||||
|
||||
glDisable( GL_LIGHTING );
|
||||
glDisable( GL_DEPTH_TEST );
|
||||
glDisable( GL_CULL_FACE );
|
||||
|
||||
// Set projection and modelview matrixes
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glLoadMatrixf( glm::value_ptr( m_settings.CameraGet().GetProjectionMatrix() ) );
|
||||
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glLoadIdentity();
|
||||
glLoadMatrixf( glm::value_ptr( m_settings.CameraGet().GetViewMatrix() ) );
|
||||
|
||||
glEnable( GL_COLOR_MATERIAL );
|
||||
glColor4f( 0.0f, 1.0f, 0.0f, 0.75f - t * 0.75f );
|
||||
|
||||
// Translate to the look at position
|
||||
glTranslatef( lookAtPos.x, lookAtPos.y, lookAtPos.z );
|
||||
|
||||
glScalef( aScale, aScale, aScale );
|
||||
|
||||
pivot_render_triangles( t * 0.5f );
|
||||
|
||||
t = t * 0.80f;
|
||||
glScalef( 1.0f - t, 1.0f - t, 1.0f - t );
|
||||
glColor4f( 0.0f, 1.0f, 0.0f, 0.8f - t );
|
||||
|
||||
glPushMatrix();
|
||||
glRotatef( t * 90.0f, 0.0f, 0.0f, 1.0f );
|
||||
pivot_render_triangles( t * 0.5f );
|
||||
glPopMatrix();
|
||||
|
||||
glPushMatrix();
|
||||
glRotatef( -t * 90.0f, 0.0f, 0.0f, 1.0f );
|
||||
pivot_render_triangles( t * 0.5f );
|
||||
glPopMatrix();
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file status_text_reporter.h
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef STATUS_TEXT_REPORTER_H_
|
||||
#define STATUS_TEXT_REPORTER_H_
|
||||
|
||||
#include <reporter.h>
|
||||
|
||||
/**
|
||||
* Class STATUS_TEXT_REPORTER
|
||||
* is a wrapper for reporting to a wxString in a wxFrame status text.
|
||||
*/
|
||||
class STATUS_TEXT_REPORTER : public REPORTER
|
||||
{
|
||||
private:
|
||||
wxStatusBar *m_parentStatusBar;
|
||||
int m_position;
|
||||
bool m_hasMessage;
|
||||
|
||||
public:
|
||||
STATUS_TEXT_REPORTER( wxStatusBar* aParentStatusBar, int aPosition = 0 ) :
|
||||
REPORTER(),
|
||||
m_parentStatusBar( aParentStatusBar ), m_position( aPosition )
|
||||
{
|
||||
m_hasMessage = false;
|
||||
}
|
||||
|
||||
REPORTER& Report( const wxString& aText, SEVERITY aSeverity = RPT_UNDEFINED ) override
|
||||
{
|
||||
if( !aText.IsEmpty() )
|
||||
m_hasMessage = true;
|
||||
|
||||
if( m_parentStatusBar )
|
||||
m_parentStatusBar->SetStatusText( aText, m_position );
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool HasMessage() const override { return m_hasMessage; }
|
||||
};
|
||||
|
||||
|
||||
#endif // STATUS_TEXT_REPORTER_H_
|
||||
@@ -0,0 +1,179 @@
|
||||
/**
|
||||
* @file 3d_class.cpp
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <fctsys.h>
|
||||
|
||||
#include <3d_viewer.h>
|
||||
|
||||
S3D_MATERIAL::S3D_MATERIAL( S3D_MASTER* father, const wxString& name ) :
|
||||
EDA_ITEM( father, NOT_USED )
|
||||
{
|
||||
m_DiffuseColor.x = m_DiffuseColor.y = m_DiffuseColor.z = 1.0;
|
||||
m_SpecularColor.x = m_SpecularColor.y = m_SpecularColor.z = 1.0;
|
||||
m_AmbientIntensity = 1.0;
|
||||
m_Transparency = 0.0;
|
||||
m_Shininess = 1.0;
|
||||
m_Name = name;
|
||||
}
|
||||
|
||||
void S3D_MATERIAL::SetMaterial()
|
||||
{
|
||||
S3D_MASTER * s3dParent = (S3D_MASTER *) GetParent();
|
||||
s3dParent->SetLastTransparency( m_Transparency );
|
||||
|
||||
if( ! s3dParent->IsOpenGlAllowed() )
|
||||
return;
|
||||
|
||||
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
|
||||
glColor4f( m_DiffuseColor.x * m_AmbientIntensity,
|
||||
m_DiffuseColor.y * m_AmbientIntensity,
|
||||
m_DiffuseColor.z * m_AmbientIntensity,
|
||||
1.0 - m_Transparency );
|
||||
#if 0
|
||||
glColorMaterial( GL_FRONT_AND_BACK, GL_SPECULAR );
|
||||
glColor3f( m_SpecularColor.x, m_SpecularColor.y, m_SpecularColor.z );
|
||||
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
|
||||
#endif
|
||||
}
|
||||
|
||||
bool S3D_MASTER::IsOpenGlAllowed()
|
||||
{
|
||||
if( m_loadNonTransparentObjects ) // return true for non transparent objects only
|
||||
{
|
||||
if( m_lastTransparency == 0.0 )
|
||||
return true;
|
||||
}
|
||||
if( m_loadTransparentObjects ) // return true for transparent objects only
|
||||
if( m_lastTransparency != 0.0 )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void S3D_MASTER::Insert( S3D_MATERIAL* aMaterial )
|
||||
{
|
||||
aMaterial->SetNext( m_Materials );
|
||||
m_Materials = aMaterial;
|
||||
}
|
||||
|
||||
|
||||
void S3D_MASTER::Copy( S3D_MASTER* pattern )
|
||||
{
|
||||
SetShape3DName( pattern->GetShape3DName() );
|
||||
m_MatScale = pattern->m_MatScale;
|
||||
m_MatRotation = pattern->m_MatRotation;
|
||||
m_MatPosition = pattern->m_MatPosition;
|
||||
m_3D_Drawings = NULL;
|
||||
m_Materials = NULL;
|
||||
}
|
||||
|
||||
|
||||
S3D_MASTER::S3D_MASTER( EDA_ITEM* aParent ) :
|
||||
EDA_ITEM( aParent, NOT_USED )
|
||||
{
|
||||
m_MatScale.x = m_MatScale.y = m_MatScale.z = 1.0;
|
||||
m_lastTransparency = 0.0;
|
||||
m_3D_Drawings = NULL;
|
||||
m_Materials = NULL;
|
||||
m_ShapeType = FILE3D_NONE;
|
||||
}
|
||||
|
||||
|
||||
S3D_MASTER:: ~S3D_MASTER()
|
||||
{
|
||||
STRUCT_3D_SHAPE* next;
|
||||
S3D_MATERIAL* nextmat;
|
||||
|
||||
for( ; m_3D_Drawings != NULL; m_3D_Drawings = next )
|
||||
{
|
||||
next = m_3D_Drawings->Next();
|
||||
delete m_3D_Drawings;
|
||||
}
|
||||
|
||||
for( ; m_Materials != NULL; m_Materials = nextmat )
|
||||
{
|
||||
nextmat = m_Materials->Next();
|
||||
delete m_Materials;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool S3D_MASTER::Is3DType( enum FILE3D_TYPE aShapeType )
|
||||
{
|
||||
// type 'none' is not valid and will always return false
|
||||
if( aShapeType == FILE3D_NONE )
|
||||
return false;
|
||||
|
||||
// no one is interested if we have no file
|
||||
if( m_Shape3DName.empty() )
|
||||
return false;
|
||||
|
||||
if( aShapeType == m_ShapeType )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void S3D_MASTER::SetShape3DName( const wxString& aShapeName )
|
||||
{
|
||||
m_ShapeType = FILE3D_NONE;
|
||||
m_Shape3DName = aShapeName;
|
||||
|
||||
if( m_Shape3DName.empty() )
|
||||
return;
|
||||
|
||||
wxFileName fn = m_Shape3DName;
|
||||
wxString ext = fn.GetExt();
|
||||
|
||||
if( ext == wxT( "wrl" ) || ext == wxT( "x3d" ) )
|
||||
m_ShapeType = FILE3D_VRML;
|
||||
else if( ext == wxT( "idf" ) )
|
||||
m_ShapeType = FILE3D_IDF;
|
||||
else
|
||||
m_ShapeType = FILE3D_UNKNOWN;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
STRUCT_3D_SHAPE::STRUCT_3D_SHAPE( EDA_ITEM* aParent ) :
|
||||
EDA_ITEM( aParent, NOT_USED )
|
||||
{
|
||||
m_3D_Coord = NULL;
|
||||
m_3D_CoordIndex = NULL;
|
||||
m_3D_Points = 0;
|
||||
}
|
||||
|
||||
|
||||
STRUCT_3D_SHAPE:: ~STRUCT_3D_SHAPE()
|
||||
{
|
||||
delete m_3D_Coord;
|
||||
delete m_3D_CoordIndex;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,419 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2012 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_draw_basic_functions.cpp
|
||||
*/
|
||||
|
||||
#include <fctsys.h>
|
||||
#include <trigo.h>
|
||||
#include <convert_basic_shapes_to_polygon.h>
|
||||
|
||||
#include <3d_viewer.h>
|
||||
#include <info3d_visu.h>
|
||||
#include <3d_draw_basic_functions.h>
|
||||
|
||||
// Imported function:
|
||||
extern void TransfertToGLlist( std::vector<S3D_VERTEX>& aVertices, double aBiuTo3DUnits );
|
||||
extern void CheckGLError();
|
||||
|
||||
// Number of segments to approximate a circle by segments
|
||||
#define SEGM_PER_CIRCLE 16
|
||||
|
||||
#ifndef CALLBACK
|
||||
#define CALLBACK
|
||||
#endif
|
||||
|
||||
// CALLBACK functions for GLU_TESS
|
||||
static void CALLBACK tessBeginCB( GLenum which );
|
||||
static void CALLBACK tessEndCB();
|
||||
static void CALLBACK tessErrorCB( GLenum errorCode );
|
||||
static void CALLBACK tessCPolyPt2Vertex( const GLvoid* data );
|
||||
|
||||
// 2 helper functions to set the current normal vector for gle items
|
||||
static inline void SetNormalZpos()
|
||||
{
|
||||
glNormal3f( 0.0, 0.0, 1.0 );
|
||||
}
|
||||
|
||||
static inline void SetNormalZneg()
|
||||
{
|
||||
glNormal3f( 0.0, 0.0, -1.0 );
|
||||
}
|
||||
|
||||
|
||||
/* Draw3D_VerticalPolygonalCylinder is a helper function.
|
||||
*
|
||||
* draws a "vertical cylinder" having a polygon shape
|
||||
* from Z position = aZpos to aZpos + aHeight
|
||||
* Used to create the vertical sides of 3D horizontal shapes with thickness.
|
||||
*/
|
||||
static void Draw3D_VerticalPolygonalCylinder( const CPOLYGONS_LIST& aPolysList,
|
||||
int aHeight, int aZpos,
|
||||
bool aInside, double aBiuTo3DUnits )
|
||||
{
|
||||
if( aHeight == 0 )
|
||||
return;
|
||||
|
||||
std::vector<S3D_VERTEX> coords;
|
||||
coords.resize( 4 );
|
||||
|
||||
// Init Z position of the 4 points of a GL_QUAD
|
||||
if( aInside )
|
||||
{
|
||||
coords[0].z = aZpos;
|
||||
coords[1].z = aZpos + aHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
coords[0].z = aZpos + aHeight;
|
||||
coords[1].z = aZpos;
|
||||
}
|
||||
coords[2].z = coords[1].z;
|
||||
coords[3].z = coords[0].z;
|
||||
|
||||
// Draw the vertical polygonal side
|
||||
int startContour = 0;
|
||||
for( unsigned ii = 0; ii < aPolysList.GetCornersCount(); ii++ )
|
||||
{
|
||||
unsigned jj = ii + 1;
|
||||
|
||||
if( aPolysList.IsEndContour( ii ) || jj >= aPolysList.GetCornersCount() )
|
||||
{
|
||||
jj = startContour;
|
||||
startContour = ii + 1;
|
||||
}
|
||||
|
||||
// Build the 4 vertices of each GL_QUAD
|
||||
coords[0].x = aPolysList.GetX( ii );
|
||||
coords[0].y = -aPolysList.GetY( ii );
|
||||
coords[1].x = coords[0].x;
|
||||
coords[1].y = coords[0].y; // only z change
|
||||
coords[2].x = aPolysList.GetX( jj );
|
||||
coords[2].y = -aPolysList.GetY( jj );
|
||||
coords[3].x = coords[2].x;
|
||||
coords[3].y = coords[2].y; // only z change
|
||||
|
||||
// Creates the GL_QUAD
|
||||
TransfertToGLlist( coords, aBiuTo3DUnits );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SetGLColor( EDA_COLOR_T color, double alpha )
|
||||
{
|
||||
double red, green, blue;
|
||||
const StructColors &colordata = g_ColorRefs[ColorGetBase( color )];
|
||||
|
||||
red = colordata.m_Red / 255.0;
|
||||
blue = colordata.m_Blue / 255.0;
|
||||
green = colordata.m_Green / 255.0;
|
||||
glColor4f( red, green, blue, alpha );
|
||||
}
|
||||
|
||||
|
||||
/* draw all solid polygons found in aPolysList
|
||||
* aZpos = z position in board internal units
|
||||
* aThickness = thickness in board internal units
|
||||
* If aThickness = 0, a polygon area is drawn in a XY plane at Z position = aZpos.
|
||||
* If aThickness > 0, a solid object is drawn.
|
||||
* The top side is located at aZpos + aThickness / 2
|
||||
* The bottom side is located at aZpos - aThickness / 2
|
||||
*/
|
||||
void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList,
|
||||
int aZpos, int aThickness, double aBiuTo3DUnits )
|
||||
{
|
||||
GLUtesselator* tess = gluNewTess();
|
||||
|
||||
gluTessCallback( tess, GLU_TESS_BEGIN, ( void (CALLBACK*) () )tessBeginCB );
|
||||
gluTessCallback( tess, GLU_TESS_END, ( void (CALLBACK*) () )tessEndCB );
|
||||
gluTessCallback( tess, GLU_TESS_ERROR, ( void (CALLBACK*) () )tessErrorCB );
|
||||
gluTessCallback( tess, GLU_TESS_VERTEX, ( void (CALLBACK*) () )tessCPolyPt2Vertex );
|
||||
|
||||
GLdouble v_data[3];
|
||||
double zpos = ( aZpos + (aThickness / 2) ) * aBiuTo3DUnits;
|
||||
g_Parm_3D_Visu.m_CurrentZpos = zpos;
|
||||
v_data[2] = aZpos + (aThickness / 2);
|
||||
|
||||
// Set normal to toward positive Z axis, for a solid object only (to draw the top side)
|
||||
if( aThickness )
|
||||
SetNormalZpos();
|
||||
|
||||
// gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
|
||||
|
||||
// Draw solid areas contained in this list
|
||||
CPOLYGONS_LIST polylist = aPolysList; // temporary copy for gluTessVertex
|
||||
|
||||
for( int side = 0; side < 2; side++ )
|
||||
{
|
||||
int startContour = 1;
|
||||
|
||||
for( unsigned ii = 0; ii < polylist.GetCornersCount(); ii++ )
|
||||
{
|
||||
if( startContour == 1 )
|
||||
{
|
||||
gluTessBeginPolygon( tess, NULL );
|
||||
gluTessBeginContour( tess );
|
||||
startContour = 0;
|
||||
}
|
||||
|
||||
v_data[0] = polylist.GetX( ii ) * aBiuTo3DUnits;
|
||||
v_data[1] = -polylist.GetY( ii ) * aBiuTo3DUnits;
|
||||
// gluTessVertex store pointers on data, not data, so do not store
|
||||
// different corners values in a temporary variable
|
||||
// but send pointer on each CPolyPt value in polylist
|
||||
// before calling gluDeleteTess
|
||||
gluTessVertex( tess, v_data, &polylist[ii] );
|
||||
|
||||
if( polylist.IsEndContour( ii ) )
|
||||
{
|
||||
gluTessEndContour( tess );
|
||||
gluTessEndPolygon( tess );
|
||||
startContour = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if( aThickness == 0 )
|
||||
break;
|
||||
|
||||
// Prepare the bottom side of solid areas
|
||||
zpos = ( aZpos - (aThickness / 2) ) * aBiuTo3DUnits;
|
||||
g_Parm_3D_Visu.m_CurrentZpos = zpos;
|
||||
v_data[2] = zpos;
|
||||
// Now;, set normal to toward negative Z axis, for the solid object bottom side
|
||||
SetNormalZneg();
|
||||
}
|
||||
|
||||
gluDeleteTess( tess );
|
||||
|
||||
if( aThickness == 0 )
|
||||
return;
|
||||
|
||||
// Build the 3D data : vertical side
|
||||
Draw3D_VerticalPolygonalCylinder( polylist, aThickness, aZpos - (aThickness / 2), false, aBiuTo3DUnits );
|
||||
}
|
||||
|
||||
|
||||
/* draw the solid polygon found in aPolysList
|
||||
* The first polygon is the main polygon, others are holes
|
||||
* See Draw3D_SolidHorizontalPolyPolygons for more info
|
||||
*/
|
||||
void Draw3D_SolidHorizontalPolygonWithHoles( const CPOLYGONS_LIST& aPolysList,
|
||||
int aZpos, int aThickness,
|
||||
double aBiuTo3DUnits )
|
||||
{
|
||||
CPOLYGONS_LIST polygon;
|
||||
|
||||
ConvertPolysListWithHolesToOnePolygon( aPolysList, polygon );
|
||||
Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos, aThickness, aBiuTo3DUnits );
|
||||
}
|
||||
|
||||
|
||||
/* draw a cylinder (a tube) using 3D primitives.
|
||||
* the cylinder axis is parallel to the Z axis
|
||||
* If aHeight = height of the cylinder is 0, only one ring will be drawn
|
||||
* If aThickness = 0, only one cylinder will be drawn
|
||||
*/
|
||||
void Draw3D_ZaxisCylinder( wxPoint aCenterPos, int aRadius,
|
||||
int aHeight, int aThickness,
|
||||
int aZpos, double aBiuTo3DUnits )
|
||||
{
|
||||
const int slice = SEGM_PER_CIRCLE;
|
||||
CPOLYGONS_LIST outer_cornerBuffer;
|
||||
|
||||
TransformCircleToPolygon( outer_cornerBuffer, aCenterPos,
|
||||
aRadius + (aThickness / 2), slice );
|
||||
|
||||
std::vector<S3D_VERTEX> coords;
|
||||
coords.resize( 4 );
|
||||
|
||||
CPOLYGONS_LIST inner_cornerBuffer;
|
||||
if( aThickness ) // build the the vertical inner polygon (hole)
|
||||
TransformCircleToPolygon( inner_cornerBuffer, aCenterPos,
|
||||
aRadius - (aThickness / 2), slice );
|
||||
|
||||
if( aHeight )
|
||||
{
|
||||
// Draw the vertical outer side
|
||||
Draw3D_VerticalPolygonalCylinder( outer_cornerBuffer,
|
||||
aHeight, aZpos, false, aBiuTo3DUnits );
|
||||
if( aThickness )
|
||||
// Draws the vertical inner side (hole)
|
||||
Draw3D_VerticalPolygonalCylinder( inner_cornerBuffer,
|
||||
aHeight, aZpos, true, aBiuTo3DUnits );
|
||||
}
|
||||
|
||||
if( aThickness )
|
||||
{
|
||||
// draw top (front) and bottom (back) horizontal sides (rings)
|
||||
SetNormalZpos();
|
||||
outer_cornerBuffer.Append( inner_cornerBuffer );
|
||||
CPOLYGONS_LIST polygon;
|
||||
|
||||
ConvertPolysListWithHolesToOnePolygon( outer_cornerBuffer, polygon );
|
||||
// draw top (front) horizontal ring
|
||||
Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos + aHeight, 0, aBiuTo3DUnits );
|
||||
|
||||
if( aHeight )
|
||||
{
|
||||
// draw bottom (back) horizontal ring
|
||||
SetNormalZneg();
|
||||
Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos, 0, aBiuTo3DUnits );
|
||||
}
|
||||
}
|
||||
|
||||
SetNormalZpos();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function Draw3D_ZaxisOblongCylinder:
|
||||
* draw a segment with an oblong hole.
|
||||
* Used to draw oblong holes
|
||||
* If aHeight = height of the cylinder is 0, only one ring will be drawn
|
||||
* If aThickness = 0, only one cylinder will be drawn
|
||||
*/
|
||||
void Draw3D_ZaxisOblongCylinder( wxPoint aAxis1Pos, wxPoint aAxis2Pos,
|
||||
int aRadius, int aHeight, int aThickness,
|
||||
int aZpos, double aBiuTo3DUnits )
|
||||
{
|
||||
const int slice = SEGM_PER_CIRCLE;
|
||||
|
||||
// Build the points to approximate oblong cylinder by segments
|
||||
CPOLYGONS_LIST outer_cornerBuffer;
|
||||
|
||||
int segm_width = (aRadius * 2) + aThickness;
|
||||
TransformRoundedEndsSegmentToPolygon( outer_cornerBuffer, aAxis1Pos,
|
||||
aAxis2Pos, slice, segm_width );
|
||||
|
||||
// Draw the oblong outer cylinder
|
||||
if( aHeight )
|
||||
Draw3D_VerticalPolygonalCylinder( outer_cornerBuffer, aHeight, aZpos,
|
||||
false, aBiuTo3DUnits );
|
||||
|
||||
if( aThickness )
|
||||
{
|
||||
CPOLYGONS_LIST inner_cornerBuffer;
|
||||
segm_width = aRadius * 2;
|
||||
TransformRoundedEndsSegmentToPolygon( inner_cornerBuffer, aAxis1Pos,
|
||||
aAxis2Pos, slice, segm_width );
|
||||
|
||||
// Draw the oblong inner cylinder
|
||||
if( aHeight )
|
||||
Draw3D_VerticalPolygonalCylinder( inner_cornerBuffer, aHeight,
|
||||
aZpos, true, aBiuTo3DUnits );
|
||||
|
||||
// Build the horizontal full polygon shape
|
||||
// (outer polygon shape - inner polygon shape)
|
||||
outer_cornerBuffer.Append( inner_cornerBuffer );
|
||||
|
||||
CPOLYGONS_LIST polygon;
|
||||
ConvertPolysListWithHolesToOnePolygon( outer_cornerBuffer, polygon );
|
||||
|
||||
// draw top (front) horizontal side (ring)
|
||||
SetNormalZpos();
|
||||
Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos + aHeight, 0, aBiuTo3DUnits );
|
||||
|
||||
if( aHeight )
|
||||
{
|
||||
// draw bottom (back) horizontal side (ring)
|
||||
SetNormalZneg();
|
||||
Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos, 0, aBiuTo3DUnits );
|
||||
}
|
||||
}
|
||||
|
||||
SetNormalZpos();
|
||||
}
|
||||
|
||||
|
||||
/* draw a thick segment using 3D primitives, in a XY plane
|
||||
* wxPoint aStart, wxPoint aEnd = YX position of end in board units
|
||||
* aWidth = width of segment in board units
|
||||
* aThickness = thickness of segment in board units
|
||||
* aZpos = z position of segment in board units
|
||||
*/
|
||||
void Draw3D_SolidSegment( const wxPoint& aStart, const wxPoint& aEnd,
|
||||
int aWidth, int aThickness, int aZpos, double aBiuTo3DUnits )
|
||||
{
|
||||
CPOLYGONS_LIST cornerBuffer;
|
||||
const int slice = SEGM_PER_CIRCLE;
|
||||
|
||||
TransformRoundedEndsSegmentToPolygon( cornerBuffer, aStart, aEnd, slice, aWidth );
|
||||
|
||||
Draw3D_SolidHorizontalPolyPolygons( cornerBuffer, aZpos, aThickness, aBiuTo3DUnits );
|
||||
}
|
||||
|
||||
|
||||
void Draw3D_ArcSegment( const wxPoint& aCenterPos, const wxPoint& aStartPoint,
|
||||
double aArcAngle, int aWidth, int aThickness,
|
||||
int aZpos, double aBiuTo3DUnits )
|
||||
{
|
||||
const int slice = SEGM_PER_CIRCLE;
|
||||
|
||||
CPOLYGONS_LIST cornerBuffer;
|
||||
TransformArcToPolygon( cornerBuffer, aCenterPos, aStartPoint, aArcAngle,
|
||||
slice, aWidth );
|
||||
|
||||
Draw3D_SolidHorizontalPolyPolygons( cornerBuffer, aZpos, aThickness, aBiuTo3DUnits );
|
||||
}
|
||||
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
// GLU_TESS CALLBACKS
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void CALLBACK tessBeginCB( GLenum which )
|
||||
{
|
||||
glBegin( which );
|
||||
}
|
||||
|
||||
|
||||
void CALLBACK tessEndCB()
|
||||
{
|
||||
glEnd();
|
||||
}
|
||||
|
||||
|
||||
void CALLBACK tessCPolyPt2Vertex( const GLvoid* data )
|
||||
{
|
||||
// cast back to double type
|
||||
const CPolyPt* ptr = (const CPolyPt*) data;
|
||||
|
||||
glVertex3d( ptr->x * g_Parm_3D_Visu.m_BiuTo3Dunits,
|
||||
-ptr->y * g_Parm_3D_Visu.m_BiuTo3Dunits,
|
||||
g_Parm_3D_Visu.m_CurrentZpos );
|
||||
}
|
||||
|
||||
|
||||
void CALLBACK tessErrorCB( GLenum errorCode )
|
||||
{
|
||||
#if defined(DEBUG)
|
||||
const GLubyte* errorStr;
|
||||
|
||||
errorStr = gluErrorString( errorCode );
|
||||
|
||||
// DEBUG //
|
||||
DBG( printf( "Tess ERROR: %s\n", errorStr ); )
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2012 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_draw_basic_functions.h
|
||||
*/
|
||||
#ifndef _3D_DRAW_BASIC_FUNCTIONS_H_
|
||||
#define _3D_DRAW_BASIC_FUNCTIONS_H_
|
||||
|
||||
// angle increment to draw a circle, approximated by segments
|
||||
#define ANGLE_INC( x ) ( 3600 / (x) )
|
||||
|
||||
/** draw all solid polygons found in aPolysList
|
||||
* @param aPolysList = the poligon list to draw
|
||||
* @param aZpos = z position in board internal units
|
||||
* @param aThickness = thickness in board internal units
|
||||
* @param aBiuTo3DUnits = board internal units to 3D units scaling value
|
||||
* If aThickness = 0, a polygon area is drawn in a XY plane at Z position = aZpos.
|
||||
* If aThickness > 0, a solid object is drawn.
|
||||
* The top side is located at aZpos + aThickness / 2
|
||||
* The bottom side is located at aZpos - aThickness / 2
|
||||
*/
|
||||
void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList,
|
||||
int aZpos, int aThickness, double aBiuTo3DUnits );
|
||||
|
||||
/** draw the solid polygon found in aPolysList
|
||||
* The first polygonj is the main polygon, others are holes
|
||||
* @param aPolysList = the polygon with holes to draw
|
||||
* @param aZpos = z position in board internal units
|
||||
* @param aThickness = thickness in board internal units
|
||||
* @param aBiuTo3DUnits = board internal units to 3D units scaling value
|
||||
* If aThickness = 0, a polygon area is drawn in a XY plane at Z position = aZpos.
|
||||
* If aThickness > 0, a solid object is drawn.
|
||||
* The top side is located at aZpos + aThickness / 2
|
||||
* The bottom side is located at aZpos - aThickness / 2
|
||||
*/
|
||||
void Draw3D_SolidHorizontalPolygonWithHoles( const CPOLYGONS_LIST& aPolysList,
|
||||
int aZpos, int aThickness, double aBiuTo3DUnits );
|
||||
|
||||
/** draw a thick segment using 3D primitives, in a XY plane
|
||||
* @param aStart = YX position of start point in board units
|
||||
* @param aEnd = YX position of end point in board units
|
||||
* @param aWidth = width of segment in board units
|
||||
* @param aThickness = thickness of segment in board units
|
||||
* @param aZpos = z position of segment in board units
|
||||
* @param aBiuTo3DUnits = board internal units to 3D units scaling value
|
||||
* If aThickness = 0, a polygon area is drawn in a XY plane at Z position = aZpos.
|
||||
* If aThickness > 0, a solid object is drawn.
|
||||
* The top side is located at aZpos + aThickness / 2
|
||||
* The bottom side is located at aZpos - aThickness / 2
|
||||
*/
|
||||
void Draw3D_SolidSegment( const wxPoint& aStart, const wxPoint& aEnd,
|
||||
int aWidth, int aThickness, int aZpos,
|
||||
double aBiuTo3DUnits );
|
||||
|
||||
/** draw an arc using 3D primitives, in a XY plane
|
||||
* @param aCenterPos = XY position of the center in board units
|
||||
* @param aStartPoint = start point coordinate of arc in board units
|
||||
* @param aWidth = width of the circle in board units
|
||||
* @param aArcAngle = arc angle in 1/10 degrees
|
||||
* @param aWidth = thickness of arc
|
||||
* @param aThickness = thickness of segment in board units
|
||||
* @param aZpos = z position of segment in board units
|
||||
* @param aBiuTo3DUnits = board internal units to 3D units scaling value
|
||||
*/
|
||||
void Draw3D_ArcSegment( const wxPoint& aCenterPos, const wxPoint& aStartPoint,
|
||||
double aArcAngle, int aWidth, int aThickness,
|
||||
int aZpos, double aBiuTo3DUnits );
|
||||
|
||||
|
||||
/** draw a thick cylinder (a tube) using 3D primitives.
|
||||
* the cylinder axis is parallel to the Z axis
|
||||
* @param aCenterPos = XY position of the axis cylinder ( board internal units)
|
||||
* @param aRadius = radius of the cylinder ( board internal units)
|
||||
* @param aHeight = height of the cylinder ( boardinternal units)
|
||||
* @param aThickness = tichkness of tube ( boardinternal units)
|
||||
* @param aZpos = Z position of the bottom side of the cylinder ( board internal units)
|
||||
* @param aBiuTo3DUnits = board internal units to 3D units scaling value
|
||||
*
|
||||
* If aHeight = height of the cylinder is 0, only one ring will be drawn
|
||||
* If aThickness = 0, only one cylinder (not a tube) will be drawn
|
||||
*/
|
||||
void Draw3D_ZaxisCylinder( wxPoint aCenterPos, int aRadius,
|
||||
int aHeight, int aThickness,
|
||||
int aZpos, double aBiuTo3DUnits );
|
||||
|
||||
/** draw an oblong cylinder (oblong tube) using 3D primitives.
|
||||
* the cylinder axis are parallel to the Z axis
|
||||
* @param aAxis1Pos = position of the first axis cylinder
|
||||
* @param aAxis2Pos = position of the second axis cylinder
|
||||
* @param aRadius = radius of the cylinder ( board internal units )
|
||||
* @param aHeight = height of the cylinder ( board internal units )
|
||||
* @param aThickness = tichkness of tube ( board internal units )
|
||||
* @param aZpos = Z position of the bottom side of the cylinder ( board internal units )
|
||||
* @param aBiuTo3DUnits = board internal units to 3D units scaling value
|
||||
*/
|
||||
void Draw3D_ZaxisOblongCylinder( wxPoint aAxis1Pos, wxPoint aAxis2Pos,
|
||||
int aRadius, int aHeight, int aThickness,
|
||||
int aZpos, double aBiuTo3DUnits );
|
||||
/**
|
||||
* Set the current 3D color from a Kicad color, with optional transparency
|
||||
* @param aColor = a EDA_COLOR_T kicad color index
|
||||
* @param aTransparency = the color transparency (default = 1.0 = no transparency)
|
||||
*/
|
||||
void SetGLColor( EDA_COLOR_T aColor, double aTransparency = 1.0 );
|
||||
|
||||
|
||||
#endif // _3D_DRAW_BASIC_FUNCTIONS_H_
|
||||
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_enums.h
|
||||
* @brief declared enumerations and flags
|
||||
*/
|
||||
|
||||
#ifndef _3D_ENUMS_H_
|
||||
#define _3D_ENUMS_H_
|
||||
|
||||
/// Flags used in rendering options
|
||||
enum DISPLAY3D_FLG {
|
||||
FL_AXIS=0, FL_ZONE,
|
||||
FL_ADHESIVE, FL_SILKSCREEN, FL_SOLDERMASK, FL_SOLDERPASTE,
|
||||
FL_COMMENTS, FL_ECO,
|
||||
|
||||
FL_MODULE_ATTRIBUTES_NORMAL,
|
||||
FL_MODULE_ATTRIBUTES_NORMAL_INSERT,
|
||||
FL_MODULE_ATTRIBUTES_VIRTUAL,
|
||||
|
||||
FL_SHOW_BOARD_BODY,
|
||||
FL_MOUSEWHEEL_PANNING,
|
||||
FL_USE_REALISTIC_MODE,
|
||||
|
||||
// OpenGL options
|
||||
FL_RENDER_OPENGL_SHOW_MODEL_BBOX,
|
||||
FL_RENDER_OPENGL_COPPER_THICKNESS,
|
||||
|
||||
// Raytracing options
|
||||
FL_RENDER_RAYTRACING_SHADOWS,
|
||||
FL_RENDER_RAYTRACING_BACKFLOOR,
|
||||
FL_RENDER_RAYTRACING_REFRACTIONS,
|
||||
FL_RENDER_RAYTRACING_REFLECTIONS,
|
||||
FL_RENDER_RAYTRACING_POST_PROCESSING,
|
||||
FL_RENDER_RAYTRACING_ANTI_ALIASING,
|
||||
FL_RENDER_RAYTRACING_PROCEDURAL_TEXTURES,
|
||||
FL_LAST
|
||||
};
|
||||
|
||||
|
||||
/// Camera types
|
||||
enum CAMERA_TYPE
|
||||
{
|
||||
CAMERA_TRACKBALL
|
||||
};
|
||||
|
||||
|
||||
/// Grid types
|
||||
enum GRID3D_TYPE
|
||||
{
|
||||
GRID3D_NONE,
|
||||
GRID3D_1MM,
|
||||
GRID3D_2P5MM,
|
||||
GRID3D_5MM,
|
||||
GRID3D_10MM
|
||||
};
|
||||
|
||||
|
||||
/// Render engine mode
|
||||
enum RENDER_ENGINE
|
||||
{
|
||||
RENDER_ENGINE_OPENGL_LEGACY,
|
||||
RENDER_ENGINE_RAYTRACING,
|
||||
};
|
||||
|
||||
|
||||
/// Render 3d model shape materials mode
|
||||
enum MATERIAL_MODE
|
||||
{
|
||||
MATERIAL_MODE_NORMAL, ///< Use all material properties from model file
|
||||
MATERIAL_MODE_DIFFUSE_ONLY, ///< Use only diffuse material properties
|
||||
MATERIAL_MODE_CAD_MODE ///< Use a gray shading based on diffuse material
|
||||
};
|
||||
|
||||
#endif // _3D_ENUMS_H_
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_fastmath.cpp
|
||||
* @brief
|
||||
*/
|
||||
|
||||
|
||||
#include "3d_fastmath.h"
|
||||
|
||||
|
||||
// Fast Float Random Numbers
|
||||
// a small and fast implementation for random float numbers in the range [-1,1]
|
||||
// References : Posted by dominik.ries[AT]gmail[DOT]com
|
||||
// http://www.musicdsp.org/showone.php?id=273
|
||||
|
||||
|
||||
// set the initial seed to whatever you like
|
||||
static int s_randSeed = 1;
|
||||
|
||||
// fast rand float, using full 32bit precision
|
||||
// returns in the range [-1, 1] (not confirmed)
|
||||
float Fast_RandFloat()
|
||||
{
|
||||
s_randSeed *= 16807;
|
||||
|
||||
return (float)s_randSeed * 4.6566129e-010f;
|
||||
}
|
||||
|
||||
|
||||
// Fast rand, as described here:
|
||||
// http://wiki.osdev.org/Random_Number_Generator
|
||||
|
||||
static unsigned long int s_nextRandSeed = 1;
|
||||
|
||||
int Fast_rand( void ) // RAND_MAX assumed to be 32767
|
||||
{
|
||||
s_nextRandSeed = s_nextRandSeed * 1103515245 + 12345;
|
||||
|
||||
return (unsigned int)(s_nextRandSeed >> 16) & 0x7FFF;
|
||||
}
|
||||
|
||||
void Fast_srand( unsigned int seed )
|
||||
{
|
||||
s_nextRandSeed = seed;
|
||||
}
|
||||
@@ -1,176 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_fastmath.h
|
||||
* @brief Defines math related functions
|
||||
*/
|
||||
|
||||
#ifndef _3D_FASTMATH_H
|
||||
#define _3D_FASTMATH_H
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <cmath>
|
||||
|
||||
|
||||
// Define this flag to use fast math optimizations
|
||||
#define FASTMATH_USE
|
||||
|
||||
#define L1_CACHE_LINE_SIZE 64
|
||||
|
||||
#ifdef FASTMATH_USE
|
||||
#define INTFLOORF(s) (lrintf( (s) - (0.5f - FLT_EPSILON) ))
|
||||
#else
|
||||
#define INTFLOORF(s) ((int)( floor(s) ))
|
||||
#endif
|
||||
|
||||
|
||||
// Fast Float Random Numbers
|
||||
// a small and fast implementation for random float numbers in the range [-1,1]
|
||||
// This is not thread safe
|
||||
float Fast_RandFloat();
|
||||
|
||||
int Fast_rand( void );
|
||||
void Fast_srand( unsigned int seed );
|
||||
|
||||
/**
|
||||
* This part contains some functions from the PBRT 3 source code.
|
||||
* https://github.com/mmp/pbrt-v3/blob/master/src/core/pbrt.h
|
||||
*/
|
||||
|
||||
/*
|
||||
pbrt source code is Copyright(c) 1998-2015
|
||||
Matt Pharr, Greg Humphreys, and Wenzel Jakob.
|
||||
|
||||
This file is part of pbrt.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
// Global Inline Functions
|
||||
inline uint32_t FloatToBits( float f )
|
||||
{
|
||||
uint32_t ui;
|
||||
|
||||
memcpy( &ui, &f, sizeof( float ) );
|
||||
|
||||
return ui;
|
||||
}
|
||||
|
||||
|
||||
inline float BitsToFloat( uint32_t ui )
|
||||
{
|
||||
float f;
|
||||
|
||||
memcpy( &f, &ui, sizeof (uint32_t ) );
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
inline uint64_t FloatToBits( double f )
|
||||
{
|
||||
uint64_t ui;
|
||||
|
||||
memcpy( &ui, &f, sizeof( double ) );
|
||||
|
||||
return ui;
|
||||
}
|
||||
|
||||
|
||||
inline double BitsToFloat( uint64_t ui )
|
||||
{
|
||||
double f;
|
||||
|
||||
memcpy( &f, &ui, sizeof( uint64_t ) );
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
inline float NextFloatUp( float v )
|
||||
{
|
||||
// Handle infinity and negative zero for _NextFloatUp()_
|
||||
if( std::isinf( v ) && (v > 0.) )
|
||||
return v;
|
||||
|
||||
if( v == -0.f )
|
||||
v = 0.f;
|
||||
|
||||
// Advance _v_ to next higher float
|
||||
uint32_t ui = FloatToBits( v );
|
||||
|
||||
if( v >= 0. )
|
||||
++ui;
|
||||
else
|
||||
--ui;
|
||||
|
||||
return BitsToFloat( ui );
|
||||
}
|
||||
|
||||
|
||||
inline float NextFloatDown( float v )
|
||||
{
|
||||
// Handle infinity and positive zero for _NextFloatDown()_
|
||||
if( std::isinf( v ) && (v < 0.) )
|
||||
return v;
|
||||
|
||||
if( v == 0.f )
|
||||
v = -0.f;
|
||||
|
||||
uint32_t ui = FloatToBits( v );
|
||||
|
||||
if( v > 0. )
|
||||
--ui;
|
||||
else
|
||||
++ui;
|
||||
|
||||
return BitsToFloat( ui );
|
||||
}
|
||||
|
||||
#endif // 3D_FASTMATH_H
|
||||
@@ -0,0 +1,529 @@
|
||||
/**
|
||||
* @file 3d_frame.cpp
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <fctsys.h>
|
||||
#include <kiface_i.h>
|
||||
#include <pgm_base.h>
|
||||
|
||||
#include <3d_viewer.h>
|
||||
#include <3d_canvas.h>
|
||||
#include <info3d_visu.h>
|
||||
#include <trackball.h>
|
||||
|
||||
#include <wx/colordlg.h>
|
||||
#include <3d_viewer_id.h>
|
||||
#include <wxBasePcbFrame.h>
|
||||
|
||||
INFO3D_VISU g_Parm_3D_Visu;
|
||||
|
||||
// Key to store 3D Viewer config:
|
||||
static const wxChar keyBgColor_Red[] = wxT( "BgColor_Red" );
|
||||
static const wxChar keyBgColor_Green[] = wxT( "BgColor_Green" );
|
||||
static const wxChar keyBgColor_Blue[] = wxT( "BgColor_Blue" );
|
||||
static const wxChar keyShowRealisticMode[] = wxT( "ShowRealisticMode" );
|
||||
static const wxChar keyShowAxis[] = wxT( "ShowAxis" );
|
||||
static const wxChar keyShowGrid[] = wxT( "ShowGrid3D" );
|
||||
static const wxChar keyShowGridSize[] = wxT( "Grid3DSize" );
|
||||
static const wxChar keyShowZones[] = wxT( "ShowZones" );
|
||||
static const wxChar keyShowFootprints[] = wxT( "ShowFootprints" );
|
||||
static const wxChar keyShowCopperThickness[] = wxT( "ShowCopperThickness" );
|
||||
static const wxChar keyShowAdhesiveLayers[] = wxT( "ShowAdhesiveLayers" );
|
||||
static const wxChar keyShowSilkScreenLayers[] = wxT( "ShowSilkScreenLayers" );
|
||||
static const wxChar keyShowSolderMaskLayers[] = wxT( "ShowSolderMasLayers" );
|
||||
static const wxChar keyShowSolderPasteLayers[] =wxT( "ShowSolderPasteLayers" );
|
||||
static const wxChar keyShowCommentsLayer[] = wxT( "ShowCommentsLayers" );
|
||||
static const wxChar keyShowBoardBody[] = wxT( "ShowBoardBody" );
|
||||
static const wxChar keyShowEcoLayers[] = wxT( "ShowEcoLayers" );
|
||||
|
||||
|
||||
BEGIN_EVENT_TABLE( EDA_3D_FRAME, EDA_BASE_FRAME )
|
||||
EVT_ACTIVATE( EDA_3D_FRAME::OnActivate )
|
||||
|
||||
EVT_TOOL_RANGE( ID_ZOOM_IN, ID_ZOOM_PAGE, EDA_3D_FRAME::Process_Zoom )
|
||||
EVT_TOOL_RANGE( ID_START_COMMAND_3D, ID_END_COMMAND_3D,
|
||||
EDA_3D_FRAME::Process_Special_Functions )
|
||||
EVT_TOOL( ID_TOOL_SET_VISIBLE_ITEMS, EDA_3D_FRAME::Process_Special_Functions )
|
||||
EVT_MENU( wxID_EXIT, EDA_3D_FRAME::Exit3DFrame )
|
||||
EVT_MENU( ID_MENU_SCREENCOPY_PNG, EDA_3D_FRAME::Process_Special_Functions )
|
||||
EVT_MENU( ID_MENU_SCREENCOPY_JPEG, EDA_3D_FRAME::Process_Special_Functions )
|
||||
|
||||
EVT_MENU_RANGE( ID_MENU3D_GRID, ID_MENU3D_GRID_END,
|
||||
EDA_3D_FRAME::On3DGridSelection )
|
||||
|
||||
EVT_CLOSE( EDA_3D_FRAME::OnCloseWindow )
|
||||
|
||||
END_EVENT_TABLE()
|
||||
|
||||
|
||||
EDA_3D_FRAME::EDA_3D_FRAME( KIWAY* aKiway, PCB_BASE_FRAME* aParent,
|
||||
const wxString& aTitle, long style ) :
|
||||
KIWAY_PLAYER( aKiway, aParent, FRAME_PCB_DISPLAY3D, aTitle,
|
||||
wxDefaultPosition, wxDefaultSize, style, wxT( "Frame3D" ) )
|
||||
{
|
||||
m_canvas = NULL;
|
||||
m_reloadRequest = false;
|
||||
m_ortho = false;
|
||||
|
||||
// Give it an icon
|
||||
wxIcon icon;
|
||||
icon.CopyFromBitmap( KiBitmap( icon_3d_xpm ) );
|
||||
SetIcon( icon );
|
||||
|
||||
LoadSettings( config() );
|
||||
SetSize( m_FramePos.x, m_FramePos.y, m_FrameSize.x, m_FrameSize.y );
|
||||
|
||||
// Create the status line
|
||||
static const int dims[5] = { -1, 100, 100, 100, 140 };
|
||||
|
||||
CreateStatusBar( 5 );
|
||||
SetStatusWidths( 5, dims );
|
||||
|
||||
CreateMenuBar();
|
||||
ReCreateMainToolbar();
|
||||
|
||||
// Make a EDA_3D_CANVAS
|
||||
int attrs[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 16, 0 };
|
||||
m_canvas = new EDA_3D_CANVAS( this, attrs );
|
||||
|
||||
m_auimgr.SetManagedWindow( this );
|
||||
|
||||
|
||||
EDA_PANEINFO horiztb;
|
||||
horiztb.HorizontalToolbarPane();
|
||||
|
||||
m_auimgr.AddPane( m_mainToolBar,
|
||||
wxAuiPaneInfo( horiztb ).Name( wxT( "m_mainToolBar" ) ).Top() );
|
||||
|
||||
m_auimgr.AddPane( m_canvas,
|
||||
wxAuiPaneInfo().Name( wxT( "DrawFrame" ) ).CentrePane() );
|
||||
|
||||
m_auimgr.Update();
|
||||
|
||||
// Fixes bug in Windows (XP and possibly others) where the canvas requires the focus
|
||||
// in order to receive mouse events. Otherwise, the user has to click somewhere on
|
||||
// the canvas before it will respond to mouse wheel events.
|
||||
m_canvas->SetFocus();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_FRAME::Exit3DFrame( wxCommandEvent& event )
|
||||
{
|
||||
Close( true );
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_FRAME::OnCloseWindow( wxCloseEvent& Event )
|
||||
{
|
||||
if( Parent() )
|
||||
Parent()->m_Draw3DFrame = NULL;
|
||||
|
||||
Destroy();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_FRAME::LoadSettings( wxConfigBase* aCfg )
|
||||
{
|
||||
EDA_BASE_FRAME::LoadSettings( aCfg );
|
||||
|
||||
INFO3D_VISU& prms = g_Parm_3D_Visu;
|
||||
|
||||
aCfg->Read( keyBgColor_Red, &g_Parm_3D_Visu.m_BgColor.m_Red, 0.0 );
|
||||
aCfg->Read( keyBgColor_Green, &g_Parm_3D_Visu.m_BgColor.m_Green, 0.0 );
|
||||
aCfg->Read( keyBgColor_Blue, &g_Parm_3D_Visu.m_BgColor.m_Blue, 0.0 );
|
||||
|
||||
bool tmp;
|
||||
aCfg->Read( keyShowRealisticMode, &tmp, false );
|
||||
prms.SetFlag( FL_USE_REALISTIC_MODE, tmp );
|
||||
|
||||
aCfg->Read( keyShowAxis, &tmp, true );
|
||||
prms.SetFlag( FL_AXIS, tmp );
|
||||
|
||||
aCfg->Read( keyShowGrid, &tmp, true );
|
||||
prms.SetFlag( FL_GRID, tmp );
|
||||
|
||||
aCfg->Read( keyShowGridSize, &prms.m_3D_Grid, 10.0 );
|
||||
prms.SetFlag( FL_MODULE, tmp );
|
||||
|
||||
aCfg->Read( keyShowFootprints, &tmp, true );
|
||||
prms.SetFlag( FL_MODULE, tmp );
|
||||
|
||||
aCfg->Read( keyShowCopperThickness, &tmp, false );
|
||||
prms.SetFlag( FL_USE_COPPER_THICKNESS, tmp );
|
||||
|
||||
aCfg->Read( keyShowZones, &tmp, true );
|
||||
prms.SetFlag( FL_ZONE, tmp );
|
||||
|
||||
aCfg->Read( keyShowAdhesiveLayers, &tmp, true );
|
||||
prms.SetFlag( FL_ADHESIVE, tmp );
|
||||
|
||||
aCfg->Read( keyShowSilkScreenLayers, &tmp, true );
|
||||
prms.SetFlag( FL_SILKSCREEN, tmp );
|
||||
|
||||
aCfg->Read( keyShowSolderMaskLayers, &tmp, true );
|
||||
prms.SetFlag( FL_SOLDERMASK, tmp );
|
||||
|
||||
aCfg->Read( keyShowSolderPasteLayers, &tmp, true );
|
||||
prms.SetFlag( FL_SOLDERPASTE, tmp );
|
||||
|
||||
aCfg->Read( keyShowCommentsLayer, &tmp, true );
|
||||
prms.SetFlag( FL_COMMENTS, tmp );
|
||||
|
||||
aCfg->Read( keyShowEcoLayers, &tmp, true );
|
||||
prms.SetFlag( FL_ECO, tmp );
|
||||
|
||||
aCfg->Read( keyShowBoardBody, &tmp, true );
|
||||
prms.SetFlag( FL_SHOW_BOARD_BODY, tmp );
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_FRAME::SaveSettings( wxConfigBase* aCfg )
|
||||
{
|
||||
EDA_BASE_FRAME::SaveSettings( aCfg );
|
||||
|
||||
INFO3D_VISU& prms = g_Parm_3D_Visu;
|
||||
|
||||
aCfg->Write( keyBgColor_Red, g_Parm_3D_Visu.m_BgColor.m_Red );
|
||||
aCfg->Write( keyBgColor_Green, g_Parm_3D_Visu.m_BgColor.m_Green );
|
||||
aCfg->Write( keyBgColor_Blue, g_Parm_3D_Visu.m_BgColor.m_Blue );
|
||||
aCfg->Write( keyShowRealisticMode, prms.GetFlag( FL_USE_REALISTIC_MODE ) );
|
||||
aCfg->Write( keyShowAxis, prms.GetFlag( FL_AXIS ) );
|
||||
aCfg->Write( keyShowGrid, prms.GetFlag( FL_GRID ) );
|
||||
aCfg->Write( keyShowGridSize, prms.m_3D_Grid );
|
||||
aCfg->Write( keyShowFootprints, prms.GetFlag( FL_MODULE ) );
|
||||
aCfg->Write( keyShowCopperThickness, prms.GetFlag( FL_USE_COPPER_THICKNESS ) );
|
||||
aCfg->Write( keyShowZones, prms.GetFlag( FL_ZONE ) );
|
||||
aCfg->Write( keyShowAdhesiveLayers, prms.GetFlag( FL_ADHESIVE ) );
|
||||
aCfg->Write( keyShowSilkScreenLayers, prms.GetFlag( FL_SILKSCREEN ) );
|
||||
aCfg->Write( keyShowSolderMaskLayers, prms.GetFlag( FL_SOLDERMASK ) );
|
||||
aCfg->Write( keyShowSolderPasteLayers, prms.GetFlag( FL_SOLDERPASTE ) );
|
||||
aCfg->Write( keyShowCommentsLayer, prms.GetFlag( FL_COMMENTS ) );
|
||||
aCfg->Write( keyShowEcoLayers, prms.GetFlag( FL_ECO ) );
|
||||
aCfg->Write( keyShowBoardBody, prms.GetFlag( FL_SHOW_BOARD_BODY ) );
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_FRAME::Process_Zoom( wxCommandEvent& event )
|
||||
{
|
||||
int ii;
|
||||
|
||||
switch( event.GetId() )
|
||||
{
|
||||
case ID_ZOOM_PAGE:
|
||||
|
||||
for( ii = 0; ii < 4; ii++ )
|
||||
g_Parm_3D_Visu.m_Rot[ii] = 0.0;
|
||||
|
||||
g_Parm_3D_Visu.m_Zoom = 1.0;
|
||||
m_canvas->SetOffset( 0.0, 0.0 );
|
||||
trackball( g_Parm_3D_Visu.m_Quat, 0.0, 0.0, 0.0, 0.0 );
|
||||
break;
|
||||
|
||||
case ID_ZOOM_IN:
|
||||
g_Parm_3D_Visu.m_Zoom /= 1.2;
|
||||
|
||||
if( g_Parm_3D_Visu.m_Zoom <= 0.01 )
|
||||
g_Parm_3D_Visu.m_Zoom = 0.01;
|
||||
|
||||
break;
|
||||
|
||||
case ID_ZOOM_OUT:
|
||||
g_Parm_3D_Visu.m_Zoom *= 1.2;
|
||||
break;
|
||||
|
||||
case ID_ZOOM_REDRAW:
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
m_canvas->Refresh( false );
|
||||
m_canvas->DisplayStatus();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_FRAME::OnLeftClick( wxDC* DC, const wxPoint& MousePos )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_FRAME::OnRightClick( const wxPoint& MousePos, wxMenu* PopMenu )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
double EDA_3D_FRAME::BestZoom()
|
||||
{
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_FRAME::RedrawActiveWindow( wxDC* DC, bool EraseBg )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_FRAME::Process_Special_Functions( wxCommandEvent& event )
|
||||
{
|
||||
#define ROT_ANGLE 10.0
|
||||
int id = event.GetId();
|
||||
bool isChecked = event.IsChecked();
|
||||
|
||||
switch( id )
|
||||
{
|
||||
case ID_TOOL_SET_VISIBLE_ITEMS:
|
||||
Install_3D_ViewOptionDialog( event );
|
||||
break;
|
||||
|
||||
case ID_RELOAD3D_BOARD:
|
||||
NewDisplay();
|
||||
return;
|
||||
break;
|
||||
|
||||
case ID_ROTATE3D_X_POS:
|
||||
g_Parm_3D_Visu.m_ROTX += ROT_ANGLE;
|
||||
break;
|
||||
|
||||
case ID_ROTATE3D_X_NEG:
|
||||
g_Parm_3D_Visu.m_ROTX -= ROT_ANGLE;
|
||||
break;
|
||||
|
||||
case ID_ROTATE3D_Y_POS:
|
||||
g_Parm_3D_Visu.m_ROTY += ROT_ANGLE;
|
||||
break;
|
||||
|
||||
case ID_ROTATE3D_Y_NEG:
|
||||
g_Parm_3D_Visu.m_ROTY -= ROT_ANGLE;
|
||||
break;
|
||||
|
||||
case ID_ROTATE3D_Z_POS:
|
||||
g_Parm_3D_Visu.m_ROTZ += ROT_ANGLE;
|
||||
break;
|
||||
|
||||
case ID_ROTATE3D_Z_NEG:
|
||||
g_Parm_3D_Visu.m_ROTZ -= ROT_ANGLE;
|
||||
break;
|
||||
|
||||
case ID_MOVE3D_LEFT:
|
||||
m_canvas->SetView3D( WXK_LEFT );
|
||||
return;
|
||||
|
||||
case ID_MOVE3D_RIGHT:
|
||||
m_canvas->SetView3D( WXK_RIGHT );
|
||||
return;
|
||||
|
||||
case ID_MOVE3D_UP:
|
||||
m_canvas->SetView3D( WXK_UP );
|
||||
return;
|
||||
|
||||
case ID_MOVE3D_DOWN:
|
||||
m_canvas->SetView3D( WXK_DOWN );
|
||||
return;
|
||||
|
||||
case ID_ORTHO:
|
||||
ToggleOrtho();
|
||||
return;
|
||||
|
||||
case ID_TOOL_SCREENCOPY_TOCLIBBOARD:
|
||||
case ID_MENU_SCREENCOPY_PNG:
|
||||
case ID_MENU_SCREENCOPY_JPEG:
|
||||
m_canvas->TakeScreenshot( event );
|
||||
break;
|
||||
|
||||
case ID_MENU3D_BGCOLOR_SELECTION:
|
||||
Set3DBgColor();
|
||||
return;
|
||||
|
||||
case ID_MENU3D_REALISTIC_MODE:
|
||||
g_Parm_3D_Visu.SetFlag( FL_USE_REALISTIC_MODE, isChecked );
|
||||
NewDisplay();
|
||||
return;
|
||||
|
||||
case ID_MENU3D_SHOW_BOARD_BODY:
|
||||
g_Parm_3D_Visu.SetFlag( FL_SHOW_BOARD_BODY, isChecked );
|
||||
NewDisplay();
|
||||
return;
|
||||
|
||||
case ID_MENU3D_AXIS_ONOFF:
|
||||
g_Parm_3D_Visu.SetFlag( FL_AXIS, isChecked );
|
||||
m_canvas->Refresh();
|
||||
return;
|
||||
|
||||
case ID_MENU3D_MODULE_ONOFF:
|
||||
g_Parm_3D_Visu.SetFlag( FL_MODULE, isChecked );
|
||||
m_canvas->Refresh();
|
||||
return;
|
||||
|
||||
case ID_MENU3D_USE_COPPER_THICKNESS:
|
||||
g_Parm_3D_Visu.SetFlag( FL_USE_COPPER_THICKNESS, isChecked );
|
||||
NewDisplay(GL_ID_BOARD);
|
||||
return;
|
||||
|
||||
case ID_MENU3D_ZONE_ONOFF:
|
||||
g_Parm_3D_Visu.SetFlag( FL_ZONE, isChecked );
|
||||
NewDisplay(GL_ID_BOARD);
|
||||
return;
|
||||
|
||||
case ID_MENU3D_ADHESIVE_ONOFF:
|
||||
g_Parm_3D_Visu.SetFlag( FL_ADHESIVE, isChecked );
|
||||
NewDisplay(GL_ID_TECH_LAYERS);
|
||||
return;
|
||||
|
||||
case ID_MENU3D_SILKSCREEN_ONOFF:
|
||||
g_Parm_3D_Visu.SetFlag( FL_SILKSCREEN, isChecked );
|
||||
NewDisplay(GL_ID_TECH_LAYERS);
|
||||
return;
|
||||
|
||||
case ID_MENU3D_SOLDER_MASK_ONOFF:
|
||||
g_Parm_3D_Visu.SetFlag( FL_SOLDERMASK, isChecked );
|
||||
NewDisplay(GL_ID_TECH_LAYERS);
|
||||
return;
|
||||
|
||||
case ID_MENU3D_SOLDER_PASTE_ONOFF:
|
||||
g_Parm_3D_Visu.SetFlag( FL_SOLDERPASTE, isChecked );
|
||||
NewDisplay(GL_ID_TECH_LAYERS);
|
||||
return;
|
||||
|
||||
case ID_MENU3D_COMMENTS_ONOFF:
|
||||
g_Parm_3D_Visu.SetFlag( FL_COMMENTS, isChecked );
|
||||
NewDisplay(GL_ID_AUX_LAYERS);
|
||||
return;
|
||||
|
||||
case ID_MENU3D_ECO_ONOFF:
|
||||
g_Parm_3D_Visu.SetFlag( FL_ECO, isChecked );
|
||||
NewDisplay(GL_ID_AUX_LAYERS);
|
||||
return;
|
||||
|
||||
default:
|
||||
wxLogMessage( wxT( "EDA_3D_FRAME::Process_Special_Functions() error: unknown command" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
m_canvas->Refresh( true );
|
||||
m_canvas->DisplayStatus();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_FRAME::On3DGridSelection( wxCommandEvent& event )
|
||||
{
|
||||
int id = event.GetId();
|
||||
|
||||
for( int ii = ID_MENU3D_GRID; ii < ID_MENU3D_GRID_END; ii++ )
|
||||
{
|
||||
if( event.GetId() == ii )
|
||||
continue;
|
||||
|
||||
GetMenuBar()->Check( ii, false );
|
||||
}
|
||||
|
||||
switch( id )
|
||||
{
|
||||
case ID_MENU3D_GRID_NOGRID:
|
||||
g_Parm_3D_Visu.SetFlag( FL_GRID, false );
|
||||
break;
|
||||
|
||||
case ID_MENU3D_GRID_10_MM:
|
||||
g_Parm_3D_Visu.SetFlag( FL_GRID, true );
|
||||
g_Parm_3D_Visu.m_3D_Grid = 10.0;
|
||||
break;
|
||||
|
||||
case ID_MENU3D_GRID_5_MM:
|
||||
g_Parm_3D_Visu.SetFlag( FL_GRID, true );
|
||||
g_Parm_3D_Visu.m_3D_Grid = 5.0;
|
||||
break;
|
||||
|
||||
case ID_MENU3D_GRID_2P5_MM:
|
||||
g_Parm_3D_Visu.SetFlag( FL_GRID, true );
|
||||
g_Parm_3D_Visu.m_3D_Grid = 2.5;
|
||||
break;
|
||||
|
||||
case ID_MENU3D_GRID_1_MM:
|
||||
g_Parm_3D_Visu.SetFlag( FL_GRID, true );
|
||||
g_Parm_3D_Visu.m_3D_Grid = 1.0;
|
||||
break;
|
||||
|
||||
default:
|
||||
wxLogMessage( wxT( "EDA_3D_FRAME::On3DGridSelection() error: unknown command" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
NewDisplay( GL_ID_GRID );
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_FRAME::NewDisplay( GLuint aGlList )
|
||||
{
|
||||
m_reloadRequest = false;
|
||||
|
||||
m_canvas->ClearLists( aGlList );
|
||||
m_canvas->CreateDrawGL_List();
|
||||
|
||||
m_canvas->Refresh( true );
|
||||
m_canvas->DisplayStatus();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_FRAME::OnActivate( wxActivateEvent& event )
|
||||
{
|
||||
// Reload data if 3D frame shows a footprint,
|
||||
// because it can be changed since last frame activation
|
||||
if( m_reloadRequest )
|
||||
NewDisplay();
|
||||
|
||||
event.Skip(); // required under wxMAC
|
||||
}
|
||||
|
||||
|
||||
/* called to set the background color of the 3D scene
|
||||
*/
|
||||
void EDA_3D_FRAME::Set3DBgColor()
|
||||
{
|
||||
S3D_COLOR color;
|
||||
wxColour newcolor, oldcolor;
|
||||
|
||||
oldcolor.Set( KiROUND( g_Parm_3D_Visu.m_BgColor.m_Red * 255 ),
|
||||
KiROUND( g_Parm_3D_Visu.m_BgColor.m_Green * 255 ),
|
||||
KiROUND( g_Parm_3D_Visu.m_BgColor.m_Blue * 255 ) );
|
||||
|
||||
newcolor = wxGetColourFromUser( this, oldcolor );
|
||||
|
||||
if( !newcolor.IsOk() ) // Happens on cancel dialog
|
||||
return;
|
||||
|
||||
if( newcolor != oldcolor )
|
||||
{
|
||||
g_Parm_3D_Visu.m_BgColor.m_Red = (double) newcolor.Red() / 255.0;
|
||||
g_Parm_3D_Visu.m_BgColor.m_Green = (double) newcolor.Green() / 255.0;
|
||||
g_Parm_3D_Visu.m_BgColor.m_Blue = (double) newcolor.Blue() / 255.0;
|
||||
NewDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
BOARD* EDA_3D_FRAME::GetBoard()
|
||||
{
|
||||
return Parent()->GetBoard();
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_math.cpp
|
||||
* @brief
|
||||
*/
|
||||
|
||||
|
||||
#include "3d_math.h"
|
||||
@@ -1,193 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_math.h
|
||||
* @brief Defines math related functions
|
||||
*/
|
||||
|
||||
#ifndef _3D_MATH_H
|
||||
#define _3D_MATH_H
|
||||
|
||||
#include <plugins/3dapi/xv3d_types.h>
|
||||
#include "3d_fastmath.h"
|
||||
|
||||
// https://en.wikipedia.org/wiki/Spherical_coordinate_system
|
||||
/**
|
||||
* @brief SphericalToCartesian
|
||||
* @param aInclination θ ∈ [0, π]
|
||||
* @param aAzimuth φ ∈ [0, 2π]
|
||||
* @return Cartesian cordinates
|
||||
*/
|
||||
inline SFVEC3F SphericalToCartesian( float aInclination, float aAzimuth )
|
||||
{
|
||||
float sinInc = glm::sin( aInclination );
|
||||
return SFVEC3F( sinInc * glm::cos( aAzimuth ),
|
||||
sinInc * glm::sin( aAzimuth ),
|
||||
glm::cos( aInclination ) );
|
||||
}
|
||||
|
||||
|
||||
// https://pathtracing.wordpress.com/2011/03/03/cosine-weighted-hemisphere/
|
||||
// !TODO: this is not correct because it is not a gaussian random
|
||||
inline SFVEC3F UniformRandomHemisphereDirection( )
|
||||
{
|
||||
// It was experienced that this function is slow! do not use it :/
|
||||
// SFVEC3F b( (rand()/(float)RAND_MAX) - 0.5f,
|
||||
// (rand()/(float)RAND_MAX) - 0.5f,
|
||||
// (rand()/(float)RAND_MAX) - 0.5f );
|
||||
|
||||
SFVEC3F b( Fast_RandFloat() * 0.5f,
|
||||
Fast_RandFloat() * 0.5f,
|
||||
Fast_RandFloat() * 0.5f );
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
// https://pathtracing.wordpress.com/2011/03/03/cosine-weighted-hemisphere/
|
||||
inline SFVEC3F CosWeightedRandomHemisphereDirection( const SFVEC3F &n )
|
||||
{
|
||||
const float Xi1 = (float)rand() / (float)RAND_MAX;
|
||||
const float Xi2 = (float)rand() / (float)RAND_MAX;
|
||||
|
||||
const float theta = acos( sqrt( 1.0f - Xi1 ) );
|
||||
const float phi = 2.0f * glm::pi<float>() * Xi2;
|
||||
|
||||
const float xs = sinf( theta ) * cosf( phi );
|
||||
const float ys = cosf( theta );
|
||||
const float zs = sinf( theta ) * sinf( phi );
|
||||
|
||||
const SFVEC3F y( n.x, n.y, n.z );
|
||||
SFVEC3F h = y;
|
||||
|
||||
if( fabs( h.x ) <= fabs( h.y ) && fabs( h.x ) <= fabs( h.z ) )
|
||||
h.x= 1.0f;
|
||||
else if( fabs( h.y ) <= fabs( h.x ) && fabs( h.y ) <= fabs( h.z ) )
|
||||
h.y= 1.0f;
|
||||
else
|
||||
h.z= 1.0f;
|
||||
|
||||
|
||||
const SFVEC3F x = glm::normalize( glm::cross( h, y ) );
|
||||
const SFVEC3F z = glm::normalize( glm::cross( x, y ) );
|
||||
|
||||
SFVEC3F direction = xs * x + ys * y + zs * z;
|
||||
return glm::normalize( direction );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Refract
|
||||
* Based on:
|
||||
* https://github.com/mmp/pbrt-v3/blob/master/src/core/reflection.h
|
||||
* See also:
|
||||
* http://www.flipcode.com/archives/Raytracing_Topics_Techniques-Part_3_Refractions_and_Beers_Law.shtml
|
||||
* @param aInVector incoming vector
|
||||
* @param aNormal normal in the intersection point
|
||||
* @param aRin_over_Rout incoming refraction index / out refraction index
|
||||
* @param aOutVector the refracted vector
|
||||
* @return true
|
||||
*/
|
||||
inline bool Refract( const SFVEC3F &aInVector,
|
||||
const SFVEC3F &aNormal,
|
||||
float aRin_over_Rout,
|
||||
SFVEC3F &aOutVector )
|
||||
{
|
||||
float cosThetaI = -glm::dot( aNormal, aInVector );
|
||||
float sin2ThetaI = glm::max( 0.0f, 1.0f - cosThetaI * cosThetaI );
|
||||
float sin2ThetaT = aRin_over_Rout * aRin_over_Rout * sin2ThetaI;
|
||||
|
||||
// Handle total internal reflection for transmission
|
||||
if( sin2ThetaT >= 1.0f )
|
||||
return false;
|
||||
|
||||
float cosThetaT = sqrtf( 1.0f - sin2ThetaT );
|
||||
|
||||
aOutVector = glm::normalize( aRin_over_Rout * aInVector +
|
||||
( aRin_over_Rout * cosThetaI - cosThetaT ) *
|
||||
aNormal );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
inline float mapf( float x,
|
||||
float in_min,
|
||||
float in_max,
|
||||
float out_min,
|
||||
float out_max)
|
||||
{
|
||||
x = glm::clamp( x, in_min, in_max );
|
||||
|
||||
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||
}
|
||||
|
||||
inline float RGBtoGray( const SFVEC3F &aColor )
|
||||
{
|
||||
return (aColor.r * 0.2126f +
|
||||
aColor.g * 0.7152f +
|
||||
aColor.b * 0.0722f);
|
||||
}
|
||||
|
||||
inline SFVEC3F MaterialDiffuseToColorCAD( const SFVEC3F &aDiffuseColor )
|
||||
{
|
||||
// convert to a discret scale of grays
|
||||
const float luminance = glm::min( (((float)((unsigned int) ( 4.0f *
|
||||
RGBtoGray( aDiffuseColor ) ) ) + 0.5f) /
|
||||
4.0f) * 1.0f,
|
||||
1.0f );
|
||||
|
||||
const float maxValue = glm::max( glm::max( glm::max( aDiffuseColor.r,
|
||||
aDiffuseColor.g),
|
||||
aDiffuseColor.b ),
|
||||
FLT_EPSILON );
|
||||
|
||||
return (aDiffuseColor / SFVEC3F(maxValue) ) * 0.125f + luminance* 0.875f;
|
||||
}
|
||||
|
||||
|
||||
// http://fooplot.com/#W3sidHlwZSI6MCwiZXEiOiJ4KngqMiIsImNvbG9yIjoiIzAwMDAwMCJ9LHsidHlwZSI6MCwiZXEiOiItKCh4LTEpXjIpKjIrMSIsImNvbG9yIjoiIzAwMDAwMCJ9LHsidHlwZSI6MTAwMCwid2luZG93IjpbIi0xLjM4NzUwMDAwMDAwMDAwMDIiLCIxLjg2MjQ5OTk5OTk5OTk5OTgiLCItMC43IiwiMS4zIl19XQ--
|
||||
inline float QuadricEasingInOut( float t )
|
||||
{
|
||||
if( t <= 0.5f )
|
||||
{
|
||||
return t * t * 2.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
t = t - 1.0f;
|
||||
|
||||
return -2.0f * (t * t) + 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// http://www.wolframalpha.com/input/?i=t%5E2(3-2t)
|
||||
inline float BezierBlend( float t )
|
||||
{
|
||||
return t * t * ( 3.0f - 2.0f * t );
|
||||
}
|
||||
|
||||
#endif // 3D_MATH_H
|
||||
@@ -1,471 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file c3d_model_viewer.cpp
|
||||
* @brief Implements a model viewer canvas. The propose of model viewer is to
|
||||
* render 3d models that come in the original data from the files without any
|
||||
* transformations.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include "3d_rendering/3d_render_ogl_legacy/c_ogl_3dmodel.h"
|
||||
#include "c3d_model_viewer.h"
|
||||
#include "../3d_rendering/3d_render_ogl_legacy/ogl_legacy_utils.h"
|
||||
#include "../3d_cache/3d_cache.h"
|
||||
#include "common_ogl/ogl_utils.h"
|
||||
#include <wx/dcclient.h>
|
||||
#include <base_units.h>
|
||||
#include <gl_context_mgr.h>
|
||||
|
||||
/**
|
||||
* Scale convertion from 3d model units to pcb units
|
||||
*/
|
||||
#define UNITS3D_TO_UNITSPCB (IU_PER_MM)
|
||||
|
||||
/**
|
||||
* Trace mask used to enable or disable the trace output of this class.
|
||||
* The debug output can be turned on by setting the WXTRACE environment variable to
|
||||
* "KI_TRACE_EDA_3D_MODEL_VIEWER". See the wxWidgets documentation on wxLogTrace for
|
||||
* more information.
|
||||
*/
|
||||
const wxChar * C3D_MODEL_VIEWER::m_logTrace = wxT( "KI_TRACE_EDA_3D_MODEL_VIEWER" );
|
||||
|
||||
|
||||
BEGIN_EVENT_TABLE( C3D_MODEL_VIEWER, wxGLCanvas )
|
||||
EVT_PAINT( C3D_MODEL_VIEWER::OnPaint )
|
||||
|
||||
// mouse events
|
||||
EVT_LEFT_DOWN( C3D_MODEL_VIEWER::OnLeftDown )
|
||||
EVT_LEFT_UP( C3D_MODEL_VIEWER::OnLeftUp )
|
||||
EVT_MIDDLE_UP( C3D_MODEL_VIEWER::OnMiddleUp )
|
||||
EVT_MIDDLE_DOWN(C3D_MODEL_VIEWER::OnMiddleDown)
|
||||
EVT_RIGHT_DOWN( C3D_MODEL_VIEWER::OnRightClick )
|
||||
EVT_MOUSEWHEEL( C3D_MODEL_VIEWER::OnMouseWheel )
|
||||
EVT_MOTION( C3D_MODEL_VIEWER::OnMouseMove )
|
||||
|
||||
#ifdef USE_OSX_MAGNIFY_EVENT
|
||||
EVT_MAGNIFY( C3D_MODEL_VIEWER::OnMagnify )
|
||||
#endif
|
||||
|
||||
// other events
|
||||
EVT_ERASE_BACKGROUND( C3D_MODEL_VIEWER::OnEraseBackground )
|
||||
END_EVENT_TABLE()
|
||||
|
||||
|
||||
// This defines the range that all coord will have to be rendered.
|
||||
// It will use this value to convert to a normalized value between
|
||||
// -(RANGE_SCALE_3D/2) .. +(RANGE_SCALE_3D/2)
|
||||
#define RANGE_SCALE_3D 8.0f
|
||||
|
||||
|
||||
C3D_MODEL_VIEWER::C3D_MODEL_VIEWER(wxWindow *aParent,
|
||||
const int *aAttribList , S3D_CACHE *aCacheManager) :
|
||||
|
||||
HIDPI_GL_CANVAS( aParent,
|
||||
wxID_ANY,
|
||||
aAttribList,
|
||||
wxDefaultPosition,
|
||||
wxDefaultSize,
|
||||
wxFULL_REPAINT_ON_RESIZE ),
|
||||
m_trackBallCamera( RANGE_SCALE_3D * 2.0f ),
|
||||
m_cacheManager(aCacheManager)
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::C3D_MODEL_VIEWER" ) );
|
||||
|
||||
m_ogl_initialized = false;
|
||||
m_reload_is_needed = false;
|
||||
m_ogl_3dmodel = NULL;
|
||||
m_3d_model = NULL;
|
||||
m_BiuTo3Dunits = 1.0;
|
||||
|
||||
m_glRC = NULL;
|
||||
}
|
||||
|
||||
|
||||
C3D_MODEL_VIEWER::~C3D_MODEL_VIEWER()
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::~C3D_MODEL_VIEWER" ) );
|
||||
|
||||
if( m_glRC )
|
||||
{
|
||||
GL_CONTEXT_MANAGER::Get().LockCtx( m_glRC, this );
|
||||
|
||||
delete m_ogl_3dmodel;
|
||||
m_ogl_3dmodel = NULL;
|
||||
|
||||
GL_CONTEXT_MANAGER::Get().UnlockCtx( m_glRC );
|
||||
GL_CONTEXT_MANAGER::Get().DestroyCtx( m_glRC );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::Set3DModel( const S3DMODEL &a3DModel )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::Set3DModel with a S3DMODEL" ) );
|
||||
|
||||
// Validate a3DModel pointers
|
||||
wxASSERT( a3DModel.m_Materials != NULL );
|
||||
wxASSERT( a3DModel.m_Meshes != NULL );
|
||||
wxASSERT( a3DModel.m_MaterialsSize > 0 );
|
||||
wxASSERT( a3DModel.m_MeshesSize > 0 );
|
||||
|
||||
// Delete the old model
|
||||
delete m_ogl_3dmodel;
|
||||
m_ogl_3dmodel = NULL;
|
||||
|
||||
m_3d_model = NULL;
|
||||
|
||||
if( (a3DModel.m_Materials != NULL) && (a3DModel.m_Meshes != NULL) &&
|
||||
(a3DModel.m_MaterialsSize > 0) && (a3DModel.m_MeshesSize > 0) )
|
||||
{
|
||||
m_3d_model = &a3DModel;
|
||||
m_reload_is_needed = true;
|
||||
}
|
||||
|
||||
Refresh();
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::Set3DModel(const wxString &aModelPathName)
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::Set3DModel with a wxString" ) );
|
||||
|
||||
if( m_cacheManager )
|
||||
{
|
||||
const S3DMODEL* model = m_cacheManager->GetModel( aModelPathName );
|
||||
|
||||
if( model )
|
||||
Set3DModel( (const S3DMODEL &)*model );
|
||||
else
|
||||
Clear3DModel();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::Clear3DModel()
|
||||
{
|
||||
// Delete the old model
|
||||
m_reload_is_needed = false;
|
||||
|
||||
delete m_ogl_3dmodel;
|
||||
m_ogl_3dmodel = NULL;
|
||||
|
||||
m_3d_model = NULL;
|
||||
|
||||
Refresh();
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::ogl_initialize()
|
||||
{
|
||||
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
|
||||
glHint( GL_LINE_SMOOTH_HINT, GL_NICEST );
|
||||
glHint( GL_POLYGON_SMOOTH_HINT, GL_NICEST );
|
||||
|
||||
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
|
||||
glEnable( GL_DEPTH_TEST );
|
||||
//glDepthFunc( GL_LEQUAL );
|
||||
glEnable( GL_CULL_FACE );
|
||||
glShadeModel( GL_SMOOTH );
|
||||
glEnable( GL_LINE_SMOOTH );
|
||||
glEnable( GL_NORMALIZE );
|
||||
|
||||
// Setup light
|
||||
// https://www.opengl.org/sdk/docs/man2/xhtml/glLight.xml
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
const GLfloat ambient[] = { 0.01f, 0.01f, 0.01f, 1.0f };
|
||||
const GLfloat diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
const GLfloat specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
|
||||
// defines a directional light that points along the negative z-axis
|
||||
const GLfloat position[] = { 0.0f, 0.0f, 2.0f * RANGE_SCALE_3D, 0.0f };
|
||||
|
||||
const GLfloat lmodel_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
|
||||
glLightfv( GL_LIGHT0, GL_AMBIENT, ambient );
|
||||
glLightfv( GL_LIGHT0, GL_DIFFUSE, diffuse );
|
||||
glLightfv( GL_LIGHT0, GL_SPECULAR, specular );
|
||||
glLightfv( GL_LIGHT0, GL_POSITION, position );
|
||||
glLightModelfv( GL_LIGHT_MODEL_AMBIENT, lmodel_ambient );
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::ogl_set_arrow_material()
|
||||
{
|
||||
glEnable( GL_COLOR_MATERIAL );
|
||||
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
|
||||
|
||||
const SFVEC4F specular = SFVEC4F( 0.1f, 0.1f, 0.1f, 1.0f );
|
||||
|
||||
glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, &specular.r );
|
||||
glMaterialf( GL_FRONT_AND_BACK, GL_SHININESS, 96.0f );
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnPaint( wxPaintEvent &event )
|
||||
{
|
||||
wxPaintDC( this );
|
||||
|
||||
event.Skip( false );
|
||||
|
||||
// SwapBuffer requires the window to be shown before calling
|
||||
if( !IsShownOnScreen() )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::OnPaint !IsShown" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
// "Makes the OpenGL state that is represented by the OpenGL rendering
|
||||
// context context current, i.e. it will be used by all subsequent OpenGL calls.
|
||||
// This function may only be called when the window is shown on screen"
|
||||
if( m_glRC == NULL )
|
||||
m_glRC = GL_CONTEXT_MANAGER::Get().CreateCtx( this );
|
||||
|
||||
GL_CONTEXT_MANAGER::Get().LockCtx( m_glRC, this );
|
||||
|
||||
// Set the OpenGL viewport according to the client size of this canvas.
|
||||
// This is done here rather than in a wxSizeEvent handler because our
|
||||
// OpenGL rendering context (and thus viewport setting) is used with
|
||||
// multiple canvases: If we updated the viewport in the wxSizeEvent
|
||||
// handler, changing the size of one canvas causes a viewport setting that
|
||||
// is wrong when next another canvas is repainted.
|
||||
wxSize clientSize = GetClientSize();
|
||||
|
||||
if( !m_ogl_initialized )
|
||||
{
|
||||
m_ogl_initialized = true;
|
||||
ogl_initialize();
|
||||
}
|
||||
|
||||
if( m_reload_is_needed )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::OnPaint m_reload_is_needed" ) );
|
||||
|
||||
m_reload_is_needed = false;
|
||||
m_ogl_3dmodel = new C_OGL_3DMODEL( *m_3d_model, MATERIAL_MODE_NORMAL );
|
||||
|
||||
// It convert a model as it was a board, so get the max size dimension of the board
|
||||
// and compute the conversion scale
|
||||
m_BiuTo3Dunits = (double)RANGE_SCALE_3D /
|
||||
( (double)m_ogl_3dmodel->GetBBox().GetMaxDimension() *
|
||||
UNITS3D_TO_UNITSPCB );
|
||||
}
|
||||
|
||||
glViewport( 0, 0, clientSize.x, clientSize.y );
|
||||
|
||||
m_trackBallCamera.SetCurWindowSize( clientSize );
|
||||
|
||||
// clear color and depth buffers
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
glEnable( GL_DEPTH_TEST );
|
||||
|
||||
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
|
||||
glClearDepth( 1.0f );
|
||||
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||
|
||||
// Set projection and modelview matrixes
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glLoadMatrixf( glm::value_ptr( m_trackBallCamera.GetProjectionMatrix() ) );
|
||||
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glLoadMatrixf( glm::value_ptr( m_trackBallCamera.GetViewMatrix() ) );
|
||||
|
||||
glEnable( GL_LIGHTING );
|
||||
glEnable( GL_LIGHT0 );
|
||||
|
||||
// Render Model
|
||||
if( m_ogl_3dmodel )
|
||||
{
|
||||
glPushMatrix();
|
||||
|
||||
double modelunit_to_3d_units_factor = m_BiuTo3Dunits * UNITS3D_TO_UNITSPCB;
|
||||
|
||||
glScaled( modelunit_to_3d_units_factor,
|
||||
modelunit_to_3d_units_factor,
|
||||
modelunit_to_3d_units_factor );
|
||||
|
||||
// Center model in the render viewport
|
||||
const SFVEC3F model_center = m_ogl_3dmodel->GetBBox().GetCenter();
|
||||
|
||||
glTranslatef( -model_center.x, -model_center.y, -model_center.z );
|
||||
|
||||
m_ogl_3dmodel->Draw_opaque();
|
||||
m_ogl_3dmodel->Draw_transparent();
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
// YxY squared view port
|
||||
glViewport( 0, 0, clientSize.y / 8 , clientSize.y / 8 );
|
||||
glClear( GL_DEPTH_BUFFER_BIT );
|
||||
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glLoadIdentity();
|
||||
gluPerspective( 45.0f, 1.0f, 0.01f, RANGE_SCALE_3D * 2.0f );
|
||||
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glLoadIdentity();
|
||||
|
||||
const glm::mat4 TranslationMatrix = glm::translate( glm::mat4(1.0f),
|
||||
SFVEC3F( 0.0f, 0.0f, -RANGE_SCALE_3D ) );
|
||||
|
||||
const glm::mat4 ViewMatrix = TranslationMatrix * m_trackBallCamera.GetRotationMatrix();
|
||||
|
||||
glLoadMatrixf( glm::value_ptr( ViewMatrix ) );
|
||||
|
||||
ogl_set_arrow_material();
|
||||
|
||||
glColor3f( 0.9f, 0.0f, 0.0f );
|
||||
OGL_draw_arrow( SFVEC3F( 0.0f, 0.0f, 0.0f ),
|
||||
SFVEC3F( RANGE_SCALE_3D / 2.65f, 0.0f, 0.0f ),
|
||||
0.275f );
|
||||
|
||||
glColor3f( 0.0f, 0.9f, 0.0f );
|
||||
OGL_draw_arrow( SFVEC3F( 0.0f, 0.0f, 0.0f ),
|
||||
SFVEC3F( 0.0f, RANGE_SCALE_3D / 2.65f, 0.0f ),
|
||||
0.275f );
|
||||
|
||||
glColor3f( 0.0f, 0.0f, 0.9f );
|
||||
OGL_draw_arrow( SFVEC3F( 0.0f, 0.0f, 0.0f ),
|
||||
SFVEC3F( 0.0f, 0.0f, RANGE_SCALE_3D / 2.65f ),
|
||||
0.275f );
|
||||
|
||||
// "Swaps the double-buffer of this window, making the back-buffer the
|
||||
// front-buffer and vice versa, so that the output of the previous OpenGL
|
||||
// commands is displayed on the window."
|
||||
SwapBuffers();
|
||||
|
||||
GL_CONTEXT_MANAGER::Get().UnlockCtx( m_glRC );
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnEraseBackground( wxEraseEvent &event )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::OnEraseBackground" ) );
|
||||
// Do nothing, to avoid flashing.
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnMouseWheel( wxMouseEvent &event )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::OnMouseWheel" ) );
|
||||
|
||||
if( event.ShiftDown() )
|
||||
{
|
||||
//if( event.GetWheelRotation() < 0 )
|
||||
//SetView3D( WXK_UP ); // move up
|
||||
//else
|
||||
//SetView3D( WXK_DOWN ); // move down
|
||||
}
|
||||
else if( event.ControlDown() )
|
||||
{
|
||||
//if( event.GetWheelRotation() > 0 )
|
||||
//SetView3D( WXK_RIGHT ); // move right
|
||||
//else
|
||||
//SetView3D( WXK_LEFT ); // move left
|
||||
}
|
||||
else
|
||||
{
|
||||
m_trackBallCamera.Zoom( event.GetWheelRotation() > 0 ? 1.1f : 1/1.1f );
|
||||
|
||||
//DisplayStatus();
|
||||
Refresh( false );
|
||||
}
|
||||
|
||||
m_trackBallCamera.SetCurMousePosition( event.GetPosition() );
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_OSX_MAGNIFY_EVENT
|
||||
void C3D_MODEL_VIEWER::OnMagnify( wxMouseEvent& event )
|
||||
{
|
||||
/*
|
||||
double magnification = ( event.GetMagnification() + 1.0f );
|
||||
GetPrm3DVisu().m_Zoom /= magnification;
|
||||
if( GetPrm3DVisu().m_Zoom <= 0.01 )
|
||||
GetPrm3DVisu().m_Zoom = 0.01;
|
||||
DisplayStatus();
|
||||
Refresh( false );
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnMouseMove( wxMouseEvent &event )
|
||||
{
|
||||
m_trackBallCamera.SetCurWindowSize( GetClientSize() );
|
||||
|
||||
if( event.Dragging() )
|
||||
{
|
||||
if( event.LeftIsDown() ) // Drag
|
||||
m_trackBallCamera.Drag( event.GetPosition() );
|
||||
//else if( event.MiddleIsDown() ) // Pan
|
||||
// m_trackBallCamera.Pan( event.GetPosition() );
|
||||
|
||||
// orientation has changed, redraw mesh
|
||||
Refresh( false );
|
||||
}
|
||||
|
||||
m_trackBallCamera.SetCurMousePosition( event.GetPosition() );
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnLeftDown( wxMouseEvent &event )
|
||||
{
|
||||
//m_is_moving_mouse = true;
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnLeftUp( wxMouseEvent &event )
|
||||
{
|
||||
//m_is_moving_mouse = false;
|
||||
//Refresh( false );
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnMiddleDown( wxMouseEvent &event )
|
||||
{
|
||||
//m_is_moving_mouse = true;
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnMiddleUp( wxMouseEvent &event )
|
||||
{
|
||||
//m_is_moving_mouse = false;
|
||||
//Refresh( false );
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnRightClick( wxMouseEvent &event )
|
||||
{
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
@@ -1,147 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file c3d_model_viewer.h
|
||||
* @brief Implements a model viewer canvas. The propose of model viewer is to
|
||||
* render 3d models that come in the original data from the files without any
|
||||
* transformations.
|
||||
*/
|
||||
|
||||
#ifndef _C3D_MODEL_VIEWER_H_
|
||||
#define _C3D_MODEL_VIEWER_H_
|
||||
|
||||
#include "3d_rendering/ctrack_ball.h"
|
||||
#include <gal/hidpi_gl_canvas.h>
|
||||
|
||||
class S3D_CACHE;
|
||||
class C_OGL_3DMODEL;
|
||||
|
||||
/**
|
||||
* Class C3D_MODEL_VIEWER
|
||||
* Implement a canvas based on a wxGLCanvas
|
||||
*/
|
||||
class C3D_MODEL_VIEWER : public HIDPI_GL_CANVAS
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new 3D Canvas with a attribute list
|
||||
* @param aParent = the parent creator of this canvas
|
||||
* @param aAttribList = a list of openGL options created by
|
||||
* COGL_ATT_LIST::GetAttributesList
|
||||
*/
|
||||
C3D_MODEL_VIEWER( wxWindow *aParent,
|
||||
const int *aAttribList = 0,
|
||||
S3D_CACHE *aCacheManager = NULL );
|
||||
|
||||
~C3D_MODEL_VIEWER();
|
||||
|
||||
/**
|
||||
* @brief Set3DModel - Set this model to be displayed
|
||||
* @param a3DModel - 3d model data
|
||||
*/
|
||||
void Set3DModel( const S3DMODEL &a3DModel );
|
||||
|
||||
/**
|
||||
* @brief Set3DModel - Set this model to be displayed
|
||||
* @param aModelPathName - 3d model path name
|
||||
*/
|
||||
void Set3DModel( wxString const& aModelPathName );
|
||||
|
||||
/**
|
||||
* @brief Clear3DModel - Unloads the displayed 3d model
|
||||
*/
|
||||
void Clear3DModel();
|
||||
|
||||
private:
|
||||
void ogl_initialize();
|
||||
void ogl_set_arrow_material();
|
||||
|
||||
private:
|
||||
|
||||
void OnPaint( wxPaintEvent &event );
|
||||
|
||||
void OnEraseBackground( wxEraseEvent &event );
|
||||
|
||||
void OnMouseWheel( wxMouseEvent &event );
|
||||
|
||||
#ifdef USE_OSX_MAGNIFY_EVENT
|
||||
void OnMagnify( wxMouseEvent& event );
|
||||
#endif
|
||||
|
||||
void OnMouseMove( wxMouseEvent &event );
|
||||
|
||||
void OnLeftDown( wxMouseEvent &event );
|
||||
|
||||
void OnLeftUp( wxMouseEvent &event );
|
||||
|
||||
void OnMiddleUp( wxMouseEvent &event );
|
||||
|
||||
void OnMiddleDown( wxMouseEvent &event );
|
||||
|
||||
void OnRightClick( wxMouseEvent &event );
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
||||
|
||||
private:
|
||||
/// openGL context
|
||||
wxGLContext *m_glRC;
|
||||
|
||||
/// Camera used in this canvas
|
||||
CTRACK_BALL m_trackBallCamera;
|
||||
|
||||
/// Original 3d model data
|
||||
const S3DMODEL *m_3d_model;
|
||||
|
||||
/// Class holder for 3d model to display on openGL
|
||||
C_OGL_3DMODEL *m_ogl_3dmodel;
|
||||
|
||||
/// Flag that we have a new model and it need to be reloaded when the paint is called
|
||||
bool m_reload_is_needed;
|
||||
|
||||
/// Flag if open gl was initialized
|
||||
bool m_ogl_initialized;
|
||||
|
||||
/// factor to convert the model or any other items to keep it in relation to
|
||||
/// the +/-RANGE_SCALE_3D
|
||||
/// (it is named same as the board render for better understanding proposes)
|
||||
double m_BiuTo3Dunits;
|
||||
|
||||
/// Optional cache manager
|
||||
S3D_CACHE* m_cacheManager;
|
||||
|
||||
/**
|
||||
* Trace mask used to enable or disable the trace output of this class.
|
||||
* The debug output can be turned on by setting the WXTRACE environment variable to
|
||||
* "KI_TRACE_EDA_3D_MODEL_VIEWER". See the wxWidgets documentation on wxLogTrace for
|
||||
* more information.
|
||||
*/
|
||||
static const wxChar *m_logTrace;
|
||||
};
|
||||
|
||||
#endif // _C3D_MODEL_VIEWER_H_
|
||||
@@ -1 +0,0 @@
|
||||
#define PLUGINDIR "@CMAKE_INSTALL_FULL_LIBDIR@"
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2012 Jean-Pierre Charras, jp.charras@wanadoo.fr
|
||||
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
|
||||
* Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_read_mesh.cpp
|
||||
*/
|
||||
|
||||
#include <fctsys.h>
|
||||
#include <common.h>
|
||||
#include <macros.h>
|
||||
#include <kicad_string.h>
|
||||
#include <pgm_base.h>
|
||||
|
||||
#include <3d_viewer.h>
|
||||
#include <info3d_visu.h>
|
||||
#include "3d_struct.h"
|
||||
#include "modelparsers.h"
|
||||
|
||||
|
||||
S3D_MODEL_PARSER* S3D_MODEL_PARSER::Create( S3D_MASTER* aMaster,
|
||||
const wxString aExtension )
|
||||
{
|
||||
if ( aExtension == wxT( "x3d" ) )
|
||||
{
|
||||
return new X3D_MODEL_PARSER( aMaster );
|
||||
}
|
||||
else if ( aExtension == wxT( "wrl" ) )
|
||||
{
|
||||
return new VRML_MODEL_PARSER( aMaster );
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const wxString S3D_MASTER::GetShape3DFullFilename()
|
||||
{
|
||||
|
||||
wxString shapeName;
|
||||
|
||||
// Expand any environment variables embedded in footprint's m_Shape3DName field.
|
||||
// To ensure compatibility with most of footprint's m_Shape3DName field,
|
||||
// if the m_Shape3DName is not an absolute path the default path
|
||||
// given by the environment variable KISYS3DMOD will be used
|
||||
|
||||
if( m_Shape3DName.StartsWith( wxT("${") ) )
|
||||
shapeName = wxExpandEnvVars( m_Shape3DName );
|
||||
else
|
||||
shapeName = m_Shape3DName;
|
||||
|
||||
wxFileName fn( shapeName );
|
||||
|
||||
if( fn.IsAbsolute() || shapeName.StartsWith( wxT(".") ) )
|
||||
return shapeName;
|
||||
|
||||
wxString default_path;
|
||||
wxGetEnv( wxT( KISYS3DMOD ), &default_path );
|
||||
|
||||
if( default_path.IsEmpty() )
|
||||
return shapeName;
|
||||
|
||||
if( !default_path.EndsWith( wxT("/") ) && !default_path.EndsWith( wxT("\\") ) )
|
||||
default_path += wxT("/");
|
||||
|
||||
default_path += shapeName;
|
||||
|
||||
return default_path;
|
||||
}
|
||||
|
||||
int S3D_MASTER::ReadData()
|
||||
{
|
||||
if( m_Shape3DName.IsEmpty() )
|
||||
return 1;
|
||||
|
||||
wxString filename = GetShape3DFullFilename();
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
filename.Replace( wxT( "/" ), wxT( "\\" ) );
|
||||
#else
|
||||
filename.Replace( wxT( "\\" ), wxT( "/" ) );
|
||||
#endif
|
||||
|
||||
if( !wxFileName::FileExists( filename ) )
|
||||
{
|
||||
wxLogDebug( wxT( "3D shape '%s' not found, even tried '%s' after env var substitution." ),
|
||||
GetChars( m_Shape3DName ),
|
||||
GetChars( filename )
|
||||
);
|
||||
return -1;
|
||||
}
|
||||
|
||||
wxFileName fn( filename );
|
||||
|
||||
wxString extension = fn.GetExt();
|
||||
S3D_MODEL_PARSER* parser = S3D_MODEL_PARSER::Create( this, extension );
|
||||
|
||||
if( parser )
|
||||
{
|
||||
parser->Load( filename );
|
||||
delete parser;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogDebug( wxT( "Unknown file type '%s'" ), GetChars( extension ) );
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
@@ -1,961 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file c3d_render_createscene_ogl_legacy.cpp
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#include "c3d_render_ogl_legacy.h"
|
||||
#include "ogl_legacy_utils.h"
|
||||
#include <class_board.h>
|
||||
#include <class_module.h>
|
||||
#include "../../3d_math.h"
|
||||
#include "../../3d_fastmath.h"
|
||||
#include <trigo.h>
|
||||
#include <project.h>
|
||||
#include <profile.h> // To use GetRunningMicroSecs or another profiling utility
|
||||
|
||||
|
||||
void C3D_RENDER_OGL_LEGACY::add_object_to_triangle_layer( const CFILLEDCIRCLE2D * aFilledCircle,
|
||||
CLAYER_TRIANGLES *aDstLayer,
|
||||
float aZtop,
|
||||
float aZbot )
|
||||
{
|
||||
const SFVEC2F ¢er = aFilledCircle->GetCenter();
|
||||
const float radius = aFilledCircle->GetRadius() *
|
||||
2.0f; // Double because the render triangle
|
||||
|
||||
// This is a small adjustment to the circle texture
|
||||
const float texture_factor = (8.0f / (float)SIZE_OF_CIRCLE_TEXTURE) + 1.0f;
|
||||
const float f = (sqrtf(2.0f) / 2.0f) * radius * texture_factor;
|
||||
|
||||
// Top and Bot segments ends are just triangle semi-circles, so need to add
|
||||
// it in duplicated
|
||||
aDstLayer->m_layer_top_segment_ends->AddTriangle( SFVEC3F( center.x + f, center.y, aZtop ),
|
||||
SFVEC3F( center.x - f, center.y, aZtop ),
|
||||
SFVEC3F( center.x,
|
||||
center.y - f, aZtop ) );
|
||||
|
||||
aDstLayer->m_layer_top_segment_ends->AddTriangle( SFVEC3F( center.x - f, center.y, aZtop ),
|
||||
SFVEC3F( center.x + f, center.y, aZtop ),
|
||||
SFVEC3F( center.x,
|
||||
center.y + f, aZtop ) );
|
||||
|
||||
aDstLayer->m_layer_bot_segment_ends->AddTriangle( SFVEC3F( center.x - f, center.y, aZbot ),
|
||||
SFVEC3F( center.x + f, center.y, aZbot ),
|
||||
SFVEC3F( center.x,
|
||||
center.y - f, aZbot ) );
|
||||
|
||||
aDstLayer->m_layer_bot_segment_ends->AddTriangle( SFVEC3F( center.x + f, center.y, aZbot ),
|
||||
SFVEC3F( center.x - f, center.y, aZbot ),
|
||||
SFVEC3F( center.x,
|
||||
center.y + f, aZbot ) );
|
||||
}
|
||||
|
||||
|
||||
void C3D_RENDER_OGL_LEGACY::add_object_to_triangle_layer( const CPOLYGON4PTS2D * aPoly,
|
||||
CLAYER_TRIANGLES *aDstLayer,
|
||||
float aZtop,
|
||||
float aZbot )
|
||||
{
|
||||
const SFVEC2F &v0 = aPoly->GetV0();
|
||||
const SFVEC2F &v1 = aPoly->GetV1();
|
||||
const SFVEC2F &v2 = aPoly->GetV2();
|
||||
const SFVEC2F &v3 = aPoly->GetV3();
|
||||
|
||||
add_triangle_top_bot( aDstLayer, v0, v2, v1, aZtop, aZbot );
|
||||
add_triangle_top_bot( aDstLayer, v2, v0, v3, aZtop, aZbot );
|
||||
}
|
||||
|
||||
|
||||
void C3D_RENDER_OGL_LEGACY::generate_ring_contour( const SFVEC2F &aCenter,
|
||||
float aInnerRadius,
|
||||
float aOuterRadius,
|
||||
unsigned int aNr_sides_per_circle,
|
||||
std::vector< SFVEC2F > &aInnerContourResult,
|
||||
std::vector< SFVEC2F > &aOuterContourResult,
|
||||
bool aInvertOrder )
|
||||
{
|
||||
aInnerContourResult.clear();
|
||||
aInnerContourResult.reserve( aNr_sides_per_circle + 2 );
|
||||
|
||||
aOuterContourResult.clear();
|
||||
aOuterContourResult.reserve( aNr_sides_per_circle + 2 );
|
||||
|
||||
const int delta = 3600 / aNr_sides_per_circle;
|
||||
|
||||
for( int ii = 0; ii < 3600; ii += delta )
|
||||
{
|
||||
float angle = (float)( aInvertOrder ? ( 3600 - ii ) : ii )
|
||||
* 2.0f * glm::pi<float>() / 3600.0f;
|
||||
const SFVEC2F rotatedDir = SFVEC2F( cos( angle ), sin( angle ) );
|
||||
|
||||
aInnerContourResult.push_back( SFVEC2F( aCenter.x + rotatedDir.x * aInnerRadius,
|
||||
aCenter.y + rotatedDir.y * aInnerRadius ) );
|
||||
|
||||
aOuterContourResult.push_back( SFVEC2F( aCenter.x + rotatedDir.x * aOuterRadius,
|
||||
aCenter.y + rotatedDir.y * aOuterRadius ) );
|
||||
}
|
||||
|
||||
aInnerContourResult.push_back( aInnerContourResult[0] );
|
||||
aOuterContourResult.push_back( aOuterContourResult[0] );
|
||||
|
||||
wxASSERT( aInnerContourResult.size() == aOuterContourResult.size() );
|
||||
}
|
||||
|
||||
|
||||
void C3D_RENDER_OGL_LEGACY::add_object_to_triangle_layer( const CRING2D * aRing,
|
||||
CLAYER_TRIANGLES *aDstLayer,
|
||||
float aZtop,
|
||||
float aZbot )
|
||||
{
|
||||
const SFVEC2F ¢er = aRing->GetCenter();
|
||||
const float inner = aRing->GetInnerRadius();
|
||||
const float outer = aRing->GetOuterRadius();
|
||||
|
||||
std::vector< SFVEC2F > innerContour;
|
||||
std::vector< SFVEC2F > outerContour;
|
||||
|
||||
generate_ring_contour( center,
|
||||
inner,
|
||||
outer,
|
||||
m_settings.GetNrSegmentsCircle( outer * 2.0f ),
|
||||
innerContour,
|
||||
outerContour,
|
||||
false );
|
||||
|
||||
// This will add the top and bot quads that will form the approximated ring
|
||||
|
||||
for( unsigned int i = 0; i < ( innerContour.size() - 1 ); ++i )
|
||||
{
|
||||
const SFVEC2F &vi0 = innerContour[i + 0];
|
||||
const SFVEC2F &vi1 = innerContour[i + 1];
|
||||
const SFVEC2F &vo0 = outerContour[i + 0];
|
||||
const SFVEC2F &vo1 = outerContour[i + 1];
|
||||
|
||||
aDstLayer->m_layer_top_triangles->AddQuad( SFVEC3F( vi1.x, vi1.y, aZtop ),
|
||||
SFVEC3F( vi0.x, vi0.y, aZtop ),
|
||||
SFVEC3F( vo0.x, vo0.y, aZtop ),
|
||||
SFVEC3F( vo1.x, vo1.y, aZtop ) );
|
||||
|
||||
aDstLayer->m_layer_bot_triangles->AddQuad( SFVEC3F( vi1.x, vi1.y, aZbot ),
|
||||
SFVEC3F( vo1.x, vo1.y, aZbot ),
|
||||
SFVEC3F( vo0.x, vo0.y, aZbot ),
|
||||
SFVEC3F( vi0.x, vi0.y, aZbot ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void C3D_RENDER_OGL_LEGACY::add_object_to_triangle_layer( const CTRIANGLE2D * aTri,
|
||||
CLAYER_TRIANGLES *aDstLayer,
|
||||
float aZtop,
|
||||
float aZbot )
|
||||
{
|
||||
const SFVEC2F &v1 = aTri->GetP1();
|
||||
const SFVEC2F &v2 = aTri->GetP2();
|
||||
const SFVEC2F &v3 = aTri->GetP3();
|
||||
|
||||
add_triangle_top_bot( aDstLayer, v1, v2, v3, aZtop, aZbot );
|
||||
}
|
||||
|
||||
|
||||
void C3D_RENDER_OGL_LEGACY::add_object_to_triangle_layer( const CROUNDSEGMENT2D * aSeg,
|
||||
CLAYER_TRIANGLES *aDstLayer,
|
||||
float aZtop,
|
||||
float aZbot )
|
||||
{
|
||||
const SFVEC2F leftStart = aSeg->GetLeftStar();
|
||||
const SFVEC2F leftEnd = aSeg->GetLeftEnd();
|
||||
const SFVEC2F leftDir = aSeg->GetLeftDir();
|
||||
|
||||
const SFVEC2F rightStart = aSeg->GetRightStar();
|
||||
const SFVEC2F rightEnd = aSeg->GetRightEnd();
|
||||
const SFVEC2F rightDir = aSeg->GetRightDir();
|
||||
const float radius = aSeg->GetRadius();
|
||||
|
||||
const SFVEC2F start = aSeg->GetStart();
|
||||
const SFVEC2F end = aSeg->GetEnd();
|
||||
|
||||
const float texture_factor = (12.0f / (float)SIZE_OF_CIRCLE_TEXTURE) + 1.0f;
|
||||
const float texture_factorF= ( 6.0f / (float)SIZE_OF_CIRCLE_TEXTURE) + 1.0f;
|
||||
|
||||
const float radius_of_the_square = sqrtf( aSeg->GetRadiusSquared() * 2.0f );
|
||||
const float radius_triangle_factor = (radius_of_the_square - radius) / radius;
|
||||
|
||||
const SFVEC2F factorS = SFVEC2F( -rightDir.y * radius * radius_triangle_factor,
|
||||
rightDir.x * radius * radius_triangle_factor );
|
||||
|
||||
const SFVEC2F factorE = SFVEC2F( -leftDir.y * radius * radius_triangle_factor,
|
||||
leftDir.x * radius * radius_triangle_factor );
|
||||
|
||||
// Top end segment triangles (semi-circles)
|
||||
aDstLayer->m_layer_top_segment_ends->AddTriangle(
|
||||
SFVEC3F( rightEnd.x + texture_factor * factorS.x,
|
||||
rightEnd.y + texture_factor * factorS.y,
|
||||
aZtop ),
|
||||
SFVEC3F( leftStart.x + texture_factor * factorE.x,
|
||||
leftStart.y + texture_factor * factorE.y,
|
||||
aZtop ),
|
||||
SFVEC3F( start.x - texture_factorF * leftDir.x * radius * sqrtf( 2.0f ),
|
||||
start.y - texture_factorF * leftDir.y * radius * sqrtf( 2.0f ),
|
||||
aZtop ) );
|
||||
|
||||
aDstLayer->m_layer_top_segment_ends->AddTriangle(
|
||||
SFVEC3F( leftEnd.x + texture_factor * factorE.x,
|
||||
leftEnd.y + texture_factor * factorE.y, aZtop ),
|
||||
SFVEC3F( rightStart.x + texture_factor * factorS.x,
|
||||
rightStart.y + texture_factor * factorS.y, aZtop ),
|
||||
SFVEC3F( end.x - texture_factorF * rightDir.x * radius * sqrtf( 2.0f ),
|
||||
end.y - texture_factorF * rightDir.y * radius * sqrtf( 2.0f ),
|
||||
aZtop ) );
|
||||
|
||||
// Bot end segment triangles (semi-circles)
|
||||
aDstLayer->m_layer_bot_segment_ends->AddTriangle(
|
||||
SFVEC3F( leftStart.x + texture_factor * factorE.x,
|
||||
leftStart.y + texture_factor * factorE.y,
|
||||
aZbot ),
|
||||
SFVEC3F( rightEnd.x + texture_factor * factorS.x,
|
||||
rightEnd.y + texture_factor * factorS.y,
|
||||
aZbot ),
|
||||
SFVEC3F( start.x - texture_factorF * leftDir.x * radius * sqrtf( 2.0f ),
|
||||
start.y - texture_factorF * leftDir.y * radius * sqrtf( 2.0f ),
|
||||
aZbot ) );
|
||||
|
||||
aDstLayer->m_layer_bot_segment_ends->AddTriangle(
|
||||
SFVEC3F( rightStart.x + texture_factor * factorS.x,
|
||||
rightStart.y + texture_factor * factorS.y, aZbot ),
|
||||
SFVEC3F( leftEnd.x + texture_factor * factorE.x,
|
||||
leftEnd.y + texture_factor * factorE.y, aZbot ),
|
||||
SFVEC3F( end.x - texture_factorF * rightDir.x * radius * sqrtf( 2.0f ),
|
||||
end.y - texture_factorF * rightDir.y * radius * sqrtf( 2.0f ),
|
||||
aZbot ) );
|
||||
|
||||
// Segment top and bot planes
|
||||
aDstLayer->m_layer_top_triangles->AddQuad(
|
||||
SFVEC3F( rightEnd.x, rightEnd.y, aZtop ),
|
||||
SFVEC3F( rightStart.x, rightStart.y, aZtop ),
|
||||
SFVEC3F( leftEnd.x, leftEnd.y, aZtop ),
|
||||
SFVEC3F( leftStart.x, leftStart.y, aZtop ) );
|
||||
|
||||
aDstLayer->m_layer_bot_triangles->AddQuad(
|
||||
SFVEC3F( rightEnd.x, rightEnd.y, aZbot ),
|
||||
SFVEC3F( leftStart.x, leftStart.y, aZbot ),
|
||||
SFVEC3F( leftEnd.x, leftEnd.y, aZbot ),
|
||||
SFVEC3F( rightStart.x, rightStart.y, aZbot ) );
|
||||
}
|
||||
|
||||
|
||||
CLAYERS_OGL_DISP_LISTS *C3D_RENDER_OGL_LEGACY::generate_holes_display_list(
|
||||
const LIST_OBJECT2D &aListHolesObject2d,
|
||||
const SHAPE_POLY_SET &aPoly,
|
||||
float aZtop,
|
||||
float aZbot,
|
||||
bool aInvertFaces )
|
||||
{
|
||||
CLAYERS_OGL_DISP_LISTS *ret = NULL;
|
||||
|
||||
if( aListHolesObject2d.size() > 0 )
|
||||
{
|
||||
CLAYER_TRIANGLES *layerTriangles = new CLAYER_TRIANGLES( aListHolesObject2d.size() * 2 );
|
||||
|
||||
// Convert the list of objects(filled circles) to triangle layer structure
|
||||
for( LIST_OBJECT2D::const_iterator itemOnLayer = aListHolesObject2d.begin();
|
||||
itemOnLayer != aListHolesObject2d.end();
|
||||
++itemOnLayer )
|
||||
{
|
||||
const COBJECT2D *object2d_A = static_cast<const COBJECT2D *>(*itemOnLayer);
|
||||
|
||||
wxASSERT( (object2d_A->GetObjectType() == OBJ2D_FILLED_CIRCLE) ||
|
||||
(object2d_A->GetObjectType() == OBJ2D_ROUNDSEG) );
|
||||
|
||||
switch( object2d_A->GetObjectType() )
|
||||
{
|
||||
case OBJ2D_FILLED_CIRCLE:
|
||||
add_object_to_triangle_layer( (const CFILLEDCIRCLE2D *)object2d_A,
|
||||
layerTriangles,
|
||||
aZtop, aZbot );
|
||||
break;
|
||||
|
||||
case OBJ2D_ROUNDSEG:
|
||||
add_object_to_triangle_layer( (const CROUNDSEGMENT2D *) object2d_A,
|
||||
layerTriangles,
|
||||
aZtop, aZbot );
|
||||
break;
|
||||
|
||||
default:
|
||||
wxFAIL_MSG("C3D_RENDER_OGL_LEGACY::generate_holes_display_list: Object type is not implemented");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Note: he can have a aListHolesObject2d whith holes but without countours
|
||||
// eg: when there are only NPTH on the list and the contours were not
|
||||
// added
|
||||
|
||||
if( aPoly.OutlineCount() > 0 )
|
||||
{
|
||||
layerTriangles->AddToMiddleContourns( aPoly,
|
||||
aZbot,
|
||||
aZtop,
|
||||
m_settings.BiuTo3Dunits(),
|
||||
aInvertFaces );
|
||||
}
|
||||
|
||||
ret = new CLAYERS_OGL_DISP_LISTS( *layerTriangles,
|
||||
m_ogl_circle_texture,
|
||||
aZbot,
|
||||
aZtop );
|
||||
|
||||
delete layerTriangles;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void C3D_RENDER_OGL_LEGACY::reload( REPORTER *aStatusTextReporter )
|
||||
{
|
||||
m_reloadRequested = false;
|
||||
|
||||
ogl_free_all_display_lists();
|
||||
|
||||
COBJECT2D_STATS::Instance().ResetStats();
|
||||
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
printf("InitSettings...\n");
|
||||
#endif
|
||||
|
||||
unsigned stats_startReloadTime = GetRunningMicroSecs();
|
||||
|
||||
m_settings.InitSettings( aStatusTextReporter );
|
||||
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
unsigned stats_endReloadTime = GetRunningMicroSecs();
|
||||
#endif
|
||||
|
||||
SFVEC3F camera_pos = m_settings.GetBoardCenter3DU();
|
||||
m_settings.CameraGet().SetBoardLookAtPos( camera_pos );
|
||||
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
unsigned stats_start_OpenGL_Load_Time = GetRunningMicroSecs();
|
||||
#endif
|
||||
|
||||
if( aStatusTextReporter )
|
||||
aStatusTextReporter->Report( _( "Load OpenGL: board" ) );
|
||||
|
||||
// Create Board
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CCONTAINER2D boardContainer;
|
||||
SHAPE_POLY_SET tmpBoard = m_settings.GetBoardPoly();
|
||||
Convert_shape_line_polygon_to_triangles( tmpBoard,
|
||||
boardContainer,
|
||||
m_settings.BiuTo3Dunits(),
|
||||
(const BOARD_ITEM &)*m_settings.GetBoard() );
|
||||
|
||||
const LIST_OBJECT2D &listBoardObject2d = boardContainer.GetList();
|
||||
|
||||
if( listBoardObject2d.size() > 0 )
|
||||
{
|
||||
// We will set a unitary Z so it will in future used with transformations
|
||||
// since the board poly will be used not only to draw itself but also the
|
||||
// solder mask layers.
|
||||
const float layer_z_top = 1.0f;
|
||||
const float layer_z_bot = 0.0f;
|
||||
|
||||
CLAYER_TRIANGLES *layerTriangles = new CLAYER_TRIANGLES( listBoardObject2d.size() );
|
||||
|
||||
// Convert the list of objects(triangles) to triangle layer structure
|
||||
for( LIST_OBJECT2D::const_iterator itemOnLayer = listBoardObject2d.begin();
|
||||
itemOnLayer != listBoardObject2d.end();
|
||||
++itemOnLayer )
|
||||
{
|
||||
const COBJECT2D *object2d_A = static_cast<const COBJECT2D *>(*itemOnLayer);
|
||||
|
||||
wxASSERT( object2d_A->GetObjectType() == OBJ2D_TRIANGLE );
|
||||
|
||||
const CTRIANGLE2D *tri = (const CTRIANGLE2D *)object2d_A;
|
||||
|
||||
const SFVEC2F &v1 = tri->GetP1();
|
||||
const SFVEC2F &v2 = tri->GetP2();
|
||||
const SFVEC2F &v3 = tri->GetP3();
|
||||
|
||||
add_triangle_top_bot( layerTriangles,
|
||||
v1,
|
||||
v2,
|
||||
v3,
|
||||
layer_z_top,
|
||||
layer_z_bot );
|
||||
}
|
||||
|
||||
const SHAPE_POLY_SET &boardPoly = m_settings.GetBoardPoly();
|
||||
|
||||
wxASSERT( boardPoly.OutlineCount() > 0 );
|
||||
|
||||
if( boardPoly.OutlineCount() > 0 )
|
||||
{
|
||||
layerTriangles->AddToMiddleContourns( boardPoly,
|
||||
layer_z_bot,
|
||||
layer_z_top,
|
||||
m_settings.BiuTo3Dunits(),
|
||||
false );
|
||||
|
||||
m_ogl_disp_list_board = new CLAYERS_OGL_DISP_LISTS( *layerTriangles,
|
||||
m_ogl_circle_texture,
|
||||
layer_z_top,
|
||||
layer_z_top );
|
||||
}
|
||||
|
||||
delete layerTriangles;
|
||||
}
|
||||
|
||||
// Create Through Holes and vias
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if( aStatusTextReporter )
|
||||
aStatusTextReporter->Report( _( "Load OpenGL: holes and vias" ) );
|
||||
|
||||
m_ogl_disp_list_through_holes_outer = generate_holes_display_list(
|
||||
m_settings.GetThroughHole_Outer().GetList(),
|
||||
m_settings.GetThroughHole_Outer_poly(),
|
||||
1.0f,
|
||||
0.0f,
|
||||
false );
|
||||
|
||||
SHAPE_POLY_SET bodyHoles = m_settings.GetThroughHole_Outer_poly();
|
||||
|
||||
bodyHoles.BooleanAdd( m_settings.GetThroughHole_Outer_poly_NPTH(),
|
||||
SHAPE_POLY_SET::PM_FAST );
|
||||
|
||||
m_ogl_disp_list_through_holes_outer_with_npth = generate_holes_display_list(
|
||||
m_settings.GetThroughHole_Outer().GetList(),
|
||||
bodyHoles,
|
||||
1.0f,
|
||||
0.0f,
|
||||
false );
|
||||
|
||||
m_ogl_disp_list_through_holes_inner = generate_holes_display_list(
|
||||
m_settings.GetThroughHole_Inner().GetList(),
|
||||
m_settings.GetThroughHole_Inner_poly(),
|
||||
1.0f,
|
||||
0.0f,
|
||||
true );
|
||||
|
||||
|
||||
m_ogl_disp_list_through_holes_vias_outer = generate_holes_display_list(
|
||||
m_settings.GetThroughHole_Vias_Outer().GetList(),
|
||||
m_settings.GetThroughHole_Vias_Outer_poly(),
|
||||
1.0f,
|
||||
0.0f,
|
||||
false );
|
||||
|
||||
// Not in use
|
||||
//m_ogl_disp_list_through_holes_vias_inner = generate_holes_display_list(
|
||||
// m_settings.GetThroughHole_Vias_Inner().GetList(),
|
||||
// m_settings.GetThroughHole_Vias_Inner_poly(),
|
||||
// 1.0f, 0.0f,
|
||||
// false );
|
||||
|
||||
const MAP_POLY & innerMapHoles = m_settings.GetPolyMapHoles_Inner();
|
||||
const MAP_POLY & outerMapHoles = m_settings.GetPolyMapHoles_Outer();
|
||||
|
||||
wxASSERT( innerMapHoles.size() == outerMapHoles.size() );
|
||||
|
||||
const MAP_CONTAINER_2D &map_holes = m_settings.GetMapLayersHoles();
|
||||
|
||||
if( outerMapHoles.size() > 0 )
|
||||
{
|
||||
float layer_z_bot = 0.0f;
|
||||
float layer_z_top = 0.0f;
|
||||
|
||||
for( MAP_POLY::const_iterator ii = outerMapHoles.begin();
|
||||
ii != outerMapHoles.end();
|
||||
++ii )
|
||||
{
|
||||
PCB_LAYER_ID layer_id = static_cast<PCB_LAYER_ID>(ii->first);
|
||||
const SHAPE_POLY_SET *poly = static_cast<const SHAPE_POLY_SET *>(ii->second);
|
||||
const CBVHCONTAINER2D *container = map_holes.at( layer_id );
|
||||
|
||||
get_layer_z_pos( layer_id, layer_z_top, layer_z_bot );
|
||||
|
||||
m_ogl_disp_lists_layers_holes_outer[layer_id] = generate_holes_display_list(
|
||||
container->GetList(), *poly, layer_z_top, layer_z_bot, false );
|
||||
}
|
||||
|
||||
for( MAP_POLY::const_iterator ii = innerMapHoles.begin();
|
||||
ii != innerMapHoles.end();
|
||||
++ii )
|
||||
{
|
||||
PCB_LAYER_ID layer_id = static_cast<PCB_LAYER_ID>(ii->first);
|
||||
const SHAPE_POLY_SET *poly = static_cast<const SHAPE_POLY_SET *>(ii->second);
|
||||
const CBVHCONTAINER2D *container = map_holes.at( layer_id );
|
||||
|
||||
get_layer_z_pos( layer_id, layer_z_top, layer_z_bot );
|
||||
|
||||
m_ogl_disp_lists_layers_holes_inner[layer_id] = generate_holes_display_list(
|
||||
container->GetList(), *poly, layer_z_top, layer_z_bot, false );
|
||||
}
|
||||
}
|
||||
|
||||
// Generate vertical cylinders of vias and pads (copper)
|
||||
generate_3D_Vias_and_Pads();
|
||||
|
||||
// Add layers maps
|
||||
|
||||
if( aStatusTextReporter )
|
||||
aStatusTextReporter->Report( _( "Load OpenGL: layers" ) );
|
||||
|
||||
for( MAP_CONTAINER_2D::const_iterator ii = m_settings.GetMapLayers().begin();
|
||||
ii != m_settings.GetMapLayers().end();
|
||||
++ii )
|
||||
{
|
||||
PCB_LAYER_ID layer_id = static_cast<PCB_LAYER_ID>(ii->first);
|
||||
|
||||
if( !m_settings.Is3DLayerEnabled( layer_id ) )
|
||||
continue;
|
||||
|
||||
const CBVHCONTAINER2D *container2d = static_cast<const CBVHCONTAINER2D *>(ii->second);
|
||||
const LIST_OBJECT2D &listObject2d = container2d->GetList();
|
||||
|
||||
if( listObject2d.size() == 0 )
|
||||
continue;
|
||||
|
||||
float layer_z_bot = 0.0f;
|
||||
float layer_z_top = 0.0f;
|
||||
|
||||
get_layer_z_pos( layer_id, layer_z_top, layer_z_bot );
|
||||
|
||||
// Calculate an estimation for the nr of triangles based on the nr of objects
|
||||
unsigned int nrTrianglesEstimation = listObject2d.size() * 8;
|
||||
|
||||
CLAYER_TRIANGLES *layerTriangles = new CLAYER_TRIANGLES( nrTrianglesEstimation );
|
||||
|
||||
m_triangles[layer_id] = layerTriangles;
|
||||
|
||||
// Load the 2D (X,Y axis) component of shapes
|
||||
for( LIST_OBJECT2D::const_iterator itemOnLayer = listObject2d.begin();
|
||||
itemOnLayer != listObject2d.end();
|
||||
++itemOnLayer )
|
||||
{
|
||||
const COBJECT2D *object2d_A = static_cast<const COBJECT2D *>(*itemOnLayer);
|
||||
|
||||
switch( object2d_A->GetObjectType() )
|
||||
{
|
||||
case OBJ2D_FILLED_CIRCLE:
|
||||
add_object_to_triangle_layer( (const CFILLEDCIRCLE2D *)object2d_A,
|
||||
layerTriangles, layer_z_top, layer_z_bot );
|
||||
break;
|
||||
|
||||
case OBJ2D_POLYGON4PT:
|
||||
add_object_to_triangle_layer( (const CPOLYGON4PTS2D *)object2d_A,
|
||||
layerTriangles, layer_z_top, layer_z_bot );
|
||||
break;
|
||||
|
||||
case OBJ2D_RING:
|
||||
add_object_to_triangle_layer( (const CRING2D *)object2d_A,
|
||||
layerTriangles, layer_z_top, layer_z_bot );
|
||||
break;
|
||||
|
||||
case OBJ2D_TRIANGLE:
|
||||
add_object_to_triangle_layer( (const CTRIANGLE2D *)object2d_A,
|
||||
layerTriangles, layer_z_top, layer_z_bot );
|
||||
break;
|
||||
|
||||
case OBJ2D_ROUNDSEG:
|
||||
add_object_to_triangle_layer( (const CROUNDSEGMENT2D *) object2d_A,
|
||||
layerTriangles, layer_z_top, layer_z_bot );
|
||||
break;
|
||||
|
||||
default:
|
||||
wxFAIL_MSG("C3D_RENDER_OGL_LEGACY: Object type is not implemented");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const MAP_POLY &map_poly = m_settings.GetPolyMap();
|
||||
|
||||
// Load the vertical (Z axis) component of shapes
|
||||
if( map_poly.find( layer_id ) != map_poly.end() )
|
||||
{
|
||||
const SHAPE_POLY_SET *polyList = map_poly.at( layer_id );
|
||||
|
||||
if( polyList->OutlineCount() > 0 )
|
||||
layerTriangles->AddToMiddleContourns( *polyList, layer_z_bot, layer_z_top,
|
||||
m_settings.BiuTo3Dunits(), false );
|
||||
}
|
||||
|
||||
// Create display list
|
||||
// /////////////////////////////////////////////////////////////////////
|
||||
m_ogl_disp_lists_layers[layer_id] = new CLAYERS_OGL_DISP_LISTS( *layerTriangles,
|
||||
m_ogl_circle_texture,
|
||||
layer_z_bot,
|
||||
layer_z_top );
|
||||
}// for each layer on map
|
||||
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
unsigned stats_end_OpenGL_Load_Time = GetRunningMicroSecs();
|
||||
#endif
|
||||
|
||||
// Load 3D models
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
unsigned stats_start_models_Load_Time = GetRunningMicroSecs();
|
||||
#endif
|
||||
|
||||
if( aStatusTextReporter )
|
||||
aStatusTextReporter->Report( _( "Loading 3D models" ) );
|
||||
|
||||
load_3D_models( aStatusTextReporter );
|
||||
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
unsigned stats_end_models_Load_Time = GetRunningMicroSecs();
|
||||
|
||||
|
||||
printf( "C3D_RENDER_OGL_LEGACY::reload times:\n" );
|
||||
printf( " Reload board: %.3f ms\n",
|
||||
(float)( stats_endReloadTime - stats_startReloadTime ) / 1000.0f );
|
||||
printf( " Loading to openGL: %.3f ms\n",
|
||||
(float)( stats_end_OpenGL_Load_Time - stats_start_OpenGL_Load_Time ) / 1000.0f );
|
||||
printf( " Loading 3D models: %.3f ms\n",
|
||||
(float)( stats_end_models_Load_Time - stats_start_models_Load_Time ) / 1000.0f );
|
||||
COBJECT2D_STATS::Instance().PrintStats();
|
||||
#endif
|
||||
|
||||
if( aStatusTextReporter )
|
||||
{
|
||||
// Calculation time in seconds
|
||||
const double calculation_time = (double)( GetRunningMicroSecs() -
|
||||
stats_startReloadTime) / 1e6;
|
||||
|
||||
aStatusTextReporter->Report( wxString::Format( _( "Reload time %.3f s" ),
|
||||
calculation_time ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void C3D_RENDER_OGL_LEGACY::add_triangle_top_bot( CLAYER_TRIANGLES *aDst,
|
||||
const SFVEC2F &v0,
|
||||
const SFVEC2F &v1,
|
||||
const SFVEC2F &v2,
|
||||
float top,
|
||||
float bot )
|
||||
{
|
||||
aDst->m_layer_bot_triangles->AddTriangle( SFVEC3F( v0.x, v0.y, bot ),
|
||||
SFVEC3F( v1.x, v1.y, bot ),
|
||||
SFVEC3F( v2.x, v2.y, bot ) );
|
||||
|
||||
aDst->m_layer_top_triangles->AddTriangle( SFVEC3F( v2.x, v2.y, top ),
|
||||
SFVEC3F( v1.x, v1.y, top ),
|
||||
SFVEC3F( v0.x, v0.y, top ) );
|
||||
}
|
||||
|
||||
|
||||
void C3D_RENDER_OGL_LEGACY::get_layer_z_pos ( PCB_LAYER_ID aLayerID,
|
||||
float &aOutZtop,
|
||||
float &aOutZbot ) const
|
||||
{
|
||||
aOutZbot = m_settings.GetLayerBottomZpos3DU( aLayerID );
|
||||
aOutZtop = m_settings.GetLayerTopZpos3DU( aLayerID );
|
||||
|
||||
if( aOutZtop < aOutZbot )
|
||||
{
|
||||
float tmpFloat = aOutZbot;
|
||||
aOutZbot = aOutZtop;
|
||||
aOutZtop = tmpFloat;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void C3D_RENDER_OGL_LEGACY::generate_cylinder( const SFVEC2F &aCenter,
|
||||
float aInnerRadius,
|
||||
float aOuterRadius,
|
||||
float aZtop,
|
||||
float aZbot,
|
||||
unsigned int aNr_sides_per_circle,
|
||||
CLAYER_TRIANGLES *aDstLayer )
|
||||
{
|
||||
std::vector< SFVEC2F > innerContour;
|
||||
std::vector< SFVEC2F > outerContour;
|
||||
|
||||
generate_ring_contour( aCenter,
|
||||
aInnerRadius,
|
||||
aOuterRadius,
|
||||
aNr_sides_per_circle,
|
||||
innerContour,
|
||||
outerContour,
|
||||
false );
|
||||
|
||||
for( unsigned int i = 0; i < ( innerContour.size() - 1 ); ++i )
|
||||
{
|
||||
const SFVEC2F &vi0 = innerContour[i + 0];
|
||||
const SFVEC2F &vi1 = innerContour[i + 1];
|
||||
const SFVEC2F &vo0 = outerContour[i + 0];
|
||||
const SFVEC2F &vo1 = outerContour[i + 1];
|
||||
|
||||
aDstLayer->m_layer_top_triangles->AddQuad( SFVEC3F( vi1.x, vi1.y, aZtop ),
|
||||
SFVEC3F( vi0.x, vi0.y, aZtop ),
|
||||
SFVEC3F( vo0.x, vo0.y, aZtop ),
|
||||
SFVEC3F( vo1.x, vo1.y, aZtop ) );
|
||||
|
||||
aDstLayer->m_layer_bot_triangles->AddQuad( SFVEC3F( vi1.x, vi1.y, aZbot ),
|
||||
SFVEC3F( vo1.x, vo1.y, aZbot ),
|
||||
SFVEC3F( vo0.x, vo0.y, aZbot ),
|
||||
SFVEC3F( vi0.x, vi0.y, aZbot ) );
|
||||
}
|
||||
|
||||
aDstLayer->AddToMiddleContourns( outerContour, aZbot, aZtop, true );
|
||||
aDstLayer->AddToMiddleContourns( innerContour, aZbot, aZtop, false );
|
||||
}
|
||||
|
||||
|
||||
void C3D_RENDER_OGL_LEGACY::generate_3D_Vias_and_Pads()
|
||||
{
|
||||
if( m_settings.GetStats_Nr_Vias() )
|
||||
{
|
||||
const unsigned int reserve_nr_triangles_estimation =
|
||||
m_settings.GetNrSegmentsCircle( m_settings.GetStats_Med_Via_Hole_Diameter3DU() ) *
|
||||
8 *
|
||||
m_settings.GetStats_Nr_Vias();
|
||||
|
||||
CLAYER_TRIANGLES *layerTriangleVIA = new CLAYER_TRIANGLES( reserve_nr_triangles_estimation );
|
||||
|
||||
// Insert plated vertical holes inside the board
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Insert vias holes (vertical cylinders)
|
||||
for( const TRACK* track = m_settings.GetBoard()->m_Track;
|
||||
track;
|
||||
track = track->Next() )
|
||||
{
|
||||
if( track->Type() == PCB_VIA_T )
|
||||
{
|
||||
const VIA *via = static_cast<const VIA*>(track);
|
||||
|
||||
const float holediameter = via->GetDrillValue() * m_settings.BiuTo3Dunits();
|
||||
const float thickness = m_settings.GetCopperThickness3DU();
|
||||
const int nrSegments = m_settings.GetNrSegmentsCircle( via->GetDrillValue() );
|
||||
const double correctionFactor = m_settings.GetCircleCorrectionFactor( nrSegments );
|
||||
const float hole_inner_radius = ( holediameter / 2.0f ) * correctionFactor;
|
||||
|
||||
const SFVEC2F via_center( via->GetStart().x * m_settings.BiuTo3Dunits(),
|
||||
-via->GetStart().y * m_settings.BiuTo3Dunits() );
|
||||
|
||||
PCB_LAYER_ID top_layer, bottom_layer;
|
||||
via->LayerPair( &top_layer, &bottom_layer );
|
||||
|
||||
float ztop, zbot, dummy;
|
||||
|
||||
get_layer_z_pos( top_layer, ztop, dummy );
|
||||
get_layer_z_pos( bottom_layer, dummy, zbot );
|
||||
|
||||
wxASSERT( zbot < ztop );
|
||||
|
||||
generate_cylinder( via_center,
|
||||
hole_inner_radius,
|
||||
hole_inner_radius + thickness,
|
||||
ztop,
|
||||
zbot,
|
||||
nrSegments,
|
||||
layerTriangleVIA );
|
||||
}
|
||||
}
|
||||
|
||||
m_ogl_disp_list_via = new CLAYERS_OGL_DISP_LISTS( *layerTriangleVIA,
|
||||
0,
|
||||
0.0f,
|
||||
0.0f );
|
||||
|
||||
delete layerTriangleVIA;
|
||||
}
|
||||
|
||||
|
||||
if( m_settings.GetStats_Nr_Holes() > 0 )
|
||||
{
|
||||
SHAPE_POLY_SET tht_outer_holes_poly; // Stores the outer poly of the copper holes (the pad)
|
||||
SHAPE_POLY_SET tht_inner_holes_poly; // Stores the inner poly of the copper holes (the hole)
|
||||
|
||||
tht_outer_holes_poly.RemoveAllContours();
|
||||
tht_inner_holes_poly.RemoveAllContours();
|
||||
|
||||
// Insert pads holes (vertical cylinders)
|
||||
for( const MODULE* module = m_settings.GetBoard()->m_Modules;
|
||||
module;
|
||||
module = module->Next() )
|
||||
{
|
||||
for( const D_PAD* pad = module->PadsList(); pad; pad = pad->Next() )
|
||||
{
|
||||
if( pad->GetAttribute() != PAD_ATTRIB_HOLE_NOT_PLATED )
|
||||
{
|
||||
const wxSize drillsize = pad->GetDrillSize();
|
||||
const bool hasHole = drillsize.x && drillsize.y;
|
||||
|
||||
if( !hasHole )
|
||||
continue;
|
||||
|
||||
// we use the hole diameter to calculate the seg count.
|
||||
// for round holes, drillsize.x == drillsize.y
|
||||
// for slots, the diameter is the smaller of (drillsize.x, drillsize.y)
|
||||
int copperThickness = m_settings.GetCopperThicknessBIU();
|
||||
int radius = std::min( drillsize.x, drillsize.y ) / 2 + copperThickness;
|
||||
int nrSegments = m_settings.GetNrSegmentsCircle( radius * 2 );
|
||||
double correctionFactor = m_settings.GetCircleCorrectionFactor( nrSegments );
|
||||
int correction = radius * ( correctionFactor - 1 );
|
||||
|
||||
pad->BuildPadDrillShapePolygon( tht_outer_holes_poly,
|
||||
copperThickness + correction,
|
||||
nrSegments );
|
||||
|
||||
pad->BuildPadDrillShapePolygon( tht_inner_holes_poly,
|
||||
correction,
|
||||
nrSegments );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Subtract the holes
|
||||
tht_outer_holes_poly.BooleanSubtract( tht_inner_holes_poly, SHAPE_POLY_SET::PM_FAST );
|
||||
|
||||
|
||||
CCONTAINER2D holesContainer;
|
||||
|
||||
Convert_shape_line_polygon_to_triangles( tht_outer_holes_poly,
|
||||
holesContainer,
|
||||
m_settings.BiuTo3Dunits(),
|
||||
(const BOARD_ITEM &)*m_settings.GetBoard() );
|
||||
|
||||
const LIST_OBJECT2D &listHolesObject2d = holesContainer.GetList();
|
||||
|
||||
if( listHolesObject2d.size() > 0 )
|
||||
{
|
||||
float layer_z_top, layer_z_bot, dummy;
|
||||
|
||||
get_layer_z_pos( F_Cu, layer_z_top, dummy );
|
||||
get_layer_z_pos( B_Cu, dummy, layer_z_bot );
|
||||
|
||||
CLAYER_TRIANGLES *layerTriangles = new CLAYER_TRIANGLES( listHolesObject2d.size() );
|
||||
|
||||
// Convert the list of objects(triangles) to triangle layer structure
|
||||
for( LIST_OBJECT2D::const_iterator itemOnLayer = listHolesObject2d.begin();
|
||||
itemOnLayer != listHolesObject2d.end();
|
||||
++itemOnLayer )
|
||||
{
|
||||
const COBJECT2D *object2d_A = static_cast<const COBJECT2D *>(*itemOnLayer);
|
||||
|
||||
wxASSERT( object2d_A->GetObjectType() == OBJ2D_TRIANGLE );
|
||||
|
||||
const CTRIANGLE2D *tri = (const CTRIANGLE2D *)object2d_A;
|
||||
|
||||
const SFVEC2F &v1 = tri->GetP1();
|
||||
const SFVEC2F &v2 = tri->GetP2();
|
||||
const SFVEC2F &v3 = tri->GetP3();
|
||||
|
||||
add_triangle_top_bot( layerTriangles, v1, v2, v3,
|
||||
layer_z_top, layer_z_bot );
|
||||
}
|
||||
|
||||
wxASSERT( tht_outer_holes_poly.OutlineCount() > 0 );
|
||||
|
||||
if( tht_outer_holes_poly.OutlineCount() > 0 )
|
||||
{
|
||||
layerTriangles->AddToMiddleContourns( tht_outer_holes_poly,
|
||||
layer_z_bot, layer_z_top,
|
||||
m_settings.BiuTo3Dunits(),
|
||||
false );
|
||||
|
||||
m_ogl_disp_list_pads_holes = new CLAYERS_OGL_DISP_LISTS(
|
||||
*layerTriangles,
|
||||
m_ogl_circle_texture, // not need
|
||||
layer_z_top, layer_z_top );
|
||||
}
|
||||
|
||||
delete layerTriangles;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This function will get models from the cache and load it to openGL lists
|
||||
* in the form of C_OGL_3DMODEL. So this map of models will work as a local
|
||||
* cache for this render. (cache based on C_OGL_3DMODEL with associated
|
||||
* openGL lists in GPU memory)
|
||||
*/
|
||||
void C3D_RENDER_OGL_LEGACY::load_3D_models( REPORTER *aStatusTextReporter )
|
||||
{
|
||||
if( (!m_settings.GetFlag( FL_MODULE_ATTRIBUTES_NORMAL )) &&
|
||||
(!m_settings.GetFlag( FL_MODULE_ATTRIBUTES_NORMAL_INSERT )) &&
|
||||
(!m_settings.GetFlag( FL_MODULE_ATTRIBUTES_VIRTUAL )) )
|
||||
return;
|
||||
|
||||
// Go for all modules
|
||||
for( const MODULE* module = m_settings.GetBoard()->m_Modules;
|
||||
module; module = module->Next() )
|
||||
{
|
||||
if( !module->Models().empty() )
|
||||
{
|
||||
// Get the list of model files for this model
|
||||
auto sM = module->Models().begin();
|
||||
auto eM = module->Models().end();
|
||||
|
||||
while( sM != eM )
|
||||
{
|
||||
if( !sM->m_Filename.empty() )
|
||||
{
|
||||
if( aStatusTextReporter )
|
||||
{
|
||||
// Display the short filename of the 3D model loaded:
|
||||
// (the full name is usually too long to be displayed)
|
||||
wxFileName fn( sM->m_Filename );
|
||||
wxString msg;
|
||||
msg.Printf( _( "Loading %s" ), fn.GetFullName() );
|
||||
aStatusTextReporter->Report( msg );
|
||||
}
|
||||
|
||||
// Check if the model is not present in our cache map
|
||||
// (Not already loaded in memory)
|
||||
if( m_3dmodel_map.find( sM->m_Filename ) == m_3dmodel_map.end() )
|
||||
{
|
||||
// It is not present, try get it from cache
|
||||
const S3DMODEL *modelPtr =
|
||||
m_settings.Get3DCacheManager()->GetModel( sM->m_Filename );
|
||||
|
||||
// only add it if the return is not NULL
|
||||
if( modelPtr )
|
||||
{
|
||||
C_OGL_3DMODEL* ogl_model =
|
||||
new C_OGL_3DMODEL( *modelPtr,
|
||||
m_settings.MaterialModeGet() );
|
||||
|
||||
if( ogl_model )
|
||||
m_3dmodel_map[ sM->m_Filename ] = ogl_model;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
++sM;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,221 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file c3d_render_ogl_legacy.h
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef C3D_RENDER_OGL_LEGACY_H_
|
||||
#define C3D_RENDER_OGL_LEGACY_H_
|
||||
|
||||
#include "../c3d_render_base.h"
|
||||
#include "clayer_triangles.h"
|
||||
|
||||
#include "../3d_render_raytracing/shapes2D/cpolygon2d.h"
|
||||
#include "../3d_render_raytracing/shapes2D/ctriangle2d.h"
|
||||
#include "../3d_render_raytracing/shapes2D/cpolygon4pts2d.h"
|
||||
#include "../3d_render_raytracing/shapes2D/cfilledcircle2d.h"
|
||||
#include "../3d_render_raytracing/shapes2D/cring2d.h"
|
||||
#include "../3d_render_raytracing/shapes2D/croundsegment2d.h"
|
||||
|
||||
#include "c_ogl_3dmodel.h"
|
||||
|
||||
#include "3d_cache/3d_info.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
|
||||
typedef std::map< PCB_LAYER_ID, CLAYERS_OGL_DISP_LISTS* > MAP_OGL_DISP_LISTS;
|
||||
typedef std::map< PCB_LAYER_ID, CLAYER_TRIANGLES * > MAP_TRIANGLES;
|
||||
typedef std::map< wxString, C_OGL_3DMODEL * > MAP_3DMODEL;
|
||||
|
||||
#define SIZE_OF_CIRCLE_TEXTURE 1024
|
||||
|
||||
/**
|
||||
* @brief The C3D_RENDER_OGL_LEGACY class render the board using openGL legacy mode
|
||||
*/
|
||||
class C3D_RENDER_OGL_LEGACY : public C3D_RENDER_BASE
|
||||
{
|
||||
public:
|
||||
explicit C3D_RENDER_OGL_LEGACY( CINFO3D_VISU &aSettings );
|
||||
|
||||
~C3D_RENDER_OGL_LEGACY();
|
||||
|
||||
// Imported from C3D_RENDER_BASE
|
||||
void SetCurWindowSize( const wxSize &aSize ) override;
|
||||
bool Redraw( bool aIsMoving, REPORTER *aStatusTextReporter ) override;
|
||||
|
||||
int GetWaitForEditingTimeOut() override;
|
||||
|
||||
private:
|
||||
bool initializeOpenGL();
|
||||
void reload( REPORTER *aStatusTextReporter );
|
||||
|
||||
void ogl_set_arrow_material();
|
||||
|
||||
void ogl_free_all_display_lists();
|
||||
MAP_OGL_DISP_LISTS m_ogl_disp_lists_layers;
|
||||
MAP_OGL_DISP_LISTS m_ogl_disp_lists_layers_holes_outer;
|
||||
MAP_OGL_DISP_LISTS m_ogl_disp_lists_layers_holes_inner;
|
||||
CLAYERS_OGL_DISP_LISTS* m_ogl_disp_list_board;
|
||||
CLAYERS_OGL_DISP_LISTS* m_ogl_disp_list_through_holes_outer;
|
||||
CLAYERS_OGL_DISP_LISTS* m_ogl_disp_list_through_holes_inner;
|
||||
|
||||
// User for body render
|
||||
CLAYERS_OGL_DISP_LISTS* m_ogl_disp_list_through_holes_outer_with_npth;
|
||||
|
||||
CLAYERS_OGL_DISP_LISTS* m_ogl_disp_list_through_holes_vias_outer;
|
||||
//CLAYERS_OGL_DISP_LISTS* m_ogl_disp_list_through_holes_vias_inner; // Not in use
|
||||
|
||||
// This is for pads holes of the modules
|
||||
//CLAYERS_OGL_DISP_LISTS* m_ogl_disp_list_vias_and_pad_holes_inner_contourn_and_caps;
|
||||
CLAYERS_OGL_DISP_LISTS* m_ogl_disp_list_vias_and_pad_holes_outer_contourn_and_caps;
|
||||
|
||||
MAP_TRIANGLES m_triangles;
|
||||
|
||||
GLuint m_ogl_circle_texture;
|
||||
|
||||
GLuint m_ogl_disp_list_grid; ///< oGL list that stores current grid
|
||||
|
||||
GRID3D_TYPE m_last_grid_type; ///< Stores the last grid computed
|
||||
|
||||
CLAYERS_OGL_DISP_LISTS* m_ogl_disp_list_via;
|
||||
CLAYERS_OGL_DISP_LISTS* m_ogl_disp_list_pads_holes;
|
||||
|
||||
MAP_3DMODEL m_3dmodel_map;
|
||||
|
||||
private:
|
||||
void generate_through_outer_holes();
|
||||
void generate_through_inner_holes();
|
||||
|
||||
CLAYERS_OGL_DISP_LISTS *generate_holes_display_list( const LIST_OBJECT2D &aListHolesObject2d,
|
||||
const SHAPE_POLY_SET &aPoly,
|
||||
float aZtop,
|
||||
float aZbot,
|
||||
bool aInvertFaces );
|
||||
|
||||
void add_triangle_top_bot( CLAYER_TRIANGLES *aDst,
|
||||
const SFVEC2F &v0,
|
||||
const SFVEC2F &v1,
|
||||
const SFVEC2F &v2,
|
||||
float top,
|
||||
float bot );
|
||||
|
||||
void add_object_to_triangle_layer( const CRING2D *aRing,
|
||||
CLAYER_TRIANGLES *aDstLayer,
|
||||
float aZtop,
|
||||
float aZbot );
|
||||
|
||||
void add_object_to_triangle_layer( const CPOLYGON4PTS2D *aPoly,
|
||||
CLAYER_TRIANGLES *aDstLayer,
|
||||
float aZtop,
|
||||
float aZbot );
|
||||
|
||||
void add_object_to_triangle_layer( const CFILLEDCIRCLE2D *aFilledCircle,
|
||||
CLAYER_TRIANGLES *aDstLayer,
|
||||
float aZtop,
|
||||
float aZbot );
|
||||
|
||||
void add_object_to_triangle_layer( const CTRIANGLE2D *aTri,
|
||||
CLAYER_TRIANGLES *aDstLayer,
|
||||
float aZtop,
|
||||
float aZbot );
|
||||
|
||||
void add_object_to_triangle_layer( const CROUNDSEGMENT2D *aSeg,
|
||||
CLAYER_TRIANGLES *aDstLayer,
|
||||
float aZtop,
|
||||
float aZbot );
|
||||
|
||||
void render_solder_mask_layer( PCB_LAYER_ID aLayerID,
|
||||
float aZPosition,
|
||||
bool aIsRenderingOnPreviewMode );
|
||||
|
||||
void get_layer_z_pos( PCB_LAYER_ID aLayerID,
|
||||
float &aOutZtop,
|
||||
float &aOutZbot ) const;
|
||||
|
||||
void generate_ring_contour( const SFVEC2F &aCenter,
|
||||
float aInnerRadius,
|
||||
float aOuterRadius,
|
||||
unsigned int aNr_sides_per_circle,
|
||||
std::vector< SFVEC2F > &aInnerContourResult,
|
||||
std::vector< SFVEC2F > &aOuterContourResult,
|
||||
bool aInvertOrder );
|
||||
|
||||
void generate_cylinder( const SFVEC2F &aCenter,
|
||||
float aInnerRadius,
|
||||
float aOuterRadius,
|
||||
float aZtop,
|
||||
float aZbot,
|
||||
unsigned int aNr_sides_per_circle,
|
||||
CLAYER_TRIANGLES *aDstLayer );
|
||||
|
||||
void generate_3D_Vias_and_Pads();
|
||||
|
||||
void load_3D_models( REPORTER *aStatusTextReporter );
|
||||
|
||||
/**
|
||||
* @brief render_3D_models
|
||||
* @param aRenderTopOrBot - true will render Top, false will render bottom
|
||||
* @param aRenderTransparentOnly - true will render only the transparent
|
||||
* objects, false will render opaque
|
||||
*/
|
||||
void render_3D_models( bool aRenderTopOrBot, bool aRenderTransparentOnly );
|
||||
|
||||
void render_3D_module( const MODULE* module, bool aRenderTransparentOnly );
|
||||
|
||||
void setLight_Front( bool enabled );
|
||||
void setLight_Top( bool enabled );
|
||||
void setLight_Bottom( bool enabled );
|
||||
|
||||
void render_3D_arrows();
|
||||
|
||||
void generate_new_3DGrid( GRID3D_TYPE aGridType );
|
||||
|
||||
// Materials
|
||||
void setupMaterials();
|
||||
|
||||
struct
|
||||
{
|
||||
SMATERIAL m_Paste;
|
||||
SMATERIAL m_SilkS;
|
||||
SMATERIAL m_SolderMask;
|
||||
SMATERIAL m_EpoxyBoard;
|
||||
SMATERIAL m_Copper;
|
||||
SMATERIAL m_Plastic;
|
||||
SMATERIAL m_GrayMaterial;
|
||||
}m_materials;
|
||||
|
||||
void set_layer_material( PCB_LAYER_ID aLayerID );
|
||||
SFVEC3F get_layer_color( PCB_LAYER_ID aLayerID );
|
||||
|
||||
public:
|
||||
const MAP_OGL_DISP_LISTS &GetLayerDispListMap() const { return m_ogl_disp_lists_layers; }
|
||||
const CLAYERS_OGL_DISP_LISTS *GetLayerDispList( PCB_LAYER_ID aLayerId ) const { return m_ogl_disp_lists_layers.at( aLayerId ); }
|
||||
const CLAYERS_OGL_DISP_LISTS *GetBoardDispList() const { return m_ogl_disp_list_board; }
|
||||
};
|
||||
|
||||
#endif // C3D_RENDER_OGL_LEGACY_H_
|
||||
|
||||
@@ -1,383 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file c_ogl_3dmodel.cpp
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#include "c_ogl_3dmodel.h"
|
||||
#include "ogl_legacy_utils.h"
|
||||
#include "../common_ogl/ogl_utils.h"
|
||||
#include "../3d_math.h"
|
||||
#include <wx/debug.h>
|
||||
|
||||
|
||||
C_OGL_3DMODEL::C_OGL_3DMODEL( const S3DMODEL &a3DModel,
|
||||
MATERIAL_MODE aMaterialMode )
|
||||
{
|
||||
m_ogl_idx_list_meshes = 0;
|
||||
m_ogl_idx_list_opaque = 0;
|
||||
m_ogl_idx_list_transparent = 0;
|
||||
m_nr_meshes = 0;
|
||||
m_meshs_bbox = NULL;
|
||||
|
||||
// Validate a3DModel pointers
|
||||
wxASSERT( a3DModel.m_Materials != NULL );
|
||||
wxASSERT( a3DModel.m_Meshes != NULL );
|
||||
wxASSERT( a3DModel.m_MaterialsSize > 0 );
|
||||
wxASSERT( a3DModel.m_MeshesSize > 0 );
|
||||
|
||||
if( (a3DModel.m_Materials != NULL) && (a3DModel.m_Meshes != NULL) &&
|
||||
(a3DModel.m_MaterialsSize > 0) && (a3DModel.m_MeshesSize > 0) )
|
||||
{
|
||||
m_nr_meshes = a3DModel.m_MeshesSize;
|
||||
|
||||
m_meshs_bbox = new CBBOX[a3DModel.m_MeshesSize];
|
||||
|
||||
// Generate m_MeshesSize auxiliar lists to render the meshes
|
||||
m_ogl_idx_list_meshes = glGenLists( a3DModel.m_MeshesSize );
|
||||
|
||||
// Render each mesh of the model
|
||||
// /////////////////////////////////////////////////////////////////////
|
||||
for( unsigned int mesh_i = 0; mesh_i < a3DModel.m_MeshesSize; ++mesh_i )
|
||||
{
|
||||
if( glIsList( m_ogl_idx_list_meshes + mesh_i ) )
|
||||
{
|
||||
const SMESH &mesh = a3DModel.m_Meshes[mesh_i];
|
||||
|
||||
// Validate the mesh pointers
|
||||
wxASSERT( mesh.m_Positions != NULL );
|
||||
wxASSERT( mesh.m_FaceIdx != NULL );
|
||||
wxASSERT( mesh.m_Normals != NULL );
|
||||
|
||||
if( (mesh.m_Positions != NULL) &&
|
||||
(mesh.m_Normals != NULL) &&
|
||||
(mesh.m_FaceIdx != NULL) &&
|
||||
(mesh.m_FaceIdxSize > 0) && (mesh.m_VertexSize > 0) )
|
||||
{
|
||||
SFVEC4F *pColorRGBA = NULL;
|
||||
|
||||
// Create the bbox for this mesh
|
||||
// /////////////////////////////////////////////////////////
|
||||
m_meshs_bbox[mesh_i].Reset();
|
||||
|
||||
for( unsigned int vertex_i = 0;
|
||||
vertex_i < mesh.m_VertexSize;
|
||||
++vertex_i )
|
||||
{
|
||||
m_meshs_bbox[mesh_i].Union( mesh.m_Positions[vertex_i] );
|
||||
}
|
||||
|
||||
// Make sure we start with client state disabled
|
||||
// /////////////////////////////////////////////////////////
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
glDisableClientState( GL_COLOR_ARRAY );
|
||||
|
||||
|
||||
// Enable arrays client states
|
||||
// /////////////////////////////////////////////////////////
|
||||
glEnableClientState( GL_VERTEX_ARRAY );
|
||||
glEnableClientState( GL_NORMAL_ARRAY );
|
||||
|
||||
glVertexPointer( 3, GL_FLOAT, 0, mesh.m_Positions );
|
||||
glNormalPointer( GL_FLOAT, 0, mesh.m_Normals );
|
||||
|
||||
if( mesh.m_Color != NULL )
|
||||
{
|
||||
glEnableClientState( GL_COLOR_ARRAY );
|
||||
|
||||
float transparency = 0.0f;
|
||||
|
||||
if( mesh.m_MaterialIdx < a3DModel.m_MaterialsSize )
|
||||
transparency = a3DModel.m_Materials[mesh.m_MaterialIdx].m_Transparency;
|
||||
|
||||
if( (transparency > FLT_EPSILON) &&
|
||||
(aMaterialMode == MATERIAL_MODE_NORMAL) )
|
||||
{
|
||||
// Create a new array of RGBA colors
|
||||
pColorRGBA = new SFVEC4F[mesh.m_VertexSize];
|
||||
|
||||
// Copy RGB array and add the Alpha value
|
||||
for( unsigned int i = 0; i < mesh.m_VertexSize; ++i )
|
||||
pColorRGBA[i] = SFVEC4F( mesh.m_Color[i],
|
||||
1.0f - transparency );
|
||||
|
||||
// Load an RGBA array
|
||||
glColorPointer( 4, GL_FLOAT, 0, pColorRGBA );
|
||||
}
|
||||
else
|
||||
{
|
||||
switch( aMaterialMode )
|
||||
{
|
||||
case MATERIAL_MODE_NORMAL:
|
||||
case MATERIAL_MODE_DIFFUSE_ONLY:
|
||||
// load the original RGB color array
|
||||
glColorPointer( 3, GL_FLOAT, 0, mesh.m_Color );
|
||||
break;
|
||||
case MATERIAL_MODE_CAD_MODE:
|
||||
// Create a new array of RGBA colors
|
||||
pColorRGBA = new SFVEC4F[mesh.m_VertexSize];
|
||||
|
||||
// Copy RGB array and add the Alpha value
|
||||
for( unsigned int i = 0; i < mesh.m_VertexSize; ++i )
|
||||
{
|
||||
pColorRGBA[i] =
|
||||
SFVEC4F( MaterialDiffuseToColorCAD( mesh.m_Color[i] ),
|
||||
1.0f );
|
||||
}
|
||||
|
||||
// Load an RGBA array
|
||||
glColorPointer( 4, GL_FLOAT, 0, pColorRGBA );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( mesh.m_Texcoords != NULL )
|
||||
{
|
||||
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
glTexCoordPointer( 2, GL_FLOAT, 0, mesh.m_Texcoords );
|
||||
}
|
||||
|
||||
// Compile the display list to store triangles
|
||||
// /////////////////////////////////////////////////////////
|
||||
glNewList( m_ogl_idx_list_meshes + mesh_i, GL_COMPILE );
|
||||
|
||||
// Set material properties
|
||||
// /////////////////////////////////////////////////////////
|
||||
|
||||
if( mesh.m_Color != NULL )
|
||||
{
|
||||
// This enables the use of the Color Pointer information
|
||||
glEnable( GL_COLOR_MATERIAL );
|
||||
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
|
||||
}
|
||||
else
|
||||
{
|
||||
glDisable( GL_COLOR_MATERIAL );
|
||||
}
|
||||
|
||||
if( mesh.m_MaterialIdx < a3DModel.m_MaterialsSize )
|
||||
{
|
||||
switch( aMaterialMode )
|
||||
{
|
||||
case MATERIAL_MODE_NORMAL:
|
||||
OGL_SetMaterial( a3DModel.m_Materials[mesh.m_MaterialIdx] );
|
||||
break;
|
||||
case MATERIAL_MODE_DIFFUSE_ONLY:
|
||||
OGL_SetDiffuseOnlyMaterial(
|
||||
a3DModel.m_Materials[mesh.m_MaterialIdx].m_Diffuse );
|
||||
break;
|
||||
case MATERIAL_MODE_CAD_MODE:
|
||||
OGL_SetDiffuseOnlyMaterial(
|
||||
MaterialDiffuseToColorCAD(
|
||||
a3DModel.m_Materials[mesh.m_MaterialIdx].m_Diffuse ) );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw mesh
|
||||
// /////////////////////////////////////////////////////////
|
||||
glDrawElements( GL_TRIANGLES, mesh.m_FaceIdxSize,
|
||||
GL_UNSIGNED_INT, mesh.m_FaceIdx );
|
||||
|
||||
glDisable( GL_COLOR_MATERIAL );
|
||||
|
||||
glEndList();
|
||||
|
||||
// Disable arrays client states
|
||||
// /////////////////////////////////////////////////////////
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
glDisableClientState( GL_COLOR_ARRAY );
|
||||
glDisableClientState( GL_NORMAL_ARRAY );
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
|
||||
glFlush();
|
||||
|
||||
delete [] pColorRGBA;
|
||||
}
|
||||
}
|
||||
}// for each mesh
|
||||
|
||||
|
||||
m_ogl_idx_list_opaque = glGenLists( 1 );
|
||||
|
||||
// Check if the generated list is valid
|
||||
if( glIsList( m_ogl_idx_list_opaque ) )
|
||||
{
|
||||
bool have_opaque_meshes = false;
|
||||
bool have_transparent_meshes = false;
|
||||
|
||||
// Compile the model display list
|
||||
glNewList( m_ogl_idx_list_opaque, GL_COMPILE );
|
||||
|
||||
// Render each mesh display list (opaque first)
|
||||
// /////////////////////////////////////////////////////////////////
|
||||
for( unsigned int mesh_i = 0; mesh_i < a3DModel.m_MeshesSize; ++mesh_i )
|
||||
{
|
||||
const SMESH &mesh = a3DModel.m_Meshes[mesh_i];
|
||||
|
||||
if( mesh.m_MaterialIdx < a3DModel.m_MaterialsSize )
|
||||
{
|
||||
const SMATERIAL &material = a3DModel.m_Materials[mesh.m_MaterialIdx];
|
||||
|
||||
if( material.m_Transparency == 0.0f )
|
||||
{
|
||||
have_opaque_meshes = true; // Flag that we have at least one opaque mesh
|
||||
glCallList( m_ogl_idx_list_meshes + mesh_i );
|
||||
}
|
||||
else
|
||||
{
|
||||
have_transparent_meshes = true; // Flag that we found a transparent mesh
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glEndList();
|
||||
|
||||
if( !have_opaque_meshes )
|
||||
{
|
||||
// If we dont have opaque meshes, we can free the list
|
||||
glDeleteLists( m_ogl_idx_list_opaque, 1 );
|
||||
m_ogl_idx_list_opaque = 0;
|
||||
}
|
||||
|
||||
if( have_transparent_meshes )
|
||||
{
|
||||
m_ogl_idx_list_transparent = glGenLists( 1 );
|
||||
|
||||
// Check if the generated list is valid
|
||||
if( glIsList( m_ogl_idx_list_transparent ) )
|
||||
{
|
||||
// Compile the model display list
|
||||
glNewList( m_ogl_idx_list_transparent, GL_COMPILE );
|
||||
|
||||
glEnable( GL_BLEND );
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
|
||||
// Render each mesh display list
|
||||
// /////////////////////////////////////////////////////////
|
||||
for( unsigned mesh_i = 0; mesh_i < a3DModel.m_MeshesSize; ++mesh_i )
|
||||
{
|
||||
const SMESH &mesh = a3DModel.m_Meshes[mesh_i];
|
||||
|
||||
if( mesh.m_MaterialIdx < a3DModel.m_MaterialsSize )
|
||||
{
|
||||
const SMATERIAL &material = a3DModel.m_Materials[mesh.m_MaterialIdx];
|
||||
|
||||
// Render the transparent mesh if it have a transparency value
|
||||
if( material.m_Transparency != 0.0f )
|
||||
glCallList( m_ogl_idx_list_meshes + mesh_i );
|
||||
}
|
||||
}
|
||||
|
||||
glDisable( GL_BLEND );
|
||||
|
||||
glEndList();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ogl_idx_list_transparent = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ogl_idx_list_opaque = 0;
|
||||
}
|
||||
|
||||
// Create the main bbox
|
||||
// /////////////////////////////////////////////////////////////////////
|
||||
m_model_bbox.Reset();
|
||||
|
||||
for( unsigned int mesh_i = 0; mesh_i < a3DModel.m_MeshesSize; ++mesh_i )
|
||||
m_model_bbox.Union( m_meshs_bbox[mesh_i] );
|
||||
|
||||
glFlush();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void C_OGL_3DMODEL::Draw_opaque() const
|
||||
{
|
||||
if( glIsList( m_ogl_idx_list_opaque ) )
|
||||
glCallList( m_ogl_idx_list_opaque );
|
||||
}
|
||||
|
||||
|
||||
void C_OGL_3DMODEL::Draw_transparent() const
|
||||
{
|
||||
if( glIsList( m_ogl_idx_list_transparent ) )
|
||||
glCallList( m_ogl_idx_list_transparent );
|
||||
}
|
||||
|
||||
|
||||
C_OGL_3DMODEL::~C_OGL_3DMODEL()
|
||||
{
|
||||
if( glIsList( m_ogl_idx_list_opaque ) )
|
||||
glDeleteLists( m_ogl_idx_list_opaque, 1 );
|
||||
|
||||
if( glIsList( m_ogl_idx_list_transparent ) )
|
||||
glDeleteLists( m_ogl_idx_list_transparent, 1 );
|
||||
|
||||
if( glIsList( m_ogl_idx_list_meshes ) )
|
||||
glDeleteLists( m_ogl_idx_list_meshes, m_nr_meshes );
|
||||
|
||||
m_ogl_idx_list_meshes = 0;
|
||||
m_ogl_idx_list_opaque = 0;
|
||||
m_ogl_idx_list_transparent = 0;
|
||||
|
||||
delete[] m_meshs_bbox;
|
||||
m_meshs_bbox = NULL;
|
||||
}
|
||||
|
||||
|
||||
void C_OGL_3DMODEL::Draw_bbox() const
|
||||
{
|
||||
OGL_draw_bbox( m_model_bbox );
|
||||
}
|
||||
|
||||
|
||||
void C_OGL_3DMODEL::Draw_bboxes() const
|
||||
{
|
||||
for( unsigned int mesh_i = 0; mesh_i < m_nr_meshes; ++mesh_i )
|
||||
OGL_draw_bbox( m_meshs_bbox[mesh_i] );
|
||||
}
|
||||
|
||||
|
||||
bool C_OGL_3DMODEL::Have_opaque() const
|
||||
{
|
||||
return glIsList( m_ogl_idx_list_opaque );
|
||||
}
|
||||
|
||||
|
||||
bool C_OGL_3DMODEL::Have_transparent() const
|
||||
{
|
||||
return glIsList( m_ogl_idx_list_transparent );
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file c_ogl_3dmodel.h
|
||||
* @brief implement a legacy 3dmodel render
|
||||
*/
|
||||
|
||||
#ifndef _C_OGL_3DMODEL_H_
|
||||
#define _C_OGL_3DMODEL_H_
|
||||
|
||||
#include <plugins/3dapi/c3dmodel.h>
|
||||
#include "../../common_ogl/openGL_includes.h"
|
||||
#include "../3d_render_raytracing/shapes3D/cbbox.h"
|
||||
#include "../../3d_enums.h"
|
||||
|
||||
///
|
||||
class C_OGL_3DMODEL
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief C_OGL_3DMODEL - Load a 3d model. This must be called inside a gl context
|
||||
* @param a3DModel: a 3d model data to load.
|
||||
* @param aMaterialMode: a mode to render the materials of the model
|
||||
*/
|
||||
C_OGL_3DMODEL( const S3DMODEL &a3DModel, MATERIAL_MODE aMaterialMode );
|
||||
|
||||
~C_OGL_3DMODEL();
|
||||
|
||||
/**
|
||||
* @brief Draw_opaque - render the model into the current context
|
||||
*/
|
||||
void Draw_opaque() const;
|
||||
|
||||
/**
|
||||
* @brief Draw_transparent - render the model into the current context
|
||||
*/
|
||||
void Draw_transparent() const;
|
||||
|
||||
/**
|
||||
* @brief Have_opaque - return true if have opaque meshs to render
|
||||
*/
|
||||
bool Have_opaque() const;
|
||||
|
||||
/**
|
||||
* @brief Have_transparent - return true if have transparent meshs to render
|
||||
*/
|
||||
bool Have_transparent() const;
|
||||
|
||||
/**
|
||||
* @brief Draw_bbox - draw main bounding box of the model
|
||||
*/
|
||||
void Draw_bbox() const;
|
||||
|
||||
/**
|
||||
* @brief Draw_bboxes - draw individual bounding boxes of each mesh
|
||||
*/
|
||||
void Draw_bboxes() const;
|
||||
|
||||
/**
|
||||
* @brief GetBBox - Get main bbox
|
||||
* @return the main model bbox
|
||||
*/
|
||||
const CBBOX &GetBBox() const { return m_model_bbox; }
|
||||
|
||||
private:
|
||||
GLuint m_ogl_idx_list_opaque; ///< display list for rendering opaque meshes
|
||||
GLuint m_ogl_idx_list_transparent; ///< display list for rendering transparent meshes
|
||||
GLuint m_ogl_idx_list_meshes; ///< display lists for all meshes.
|
||||
unsigned int m_nr_meshes; ///< number of meshes of this model
|
||||
|
||||
CBBOX m_model_bbox; ///< global bounding box for this model
|
||||
CBBOX *m_meshs_bbox; ///< individual bbox for each mesh
|
||||
};
|
||||
|
||||
#endif // _C_OGL_3DMODEL_H_
|
||||
@@ -1,832 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file clayer_triangles.cpp
|
||||
* @brief
|
||||
*/
|
||||
|
||||
|
||||
#include "clayer_triangles.h"
|
||||
#include <wx/debug.h> // For the wxASSERT
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
|
||||
|
||||
CLAYER_TRIANGLE_CONTAINER::CLAYER_TRIANGLE_CONTAINER( unsigned int aNrReservedTriangles,
|
||||
bool aReserveNormals )
|
||||
{
|
||||
wxASSERT( aNrReservedTriangles > 0 );
|
||||
|
||||
m_vertexs.clear();
|
||||
m_normals.clear();
|
||||
|
||||
m_vertexs.reserve( aNrReservedTriangles * 3 );
|
||||
|
||||
if( aReserveNormals )
|
||||
m_normals.reserve( aNrReservedTriangles * 3 );
|
||||
}
|
||||
|
||||
|
||||
void CLAYER_TRIANGLE_CONTAINER::Reserve_More( unsigned int aNrReservedTriangles,
|
||||
bool aReserveNormals )
|
||||
{
|
||||
m_vertexs.reserve( m_vertexs.size() + aNrReservedTriangles * 3 );
|
||||
|
||||
if( aReserveNormals )
|
||||
m_normals.reserve( m_normals.size() + aNrReservedTriangles * 3 );
|
||||
}
|
||||
|
||||
|
||||
void CLAYER_TRIANGLE_CONTAINER::AddQuad( const SFVEC3F &aV1,
|
||||
const SFVEC3F &aV2,
|
||||
const SFVEC3F &aV3,
|
||||
const SFVEC3F &aV4 )
|
||||
{
|
||||
m_vertexs.push_back( aV1 );
|
||||
m_vertexs.push_back( aV2 );
|
||||
m_vertexs.push_back( aV3 );
|
||||
|
||||
m_vertexs.push_back( aV3 );
|
||||
m_vertexs.push_back( aV4 );
|
||||
m_vertexs.push_back( aV1 );
|
||||
}
|
||||
|
||||
|
||||
void CLAYER_TRIANGLE_CONTAINER::AddTriangle( const SFVEC3F &aV1,
|
||||
const SFVEC3F &aV2,
|
||||
const SFVEC3F &aV3 )
|
||||
{
|
||||
m_vertexs.push_back( aV1 );
|
||||
m_vertexs.push_back( aV2 );
|
||||
m_vertexs.push_back( aV3 );
|
||||
}
|
||||
|
||||
|
||||
void CLAYER_TRIANGLE_CONTAINER::AddNormal( const SFVEC3F &aN1,
|
||||
const SFVEC3F &aN2,
|
||||
const SFVEC3F &aN3 )
|
||||
{
|
||||
m_normals.push_back( aN1 );
|
||||
m_normals.push_back( aN2 );
|
||||
m_normals.push_back( aN3 );
|
||||
}
|
||||
|
||||
void CLAYER_TRIANGLE_CONTAINER::AddNormal( const SFVEC3F &aN1,
|
||||
const SFVEC3F &aN2,
|
||||
const SFVEC3F &aN3,
|
||||
const SFVEC3F &aN4 )
|
||||
{
|
||||
m_normals.push_back( aN1 );
|
||||
m_normals.push_back( aN2 );
|
||||
m_normals.push_back( aN3 );
|
||||
|
||||
m_normals.push_back( aN3 );
|
||||
m_normals.push_back( aN4 );
|
||||
m_normals.push_back( aN1 );
|
||||
}
|
||||
|
||||
|
||||
CLAYER_TRIANGLES::CLAYER_TRIANGLES( unsigned int aNrReservedTriangles )
|
||||
{
|
||||
wxASSERT( aNrReservedTriangles > 0 );
|
||||
|
||||
m_layer_top_segment_ends = new CLAYER_TRIANGLE_CONTAINER( aNrReservedTriangles,
|
||||
false );
|
||||
m_layer_top_triangles = new CLAYER_TRIANGLE_CONTAINER( aNrReservedTriangles,
|
||||
false );
|
||||
m_layer_middle_contourns_quads = new CLAYER_TRIANGLE_CONTAINER( aNrReservedTriangles,
|
||||
true );
|
||||
m_layer_bot_triangles = new CLAYER_TRIANGLE_CONTAINER( aNrReservedTriangles,
|
||||
false );
|
||||
m_layer_bot_segment_ends = new CLAYER_TRIANGLE_CONTAINER( aNrReservedTriangles,
|
||||
false );
|
||||
}
|
||||
|
||||
|
||||
CLAYER_TRIANGLES::~CLAYER_TRIANGLES()
|
||||
{
|
||||
delete m_layer_top_segment_ends;
|
||||
m_layer_top_segment_ends = 0;
|
||||
|
||||
delete m_layer_top_triangles;
|
||||
m_layer_top_triangles = 0;
|
||||
|
||||
delete m_layer_middle_contourns_quads;
|
||||
m_layer_middle_contourns_quads = 0;
|
||||
|
||||
delete m_layer_bot_triangles;
|
||||
m_layer_bot_triangles = 0;
|
||||
|
||||
delete m_layer_bot_segment_ends;
|
||||
m_layer_bot_segment_ends = 0;
|
||||
}
|
||||
|
||||
|
||||
void CLAYER_TRIANGLES::AddToMiddleContourns( const std::vector< SFVEC2F > &aContournPoints,
|
||||
float zBot,
|
||||
float zTop,
|
||||
bool aInvertFaceDirection )
|
||||
{
|
||||
if( aContournPoints.size() >= 4 )
|
||||
{
|
||||
// Calculate normals of each segment of the contourn
|
||||
std::vector< SFVEC2F > contournNormals;
|
||||
|
||||
contournNormals.clear();
|
||||
contournNormals.resize( aContournPoints.size() - 1 );
|
||||
|
||||
if( aInvertFaceDirection )
|
||||
{
|
||||
for( unsigned int i = 0; i < ( aContournPoints.size() - 1 ); ++i )
|
||||
{
|
||||
const SFVEC2F &v0 = aContournPoints[i + 0];
|
||||
const SFVEC2F &v1 = aContournPoints[i + 1];
|
||||
const SFVEC2F n = glm::normalize( v1 - v0 );
|
||||
|
||||
contournNormals[i] = SFVEC2F( n.y,-n.x );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( unsigned int i = 0; i < ( aContournPoints.size() - 1 ); ++i )
|
||||
{
|
||||
const SFVEC2F &v0 = aContournPoints[i + 0];
|
||||
const SFVEC2F &v1 = aContournPoints[i + 1];
|
||||
const SFVEC2F n = glm::normalize( v1 - v0 );
|
||||
|
||||
contournNormals[i] = SFVEC2F( -n.y, n.x );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( aInvertFaceDirection )
|
||||
std::swap( zBot, zTop );
|
||||
|
||||
const unsigned int nContournsToProcess = ( aContournPoints.size() - 1 );
|
||||
|
||||
for( unsigned int i = 0; i < nContournsToProcess; ++i )
|
||||
{
|
||||
SFVEC2F lastNormal;
|
||||
|
||||
if( i > 0 )
|
||||
lastNormal = contournNormals[i - 1];
|
||||
else
|
||||
lastNormal = contournNormals[nContournsToProcess - 1];
|
||||
|
||||
SFVEC2F n0 = contournNormals[i];
|
||||
|
||||
// Only interpolate the normal if the angle is closer
|
||||
if( glm::dot( n0, lastNormal ) > 0.5f )
|
||||
n0 = glm::normalize( n0 + lastNormal );
|
||||
|
||||
SFVEC2F nextNormal;
|
||||
|
||||
if( i < (nContournsToProcess - 1) )
|
||||
nextNormal = contournNormals[i + 1];
|
||||
else
|
||||
nextNormal = contournNormals[0];
|
||||
|
||||
SFVEC2F n1 = contournNormals[i];
|
||||
|
||||
if( glm::dot( n1, nextNormal ) > 0.5f )
|
||||
n1 = glm::normalize( n1 + nextNormal );
|
||||
|
||||
const SFVEC3F n3d0 = SFVEC3F( n0.x, n0.y, 0.0f );
|
||||
const SFVEC3F n3d1 = SFVEC3F( n1.x, n1.y, 0.0f );
|
||||
|
||||
const SFVEC2F &v0 = aContournPoints[i + 0];
|
||||
const SFVEC2F &v1 = aContournPoints[i + 1];
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock( m_middle_layer_lock );
|
||||
m_layer_middle_contourns_quads->AddQuad( SFVEC3F( v0.x, v0.y, zTop ),
|
||||
SFVEC3F( v1.x, v1.y, zTop ),
|
||||
SFVEC3F( v1.x, v1.y, zBot ),
|
||||
SFVEC3F( v0.x, v0.y, zBot ) );
|
||||
|
||||
m_layer_middle_contourns_quads->AddNormal( n3d0, n3d1, n3d1, n3d0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CLAYER_TRIANGLES::AddToMiddleContourns( const SHAPE_LINE_CHAIN &outlinePath,
|
||||
float zBot,
|
||||
float zTop,
|
||||
double aBiuTo3Du,
|
||||
bool aInvertFaceDirection )
|
||||
{
|
||||
std::vector< SFVEC2F >contournPoints;
|
||||
|
||||
contournPoints.clear();
|
||||
contournPoints.reserve( outlinePath.PointCount() + 2 );
|
||||
|
||||
const VECTOR2I &firstV = outlinePath.CPoint( 0 );
|
||||
|
||||
SFVEC2F lastV = SFVEC2F( firstV.x * aBiuTo3Du,
|
||||
-firstV.y * aBiuTo3Du );
|
||||
|
||||
contournPoints.push_back( lastV );
|
||||
|
||||
for( unsigned int i = 1; i < (unsigned int)outlinePath.PointCount(); ++i )
|
||||
{
|
||||
const VECTOR2I & v = outlinePath.CPoint( i );
|
||||
|
||||
const SFVEC2F vf = SFVEC2F( v.x * aBiuTo3Du,
|
||||
-v.y * aBiuTo3Du );
|
||||
|
||||
if( vf != lastV ) // Do not add repeated points
|
||||
{
|
||||
lastV = vf;
|
||||
contournPoints.push_back( vf );
|
||||
}
|
||||
}
|
||||
|
||||
// Add first position fo the list to close the path
|
||||
if( lastV != contournPoints[0] )
|
||||
contournPoints.push_back( contournPoints[0] );
|
||||
|
||||
AddToMiddleContourns( contournPoints, zBot, zTop, aInvertFaceDirection );
|
||||
}
|
||||
|
||||
|
||||
void CLAYER_TRIANGLES::AddToMiddleContourns( const SHAPE_POLY_SET &aPolySet,
|
||||
float zBot,
|
||||
float zTop,
|
||||
double aBiuTo3Du,
|
||||
bool aInvertFaceDirection )
|
||||
{
|
||||
if( aPolySet.OutlineCount() == 0 )
|
||||
return;
|
||||
|
||||
// Calculate an estimation of points to reserve
|
||||
unsigned int nrContournPointsToReserve = 0;
|
||||
|
||||
for( int i = 0; i < aPolySet.OutlineCount(); ++i )
|
||||
{
|
||||
const SHAPE_LINE_CHAIN& pathOutline = aPolySet.COutline( i );
|
||||
|
||||
nrContournPointsToReserve += pathOutline.PointCount();
|
||||
|
||||
for( int h = 0; h < aPolySet.HoleCount( i ); ++h )
|
||||
{
|
||||
const SHAPE_LINE_CHAIN &hole = aPolySet.CHole( i, h );
|
||||
|
||||
nrContournPointsToReserve += hole.PointCount();
|
||||
}
|
||||
}
|
||||
|
||||
// Request to reserve more space
|
||||
m_layer_middle_contourns_quads->Reserve_More( nrContournPointsToReserve * 2,
|
||||
true );
|
||||
|
||||
for( int i = 0; i < aPolySet.OutlineCount(); i++ )
|
||||
{
|
||||
// Add outline
|
||||
const SHAPE_LINE_CHAIN& pathOutline = aPolySet.COutline( i );
|
||||
|
||||
AddToMiddleContourns( pathOutline, zBot, zTop, aBiuTo3Du, aInvertFaceDirection );
|
||||
|
||||
// Add holes for this outline
|
||||
for( int h = 0; h < aPolySet.HoleCount( i ); ++h )
|
||||
{
|
||||
const SHAPE_LINE_CHAIN &hole = aPolySet.CHole( i, h );
|
||||
AddToMiddleContourns( hole, zBot, zTop, aBiuTo3Du, aInvertFaceDirection );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CLAYERS_OGL_DISP_LISTS::CLAYERS_OGL_DISP_LISTS( const CLAYER_TRIANGLES &aLayerTriangles,
|
||||
GLuint aTextureIndexForSegEnds,
|
||||
float aZBot,
|
||||
float aZTop )
|
||||
{
|
||||
m_zBot = aZBot;
|
||||
m_zTop = aZTop;
|
||||
|
||||
m_layer_top_segment_ends = 0;
|
||||
m_layer_top_triangles = 0;
|
||||
m_layer_middle_contourns_quads = 0;
|
||||
m_layer_bot_triangles = 0;
|
||||
m_layer_bot_segment_ends = 0;
|
||||
|
||||
if( aTextureIndexForSegEnds )
|
||||
{
|
||||
wxASSERT( glIsTexture( aTextureIndexForSegEnds ) );
|
||||
|
||||
if( glIsTexture( aTextureIndexForSegEnds ) )
|
||||
{
|
||||
m_layer_top_segment_ends =
|
||||
generate_top_or_bot_seg_ends( aLayerTriangles.m_layer_top_segment_ends,
|
||||
true,
|
||||
aTextureIndexForSegEnds );
|
||||
|
||||
m_layer_bot_segment_ends =
|
||||
generate_top_or_bot_seg_ends( aLayerTriangles.m_layer_bot_segment_ends,
|
||||
false,
|
||||
aTextureIndexForSegEnds );
|
||||
}
|
||||
}
|
||||
|
||||
m_layer_top_triangles = generate_top_or_bot_triangles( aLayerTriangles.m_layer_top_triangles,
|
||||
true );
|
||||
|
||||
m_layer_bot_triangles = generate_top_or_bot_triangles( aLayerTriangles.m_layer_bot_triangles,
|
||||
false );
|
||||
|
||||
|
||||
if( aLayerTriangles.m_layer_middle_contourns_quads->GetVertexSize() > 0 )
|
||||
{
|
||||
m_layer_middle_contourns_quads =
|
||||
generate_middle_triangles( aLayerTriangles.m_layer_middle_contourns_quads );
|
||||
}
|
||||
|
||||
m_draw_it_transparent = false;
|
||||
m_haveTransformation = false;
|
||||
m_zPositionTransformation = 0.0f;
|
||||
m_zScaleTransformation = 0.0f;
|
||||
}
|
||||
|
||||
|
||||
CLAYERS_OGL_DISP_LISTS::~CLAYERS_OGL_DISP_LISTS()
|
||||
{
|
||||
if( glIsList( m_layer_top_segment_ends ) )
|
||||
glDeleteLists( m_layer_top_segment_ends, 1 );
|
||||
|
||||
if( glIsList( m_layer_top_triangles ) )
|
||||
glDeleteLists( m_layer_top_triangles, 1 );
|
||||
|
||||
if( glIsList( m_layer_middle_contourns_quads ) )
|
||||
glDeleteLists( m_layer_middle_contourns_quads, 1 );
|
||||
|
||||
if( glIsList( m_layer_bot_triangles ) )
|
||||
glDeleteLists( m_layer_bot_triangles, 1 );
|
||||
|
||||
if( glIsList( m_layer_bot_segment_ends ) )
|
||||
glDeleteLists( m_layer_bot_segment_ends, 1 );
|
||||
|
||||
m_layer_top_segment_ends = 0;
|
||||
m_layer_top_triangles = 0;
|
||||
m_layer_middle_contourns_quads = 0;
|
||||
m_layer_bot_triangles = 0;
|
||||
m_layer_bot_segment_ends = 0;
|
||||
}
|
||||
|
||||
|
||||
void CLAYERS_OGL_DISP_LISTS::DrawTopAndMiddle() const
|
||||
{
|
||||
beginTransformation();
|
||||
|
||||
if( glIsList( m_layer_middle_contourns_quads ) )
|
||||
glCallList( m_layer_middle_contourns_quads );
|
||||
|
||||
if( glIsList( m_layer_top_triangles ) )
|
||||
glCallList( m_layer_top_triangles );
|
||||
|
||||
if( glIsList( m_layer_top_segment_ends ) )
|
||||
glCallList( m_layer_top_segment_ends );
|
||||
|
||||
endTransformation();
|
||||
}
|
||||
|
||||
|
||||
void CLAYERS_OGL_DISP_LISTS::DrawBotAndMiddle() const
|
||||
{
|
||||
beginTransformation();
|
||||
|
||||
if( glIsList( m_layer_middle_contourns_quads ) )
|
||||
glCallList( m_layer_middle_contourns_quads );
|
||||
|
||||
if( glIsList( m_layer_bot_triangles ) )
|
||||
glCallList( m_layer_bot_triangles );
|
||||
|
||||
if( glIsList( m_layer_bot_segment_ends ) )
|
||||
glCallList( m_layer_bot_segment_ends );
|
||||
|
||||
endTransformation();
|
||||
}
|
||||
|
||||
|
||||
void CLAYERS_OGL_DISP_LISTS::DrawTop() const
|
||||
{
|
||||
beginTransformation();
|
||||
|
||||
if( glIsList( m_layer_top_triangles ) )
|
||||
glCallList( m_layer_top_triangles );
|
||||
|
||||
if( glIsList( m_layer_top_segment_ends ) )
|
||||
glCallList( m_layer_top_segment_ends );
|
||||
|
||||
endTransformation();
|
||||
}
|
||||
|
||||
|
||||
void CLAYERS_OGL_DISP_LISTS::DrawBot() const
|
||||
{
|
||||
beginTransformation();
|
||||
|
||||
if( glIsList( m_layer_bot_triangles ) )
|
||||
glCallList( m_layer_bot_triangles );
|
||||
|
||||
if( glIsList( m_layer_bot_segment_ends ) )
|
||||
glCallList( m_layer_bot_segment_ends );
|
||||
|
||||
endTransformation();
|
||||
}
|
||||
|
||||
|
||||
void CLAYERS_OGL_DISP_LISTS::DrawMiddle() const
|
||||
{
|
||||
beginTransformation();
|
||||
|
||||
if( glIsList( m_layer_middle_contourns_quads ) )
|
||||
glCallList( m_layer_middle_contourns_quads );
|
||||
|
||||
endTransformation();
|
||||
}
|
||||
|
||||
|
||||
void CLAYERS_OGL_DISP_LISTS::DrawAll( bool aDrawMiddle ) const
|
||||
{
|
||||
beginTransformation();
|
||||
|
||||
if( aDrawMiddle )
|
||||
if( glIsList( m_layer_middle_contourns_quads ) )
|
||||
glCallList( m_layer_middle_contourns_quads );
|
||||
|
||||
if( glIsList( m_layer_top_triangles ) )
|
||||
glCallList( m_layer_top_triangles );
|
||||
|
||||
if( glIsList( m_layer_bot_triangles ) )
|
||||
glCallList( m_layer_bot_triangles );
|
||||
|
||||
if( glIsList( m_layer_top_segment_ends ) )
|
||||
glCallList( m_layer_top_segment_ends );
|
||||
|
||||
if( glIsList( m_layer_bot_segment_ends ) )
|
||||
glCallList( m_layer_bot_segment_ends );
|
||||
|
||||
endTransformation();
|
||||
}
|
||||
|
||||
|
||||
void CLAYERS_OGL_DISP_LISTS::DrawAllCameraCulled(float zCameraPos, bool aDrawMiddle ) const
|
||||
{
|
||||
zCameraPos = m_haveTransformation?( (zCameraPos - m_zPositionTransformation ) /
|
||||
m_zScaleTransformation ):zCameraPos;
|
||||
|
||||
if( aDrawMiddle )
|
||||
DrawMiddle();
|
||||
|
||||
if( zCameraPos > m_zTop )
|
||||
{
|
||||
DrawTop();
|
||||
}
|
||||
else
|
||||
{
|
||||
if( zCameraPos < m_zBot )
|
||||
{
|
||||
DrawBot();
|
||||
}
|
||||
else
|
||||
{
|
||||
// If camera is in the middle dont draw it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CLAYERS_OGL_DISP_LISTS::DrawAllCameraCulledSubtractLayer(
|
||||
const CLAYERS_OGL_DISP_LISTS *aLayerToSubtractA,
|
||||
const CLAYERS_OGL_DISP_LISTS *aLayerToSubtractB,
|
||||
bool aDrawMiddle ) const
|
||||
{
|
||||
if( aDrawMiddle )
|
||||
DrawMiddle();
|
||||
|
||||
glClearStencil( 0x00 );
|
||||
glClear( GL_STENCIL_BUFFER_BIT );
|
||||
|
||||
glEnable( GL_CULL_FACE );
|
||||
glCullFace( GL_BACK );
|
||||
|
||||
glDisable( GL_DEPTH_TEST );
|
||||
glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
|
||||
glDepthMask( GL_FALSE );
|
||||
glEnable( GL_STENCIL_TEST );
|
||||
glStencilFunc( GL_ALWAYS, 1, 0 );
|
||||
glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
|
||||
|
||||
if( aLayerToSubtractA )
|
||||
aLayerToSubtractA->DrawBot();
|
||||
|
||||
if( aLayerToSubtractB )
|
||||
aLayerToSubtractB->DrawBot();
|
||||
|
||||
|
||||
//if( !m_draw_it_transparent )
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_TRUE);
|
||||
}
|
||||
|
||||
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
|
||||
glStencilFunc( GL_EQUAL, 0, 1 );
|
||||
glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
|
||||
DrawBot();
|
||||
|
||||
glDisable( GL_DEPTH_TEST );
|
||||
glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
|
||||
glDepthMask( GL_FALSE );
|
||||
glEnable( GL_STENCIL_TEST );
|
||||
glStencilFunc( GL_ALWAYS, 2, 0 );
|
||||
glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
|
||||
|
||||
if( aLayerToSubtractA )
|
||||
aLayerToSubtractA->DrawTop();
|
||||
|
||||
if( aLayerToSubtractB )
|
||||
aLayerToSubtractB->DrawTop();
|
||||
|
||||
//if( !m_draw_it_transparent )
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_TRUE);
|
||||
}
|
||||
|
||||
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
|
||||
glStencilFunc( GL_NOTEQUAL, 2, 0x03 );
|
||||
glStencilOp( GL_KEEP, GL_KEEP, GL_INCR );
|
||||
DrawTop();
|
||||
|
||||
|
||||
glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE );
|
||||
|
||||
glCullFace( GL_FRONT );
|
||||
glStencilFunc( GL_GEQUAL, 3, 0x03 );
|
||||
glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
|
||||
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
|
||||
|
||||
if( aDrawMiddle )
|
||||
{
|
||||
if( aLayerToSubtractA )
|
||||
aLayerToSubtractA->DrawMiddle();
|
||||
|
||||
// It will not render the middle contours of the layer.
|
||||
// It is used with vias and holes (copper vias and to subtract solder
|
||||
// mask holes). But since in the vias, it will draw a cylinder
|
||||
// and in soldermask it doesn't need to draw the contour.
|
||||
// so it is not used the middle part of B
|
||||
// if( aLayerToSubtractB )
|
||||
// aLayerToSubtractB->DrawMiddle();
|
||||
}
|
||||
|
||||
glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE );
|
||||
|
||||
glCullFace( GL_BACK );
|
||||
glDisable( GL_STENCIL_TEST );
|
||||
|
||||
/*
|
||||
if( m_draw_it_transparent )
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_TRUE);
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
void CLAYERS_OGL_DISP_LISTS::ApplyScalePosition( float aZposition,
|
||||
float aZscale )
|
||||
{
|
||||
wxASSERT( aZscale > FLT_EPSILON );
|
||||
|
||||
m_zPositionTransformation = aZposition;
|
||||
m_zScaleTransformation = aZscale;
|
||||
m_haveTransformation = true;
|
||||
}
|
||||
|
||||
|
||||
void CLAYERS_OGL_DISP_LISTS::SetItIsTransparent( bool aSetTransparent )
|
||||
{
|
||||
m_draw_it_transparent = aSetTransparent;
|
||||
}
|
||||
|
||||
|
||||
GLuint CLAYERS_OGL_DISP_LISTS::generate_top_or_bot_seg_ends(
|
||||
const CLAYER_TRIANGLE_CONTAINER *aTriangleContainer,
|
||||
bool aIsNormalUp,
|
||||
GLuint aTextureId ) const
|
||||
{
|
||||
wxASSERT( aTriangleContainer != NULL );
|
||||
|
||||
wxASSERT( (aTriangleContainer->GetVertexSize() % 3) == 0 );
|
||||
|
||||
// Top and Bot dont have normals array stored in container
|
||||
wxASSERT( aTriangleContainer->GetNormalsSize() == 0 );
|
||||
|
||||
if( (aTriangleContainer->GetVertexSize() > 0) &&
|
||||
((aTriangleContainer->GetVertexSize() % 3) == 0) )
|
||||
{
|
||||
GLuint listIdx = glGenLists( 1 );
|
||||
|
||||
if( glIsList( listIdx ) )
|
||||
{
|
||||
// Prepare an array of UV text coordinates
|
||||
SFVEC2F *uvArray = new SFVEC2F[aTriangleContainer->GetVertexSize()];
|
||||
|
||||
for( unsigned int i = 0;
|
||||
i < aTriangleContainer->GetVertexSize();
|
||||
i += 3 )
|
||||
{
|
||||
uvArray[i + 0] = SFVEC2F( 1.0f, 0.0f );
|
||||
uvArray[i + 1] = SFVEC2F( 0.0f, 1.0f );
|
||||
uvArray[i + 2] = SFVEC2F( 0.0f, 0.0f );
|
||||
}
|
||||
|
||||
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
glDisableClientState( GL_COLOR_ARRAY );
|
||||
glDisableClientState( GL_NORMAL_ARRAY );
|
||||
glEnableClientState( GL_VERTEX_ARRAY );
|
||||
glVertexPointer( 3, GL_FLOAT, 0, aTriangleContainer->GetVertexPointer() );
|
||||
glTexCoordPointer( 2, GL_FLOAT, 0, uvArray );
|
||||
|
||||
glNewList( listIdx, GL_COMPILE );
|
||||
|
||||
glDisable( GL_COLOR_MATERIAL );
|
||||
|
||||
glEnable( GL_TEXTURE_2D );
|
||||
glBindTexture( GL_TEXTURE_2D, aTextureId );
|
||||
|
||||
setBlendfunction();
|
||||
|
||||
glAlphaFunc( GL_GREATER, 0.2f );
|
||||
glEnable( GL_ALPHA_TEST );
|
||||
|
||||
glNormal3f( 0.0f, 0.0f, aIsNormalUp?1.0f:-1.0f );
|
||||
|
||||
glDrawArrays( GL_TRIANGLES, 0, aTriangleContainer->GetVertexSize() );
|
||||
|
||||
glDisable( GL_TEXTURE_2D );
|
||||
glDisable( GL_ALPHA_TEST );
|
||||
glDisable( GL_BLEND );
|
||||
|
||||
glEndList();
|
||||
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
|
||||
delete [] uvArray;
|
||||
return listIdx;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
GLuint CLAYERS_OGL_DISP_LISTS::generate_top_or_bot_triangles(
|
||||
const CLAYER_TRIANGLE_CONTAINER *aTriangleContainer,
|
||||
bool aIsNormalUp ) const
|
||||
{
|
||||
wxASSERT( aTriangleContainer != NULL );
|
||||
|
||||
wxASSERT( (aTriangleContainer->GetVertexSize() % 3) == 0 );
|
||||
|
||||
// Top and Bot dont have normals array stored in container
|
||||
wxASSERT( aTriangleContainer->GetNormalsSize() == 0 );
|
||||
|
||||
if( (aTriangleContainer->GetVertexSize() > 0) &&
|
||||
( (aTriangleContainer->GetVertexSize() % 3) == 0) )
|
||||
{
|
||||
const GLuint listIdx = glGenLists( 1 );
|
||||
|
||||
if( glIsList( listIdx ) )
|
||||
{
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
glDisableClientState( GL_COLOR_ARRAY );
|
||||
glDisableClientState( GL_NORMAL_ARRAY );
|
||||
glEnableClientState( GL_VERTEX_ARRAY );
|
||||
glVertexPointer( 3, GL_FLOAT, 0, aTriangleContainer->GetVertexPointer() );
|
||||
|
||||
glNewList( listIdx, GL_COMPILE );
|
||||
|
||||
setBlendfunction();
|
||||
|
||||
glNormal3f( 0.0f, 0.0f, aIsNormalUp?1.0f:-1.0f );
|
||||
|
||||
glDrawArrays( GL_TRIANGLES, 0, aTriangleContainer->GetVertexSize() );
|
||||
|
||||
glDisable( GL_BLEND );
|
||||
glEndList();
|
||||
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
|
||||
return listIdx;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
GLuint CLAYERS_OGL_DISP_LISTS::generate_middle_triangles(
|
||||
const CLAYER_TRIANGLE_CONTAINER *aTriangleContainer ) const
|
||||
{
|
||||
wxASSERT( aTriangleContainer != NULL );
|
||||
|
||||
// We expect that it is a multiple of 3 vertex
|
||||
wxASSERT( (aTriangleContainer->GetVertexSize() % 3) == 0 );
|
||||
|
||||
// We expect that it is a multiple of 6 vertex (because we expect to add quads)
|
||||
wxASSERT( (aTriangleContainer->GetVertexSize() % 6) == 0 );
|
||||
|
||||
// We expect that there are normals with same size as vertex
|
||||
wxASSERT( aTriangleContainer->GetNormalsSize() == aTriangleContainer->GetVertexSize() );
|
||||
|
||||
|
||||
if( ( aTriangleContainer->GetVertexSize() > 0 ) &&
|
||||
( (aTriangleContainer->GetVertexSize() % 3) == 0 ) &&
|
||||
( (aTriangleContainer->GetVertexSize() % 6) == 0 ) &&
|
||||
( aTriangleContainer->GetNormalsSize() == aTriangleContainer->GetVertexSize() ) )
|
||||
{
|
||||
const GLuint listIdx = glGenLists( 1 );
|
||||
|
||||
if( glIsList( listIdx ) )
|
||||
{
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
glDisableClientState( GL_COLOR_ARRAY );
|
||||
glEnableClientState( GL_NORMAL_ARRAY );
|
||||
glEnableClientState( GL_VERTEX_ARRAY );
|
||||
glVertexPointer( 3, GL_FLOAT, 0, aTriangleContainer->GetVertexPointer() );
|
||||
glNormalPointer( GL_FLOAT, 0, aTriangleContainer->GetNormalsPointer() );
|
||||
|
||||
glNewList( listIdx, GL_COMPILE );
|
||||
|
||||
setBlendfunction();
|
||||
|
||||
glDrawArrays( GL_TRIANGLES, 0, aTriangleContainer->GetVertexSize() );
|
||||
|
||||
glDisable( GL_BLEND );
|
||||
glEndList();
|
||||
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
glDisableClientState( GL_NORMAL_ARRAY );
|
||||
|
||||
return listIdx;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void CLAYERS_OGL_DISP_LISTS::endTransformation() const
|
||||
{
|
||||
if( m_haveTransformation )
|
||||
{
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CLAYERS_OGL_DISP_LISTS::setBlendfunction() const
|
||||
{
|
||||
glEnable( GL_BLEND );
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
}
|
||||
|
||||
|
||||
void CLAYERS_OGL_DISP_LISTS::beginTransformation() const
|
||||
{
|
||||
if( m_haveTransformation )
|
||||
{
|
||||
glPushMatrix();
|
||||
glTranslatef( 0.0f, 0.0f, m_zPositionTransformation );
|
||||
glScalef( 1.0f, 1.0f, m_zScaleTransformation );
|
||||
}
|
||||
}
|
||||
@@ -1,300 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file clayer_triangles.h
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef CLAYER_TRIANGLES_H_
|
||||
#define CLAYER_TRIANGLES_H_
|
||||
|
||||
#include "../../common_ogl/openGL_includes.h"
|
||||
#include <plugins/3dapi/xv3d_types.h>
|
||||
#include <geometry/shape_line_chain.h>
|
||||
#include <geometry/shape_poly_set.h>
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
|
||||
|
||||
typedef std::vector< SFVEC3F > SFVEC3F_VECTOR;
|
||||
|
||||
|
||||
/**
|
||||
* @brief The CLAYER_TRIANGLE_CONTAINER class stores an manage vector of triangles
|
||||
*/
|
||||
class CLAYER_TRIANGLE_CONTAINER
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief CLAYER_TRIANGLE_CONTAINER
|
||||
* @param aNrReservedTriangles: number of triangles expected to be used
|
||||
* @param aReserveNormals: if you will use normals, set it to bool to pre
|
||||
* reserve space
|
||||
*/
|
||||
CLAYER_TRIANGLE_CONTAINER( unsigned int aNrReservedTriangles, bool aReserveNormals );
|
||||
|
||||
/**
|
||||
* @brief Reserve_More - reserve more triangles
|
||||
*
|
||||
*/
|
||||
void Reserve_More( unsigned int aNrReservedTriangles, bool aReserveNormals );
|
||||
|
||||
/**
|
||||
* @brief AddTriangle
|
||||
* @param aV1
|
||||
* @param aV2
|
||||
* @param aV3
|
||||
*/
|
||||
void AddTriangle( const SFVEC3F &aV1, const SFVEC3F &aV2, const SFVEC3F &aV3 );
|
||||
|
||||
/**
|
||||
* @brief AddQuad
|
||||
* @param aV1
|
||||
* @param aV2
|
||||
* @param aV3
|
||||
* @param aV4
|
||||
*/
|
||||
void AddQuad( const SFVEC3F &aV1,
|
||||
const SFVEC3F &aV2,
|
||||
const SFVEC3F &aV3,
|
||||
const SFVEC3F &aV4 );
|
||||
|
||||
/**
|
||||
* @brief AddNormal
|
||||
* @param aN1
|
||||
* @param aN2
|
||||
* @param aN3
|
||||
*/
|
||||
void AddNormal( const SFVEC3F &aN1, const SFVEC3F &aN2, const SFVEC3F &aN3 );
|
||||
|
||||
/**
|
||||
* @brief AddNormal
|
||||
* @param aN1
|
||||
* @param aN2
|
||||
* @param aN3
|
||||
*/
|
||||
void AddNormal( const SFVEC3F &aN1,
|
||||
const SFVEC3F &aN2,
|
||||
const SFVEC3F &aN3,
|
||||
const SFVEC3F &aN4 );
|
||||
|
||||
/**
|
||||
* @brief GetVertexPointer - Get the array of vertexes
|
||||
* @return The pointer to the start of array vertex
|
||||
*/
|
||||
const float *GetVertexPointer() const { return (const float *)&m_vertexs[0].x; }
|
||||
|
||||
/**
|
||||
* @brief GetNormalsPointer - Get the array of normals
|
||||
* @return The pointer to start of array of normals
|
||||
*/
|
||||
const float *GetNormalsPointer() const { return (const float *)&m_normals[0].x; }
|
||||
|
||||
/**
|
||||
* @brief GetVertexSize
|
||||
* @return
|
||||
*/
|
||||
unsigned int GetVertexSize() const { return (unsigned int)m_vertexs.size(); }
|
||||
|
||||
/**
|
||||
* @brief GetNormalsSize
|
||||
* @return
|
||||
*/
|
||||
unsigned int GetNormalsSize() const { return (unsigned int)m_normals.size(); }
|
||||
|
||||
private:
|
||||
SFVEC3F_VECTOR m_vertexs; ///< vertex array
|
||||
SFVEC3F_VECTOR m_normals; ///< normals array
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief The CLAYER_TRIANGLES class stores arrays of triangles to be used to
|
||||
* create display lists
|
||||
*/
|
||||
class CLAYER_TRIANGLES
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief CLAYER_TRIANGLES - initialize arrays with reserved triangles
|
||||
* @param aNrReservedTriangles: number of pre alloc triangles to reserve
|
||||
*/
|
||||
explicit CLAYER_TRIANGLES( unsigned int aNrReservedTriangles );
|
||||
|
||||
/**
|
||||
* @brief ~CLAYER_TRIANGLES - Free containers
|
||||
*/
|
||||
~CLAYER_TRIANGLES();
|
||||
|
||||
/**
|
||||
* @brief IsLayersSizeValid - check if the vertex arrays of the layers are
|
||||
* as expected
|
||||
* @return TRUE if layers are correctly setup
|
||||
*/
|
||||
bool IsLayersSizeValid();
|
||||
|
||||
|
||||
void AddToMiddleContourns( const SHAPE_LINE_CHAIN &outlinePath,
|
||||
float zBot,
|
||||
float zTop,
|
||||
double aBiuTo3Du,
|
||||
bool aInvertFaceDirection );
|
||||
|
||||
void AddToMiddleContourns( const SHAPE_POLY_SET &aPolySet,
|
||||
float zBot,
|
||||
float zTop,
|
||||
double aBiuTo3Du,
|
||||
bool aInvertFaceDirection );
|
||||
|
||||
void AddToMiddleContourns( const std::vector< SFVEC2F > &aContournPoints,
|
||||
float zBot,
|
||||
float zTop,
|
||||
bool aInvertFaceDirection );
|
||||
|
||||
std::mutex m_middle_layer_lock;
|
||||
|
||||
CLAYER_TRIANGLE_CONTAINER *m_layer_top_segment_ends;
|
||||
CLAYER_TRIANGLE_CONTAINER *m_layer_top_triangles;
|
||||
CLAYER_TRIANGLE_CONTAINER *m_layer_middle_contourns_quads;
|
||||
CLAYER_TRIANGLE_CONTAINER *m_layer_bot_triangles;
|
||||
CLAYER_TRIANGLE_CONTAINER *m_layer_bot_segment_ends;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief The CLAYERS_OGL_DISP_LISTS class stores the openGL display lists to
|
||||
* related with a layer
|
||||
*/
|
||||
class CLAYERS_OGL_DISP_LISTS
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief CLAYERS_OGL_DISP_LISTS - Creates the display lists for a layer
|
||||
* @param aLayerTriangles: contains the layers array of vertex to render to
|
||||
* display lists
|
||||
* @param aTextureIndexForSegEnds: texture index to be used by segment ends.
|
||||
* It is a black and white squared texture
|
||||
* with a center circle diameter of the size
|
||||
* of the texture.
|
||||
*/
|
||||
CLAYERS_OGL_DISP_LISTS( const CLAYER_TRIANGLES &aLayerTriangles,
|
||||
GLuint aTextureIndexForSegEnds,
|
||||
float aZBot,
|
||||
float aZTop );
|
||||
|
||||
/**
|
||||
* @brief ~CLAYERS_OGL_DISP_LISTS - Destroy this class while free the display
|
||||
* lists from GPU mem
|
||||
*/
|
||||
~CLAYERS_OGL_DISP_LISTS();
|
||||
|
||||
/**
|
||||
* @brief DrawTopAndMiddle - This function calls the display lists for the
|
||||
* top elements and middle contourns
|
||||
*/
|
||||
void DrawTopAndMiddle() const;
|
||||
|
||||
/**
|
||||
* @brief DrawBotAndMiddle - This function calls the display lists for the
|
||||
* botton elements and middle contourns
|
||||
*/
|
||||
void DrawBotAndMiddle() const;
|
||||
|
||||
/**
|
||||
* @brief DrawTop - This function calls the display lists for the top elements
|
||||
*/
|
||||
void DrawTop() const;
|
||||
|
||||
/**
|
||||
* @brief DrawBot - This function calls the display lists for the botton elements
|
||||
*/
|
||||
void DrawBot() const;
|
||||
|
||||
/**
|
||||
* @brief DrawMiddle - This function calls the display lists for the middle
|
||||
* elements
|
||||
*/
|
||||
void DrawMiddle() const;
|
||||
|
||||
/**
|
||||
* @brief DrawAll - This function calls all the display lists
|
||||
*/
|
||||
void DrawAll( bool aDrawMiddle = true ) const;
|
||||
|
||||
/**
|
||||
* @brief DrawAllCameraCulled - Draw all layers if they are visible by the camera.
|
||||
* i.e.: if camera position is above the layer. This only works because the
|
||||
* board is centered and the planes are always perpendicular to the Z axis.
|
||||
* @param zCameraPos: camera z position
|
||||
*/
|
||||
void DrawAllCameraCulled( float zCameraPos, bool aDrawMiddle = true ) const;
|
||||
|
||||
void DrawAllCameraCulledSubtractLayer( const CLAYERS_OGL_DISP_LISTS *aLayerToSubtractA,
|
||||
const CLAYERS_OGL_DISP_LISTS *aLayerToSubtractB,
|
||||
bool aDrawMiddle = true ) const;
|
||||
|
||||
void ApplyScalePosition( float aZposition, float aZscale );
|
||||
|
||||
void ClearScalePosition() { m_haveTransformation = false; }
|
||||
|
||||
void SetItIsTransparent( bool aSetTransparent );
|
||||
|
||||
float GetZBot() const { return m_zBot; }
|
||||
float GetZTop() const { return m_zTop; }
|
||||
|
||||
private:
|
||||
GLuint generate_top_or_bot_seg_ends( const CLAYER_TRIANGLE_CONTAINER * aTriangleContainer,
|
||||
bool aIsNormalUp,
|
||||
GLuint aTextureId ) const;
|
||||
|
||||
GLuint generate_top_or_bot_triangles( const CLAYER_TRIANGLE_CONTAINER * aTriangleContainer,
|
||||
bool aIsNormalUp ) const;
|
||||
|
||||
GLuint generate_middle_triangles( const CLAYER_TRIANGLE_CONTAINER * aTriangleContainer ) const;
|
||||
|
||||
void beginTransformation() const;
|
||||
void endTransformation() const;
|
||||
|
||||
void setBlendfunction() const;
|
||||
|
||||
private:
|
||||
float m_zBot;
|
||||
float m_zTop;
|
||||
GLuint m_layer_top_segment_ends;
|
||||
GLuint m_layer_top_triangles;
|
||||
GLuint m_layer_middle_contourns_quads;
|
||||
GLuint m_layer_bot_triangles;
|
||||
GLuint m_layer_bot_segment_ends;
|
||||
|
||||
bool m_haveTransformation;
|
||||
float m_zPositionTransformation;
|
||||
float m_zScaleTransformation;
|
||||
|
||||
bool m_draw_it_transparent;
|
||||
};
|
||||
|
||||
#endif // CLAYER_TRIANGLES_H_
|
||||
@@ -1,280 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file ogl_legacy_utils.cpp
|
||||
* @brief
|
||||
*/
|
||||
|
||||
|
||||
#include "../../common_ogl/openGL_includes.h"
|
||||
#include "ogl_legacy_utils.h"
|
||||
#include <trigo.h>
|
||||
#include <wx/debug.h> // For the wxASSERT
|
||||
|
||||
#define RADPERDEG 0.0174533
|
||||
|
||||
void OGL_draw_arrow( SFVEC3F aPosition, SFVEC3F aTargetPos, float aSize )
|
||||
{
|
||||
wxASSERT( aSize > 0.0f );
|
||||
|
||||
SFVEC3F vec = (aTargetPos - aPosition);
|
||||
float length = glm::length( vec );
|
||||
|
||||
GLUquadricObj *quadObj;
|
||||
|
||||
glPushMatrix ();
|
||||
|
||||
glTranslatef( aPosition.x, aPosition.y, aPosition.z );
|
||||
|
||||
if( ( vec.x != 0.0f ) || ( vec.y != 0.0f ) )
|
||||
{
|
||||
glRotatef( atan2( vec.y, vec.x ) / RADPERDEG, 0.0f, 0.0f, 1.0f );
|
||||
glRotatef( atan2( sqrt( vec.x * vec.x + vec.y * vec.y ), vec.z ) / RADPERDEG,
|
||||
0.0f,
|
||||
1.0f,
|
||||
0.0f );
|
||||
|
||||
} else if( vec.z < 0.0f )
|
||||
{
|
||||
glRotatef( 180.0f, 1.0f, 0.0f, 0.0f );
|
||||
}
|
||||
|
||||
glTranslatef( 0.0f, 0.0f, length - 4.0f * aSize );
|
||||
|
||||
quadObj = gluNewQuadric();
|
||||
gluQuadricDrawStyle( quadObj, GLU_FILL );
|
||||
gluQuadricNormals( quadObj, GLU_SMOOTH );
|
||||
gluCylinder( quadObj, 2.0 * aSize, 0.0, 4.0 * aSize, 12, 1 );
|
||||
gluDeleteQuadric( quadObj );
|
||||
|
||||
quadObj = gluNewQuadric();
|
||||
gluQuadricDrawStyle( quadObj, GLU_FILL );
|
||||
gluQuadricNormals( quadObj, GLU_SMOOTH );
|
||||
gluDisk( quadObj, 0.0, 2.0 * aSize, 12, 1 );
|
||||
gluDeleteQuadric( quadObj );
|
||||
|
||||
quadObj = gluNewQuadric();
|
||||
gluQuadricDrawStyle( quadObj, GLU_FILL );
|
||||
gluQuadricNormals( quadObj, GLU_SMOOTH );
|
||||
gluDisk( quadObj, 0.0, aSize, 12, 1 );
|
||||
gluDeleteQuadric( quadObj );
|
||||
|
||||
|
||||
quadObj = gluNewQuadric();
|
||||
gluQuadricDrawStyle( quadObj, GLU_FILL );
|
||||
gluQuadricNormals( quadObj, GLU_SMOOTH );
|
||||
gluSphere( quadObj, aSize, 24, 24 );
|
||||
gluDeleteQuadric( quadObj );
|
||||
|
||||
glTranslatef( 0.0f , 0.0f ,-length + 4.0f * aSize );
|
||||
|
||||
quadObj = gluNewQuadric();
|
||||
gluQuadricDrawStyle( quadObj, GLU_FILL );
|
||||
gluQuadricNormals( quadObj, GLU_SMOOTH );
|
||||
gluCylinder( quadObj, aSize, aSize, length - 4.0 * aSize, 12, 1 );
|
||||
gluDeleteQuadric( quadObj );
|
||||
/*
|
||||
|
||||
quadObj = gluNewQuadric();
|
||||
gluQuadricDrawStyle( quadObj, GLU_FILL );
|
||||
gluQuadricNormals( quadObj, GLU_SMOOTH );
|
||||
gluSphere( quadObj, aSize, 24, 24 );
|
||||
gluDeleteQuadric( quadObj );
|
||||
*/
|
||||
|
||||
quadObj = gluNewQuadric();
|
||||
gluQuadricDrawStyle( quadObj, GLU_FILL );
|
||||
gluQuadricNormals( quadObj, GLU_SMOOTH );
|
||||
gluDisk( quadObj, 0.0, aSize, 12, 1 );
|
||||
gluDeleteQuadric( quadObj );
|
||||
|
||||
glPopMatrix ();
|
||||
}
|
||||
|
||||
|
||||
void OGL_draw_bbox( const CBBOX &aBBox )
|
||||
{
|
||||
wxASSERT( aBBox.IsInitialized() );
|
||||
|
||||
glBegin( GL_LINE_LOOP );
|
||||
glVertex3f( aBBox.Min().x, aBBox.Min().y, aBBox.Min().z );
|
||||
glVertex3f( aBBox.Max().x, aBBox.Min().y, aBBox.Min().z );
|
||||
glVertex3f( aBBox.Max().x, aBBox.Max().y, aBBox.Min().z );
|
||||
glVertex3f( aBBox.Min().x, aBBox.Max().y, aBBox.Min().z );
|
||||
glEnd();
|
||||
|
||||
glBegin( GL_LINE_LOOP );
|
||||
glVertex3f( aBBox.Min().x, aBBox.Min().y, aBBox.Max().z );
|
||||
glVertex3f( aBBox.Max().x, aBBox.Min().y, aBBox.Max().z );
|
||||
glVertex3f( aBBox.Max().x, aBBox.Max().y, aBBox.Max().z );
|
||||
glVertex3f( aBBox.Min().x, aBBox.Max().y, aBBox.Max().z );
|
||||
glEnd();
|
||||
|
||||
glBegin( GL_LINE_STRIP );
|
||||
glVertex3f( aBBox.Min().x, aBBox.Min().y, aBBox.Min().z );
|
||||
glVertex3f( aBBox.Min().x, aBBox.Min().y, aBBox.Max().z );
|
||||
glEnd();
|
||||
|
||||
glBegin( GL_LINE_STRIP );
|
||||
glVertex3f( aBBox.Max().x, aBBox.Min().y, aBBox.Min().z );
|
||||
glVertex3f( aBBox.Max().x, aBBox.Min().y, aBBox.Max().z );
|
||||
glEnd();
|
||||
|
||||
glBegin( GL_LINE_STRIP );
|
||||
glVertex3f( aBBox.Max().x, aBBox.Max().y, aBBox.Min().z );
|
||||
glVertex3f( aBBox.Max().x, aBBox.Max().y, aBBox.Max().z );
|
||||
glEnd();
|
||||
|
||||
glBegin( GL_LINE_STRIP );
|
||||
glVertex3f( aBBox.Min().x, aBBox.Max().y, aBBox.Min().z );
|
||||
glVertex3f( aBBox.Min().x, aBBox.Max().y, aBBox.Max().z );
|
||||
glEnd();
|
||||
}
|
||||
|
||||
|
||||
void OGL_draw_half_open_cylinder( unsigned int aNrSidesPerCircle )
|
||||
{
|
||||
if( aNrSidesPerCircle > 1 )
|
||||
{
|
||||
const float radius = 0.5f;
|
||||
const int delta = 3600 / aNrSidesPerCircle;
|
||||
|
||||
// Generate bottom
|
||||
glNormal3f( 0.0f, 0.0f,-1.0f );
|
||||
glBegin( GL_TRIANGLE_FAN );
|
||||
glVertex3f( 0.0, 0.0, 0.0 ); // This is the V0 of the FAN
|
||||
|
||||
for( int ii = 0; ii < 1800; ii += delta )
|
||||
{
|
||||
SFVEC2D corner = SFVEC2D( 0.0, radius );
|
||||
RotatePoint( &corner.x, &corner.y, ii );
|
||||
glVertex3f( corner.x, corner.y, 0.0 );
|
||||
}
|
||||
|
||||
glVertex3d( 0.0, -radius, 0.0 );
|
||||
glEnd();
|
||||
|
||||
// Generate top
|
||||
glNormal3f( 0.0f, 0.0f, 1.0f );
|
||||
glBegin( GL_TRIANGLE_FAN );
|
||||
glVertex3f( 0.0, 0.0, 1.0 ); // This is the V0 of the FAN
|
||||
|
||||
for( int ii = 1800; ii > 0; ii -= delta )
|
||||
{
|
||||
SFVEC2D corner = SFVEC2D( 0.0, radius );
|
||||
|
||||
RotatePoint( &corner.x, &corner.y, ii );
|
||||
glVertex3f( corner.x, corner.y, 1.0 );
|
||||
}
|
||||
|
||||
glVertex3f( 0.0, radius, 1.0 );
|
||||
glEnd();
|
||||
|
||||
// Generate contours
|
||||
glBegin( GL_QUAD_STRIP );
|
||||
|
||||
for( int ii = 1800; ii > 0; ii -= delta )
|
||||
{
|
||||
SFVEC2D corner = SFVEC2D( 0.0, radius );
|
||||
|
||||
RotatePoint( &corner.x, &corner.y, ii );
|
||||
glNormal3f( corner.x * 2.0f, corner.y * 2.0f, 0.0f );
|
||||
glVertex3f( corner.x, corner.y, 1.0 );
|
||||
glVertex3f( corner.x, corner.y, 0.0 );
|
||||
}
|
||||
|
||||
glNormal3f( 0.0, 1.0f, 0.0f );
|
||||
glVertex3d( 0.0, radius, 1.0 );
|
||||
glVertex3d( 0.0, radius, 0.0 );
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OGL_Draw_segment( const CROUNDSEGMENT2D &aSegment,
|
||||
unsigned int aNrSidesPerCircle )
|
||||
{
|
||||
glPushMatrix();
|
||||
|
||||
const SFVEC2F start = aSegment.GetStart();
|
||||
const SFVEC2F end_minus_start = aSegment.GetEnd_minus_Start();
|
||||
const float radius = aSegment.GetRadius();
|
||||
const float width = aSegment.GetWidth();
|
||||
const float length = aSegment.GetLength();
|
||||
|
||||
glTranslatef( start.x, start.y, 0.0f );
|
||||
|
||||
if( ( end_minus_start.x != 0.0f ) || ( end_minus_start.y != 0.0f ) )
|
||||
{
|
||||
glRotatef( atan2( end_minus_start.y, end_minus_start.x ) / RADPERDEG,
|
||||
0.0f,
|
||||
0.0f,
|
||||
1.0f );
|
||||
}
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef( length, 0.0, 0.0f );
|
||||
glScalef( width, width, 1.0f );
|
||||
OGL_draw_half_open_cylinder( aNrSidesPerCircle );
|
||||
glPopMatrix();
|
||||
|
||||
glBegin( GL_QUADS );
|
||||
glNormal3f( 0.0,-1.0, 0.0 );
|
||||
glVertex3f( length,-radius, 1.0 );
|
||||
glVertex3f( 0.0, -radius, 1.0 );
|
||||
glVertex3f( 0.0, -radius, 0.0 );
|
||||
glVertex3f( length,-radius, 0.0 );
|
||||
glEnd();
|
||||
|
||||
glBegin( GL_QUADS );
|
||||
glNormal3f( 0.0, 1.0, 0.0 );
|
||||
glVertex3f( length, radius, 0.0 );
|
||||
glVertex3f( 0.0, radius, 0.0 );
|
||||
glVertex3f( 0.0, radius, 1.0 );
|
||||
glVertex3f( length, radius, 1.0 );
|
||||
glEnd();
|
||||
|
||||
glBegin( GL_QUADS );
|
||||
glNormal3f( 0.0, 0.0, 1.0 );
|
||||
glVertex3f( length, radius, 1.0 );
|
||||
glVertex3f( 0.0, radius, 1.0 );
|
||||
glVertex3f( 0.0, -radius, 1.0 );
|
||||
glVertex3f( length,-radius, 1.0 );
|
||||
glEnd();
|
||||
|
||||
glBegin( GL_QUADS );
|
||||
glNormal3f( 0.0, 0.0,-1.0 );
|
||||
glVertex3f( length,-radius, 0.0 );
|
||||
glVertex3f( 0.0, -radius, 0.0 );
|
||||
glVertex3f( 0.0, radius, 0.0 );
|
||||
glVertex3f( length, radius, 0.0 );
|
||||
glEnd();
|
||||
|
||||
glScalef( width, width, 1.0f );
|
||||
glRotatef( 180, 0.0, 0.0, 1.0 );
|
||||
OGL_draw_half_open_cylinder( aNrSidesPerCircle );
|
||||
|
||||
glPopMatrix ();
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file ogl_legacy_utils.h
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef OGL_LEGACY_UTILS_H_
|
||||
#define OGL_LEGACY_UTILS_H_
|
||||
|
||||
#include "../3d_render_raytracing/shapes3D/cbbox.h"
|
||||
#include "../3d_render_raytracing/shapes2D/croundsegment2d.h"
|
||||
|
||||
/**
|
||||
* @brief OGL_draw_arrow - draw a round arrow
|
||||
* @param aPosition: start position of the arrow
|
||||
* @param aTargetPos: end position of the arror
|
||||
* @param aSize: diameter size
|
||||
*/
|
||||
void OGL_draw_arrow( SFVEC3F aPosition, SFVEC3F aTargetPos, float aSize );
|
||||
|
||||
|
||||
/**
|
||||
* @brief OGL_draw_bbox - draw the bounding box lines
|
||||
* @param aBBox is the box to draw
|
||||
*/
|
||||
void OGL_draw_bbox( const CBBOX &aBBox );
|
||||
|
||||
|
||||
/**
|
||||
* @brief OGL_draw_half_open_cylinder - draws an open half cylinder
|
||||
* with diameter 1.0f and Height 1.0f
|
||||
* the bottom center is at (0,0,0) and top center is at (0,0,1)
|
||||
* @param aNrSidesPerCircle is the number of segments to approximate a circle.
|
||||
*/
|
||||
void OGL_draw_half_open_cylinder( unsigned int aNrSidesPerCircle );
|
||||
|
||||
|
||||
/**
|
||||
* @brief OGL_Draw_segment draws a thick segment with rounded ends
|
||||
* @param aSegment is the thick segment to draw
|
||||
* @param aNrSidesPerCircle is the number of segments to approximate a circle.
|
||||
* used to draw the rounded ends of the segment
|
||||
*/
|
||||
void OGL_Draw_segment( const CROUNDSEGMENT2D &aSegment,
|
||||
unsigned int aNrSidesPerCircle );
|
||||
|
||||
#endif // OGL_LEGACY_UTILS_H_
|
||||
@@ -1,212 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file PerlinNoise.h
|
||||
* @brief This source code comes from the project:
|
||||
* https://github.com/sol-prog/Perlin_Noise
|
||||
*
|
||||
* It was changed to work with floats instead of doubles
|
||||
*
|
||||
* Original copyright notice:
|
||||
*
|
||||
* Perlin_Noise
|
||||
* Here you could find the code for "Perlin noise in C++11", for more informations visit the project webpage:
|
||||
* http://solarianprogrammer.com/2012/07/18/perlin-noise-cpp-11/
|
||||
* You could use this program under the terms of GPL v3, for more details see:
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
* Copyright 2012 Sol from www.solarianprogrammer.com
|
||||
*/
|
||||
|
||||
#include "PerlinNoise.h"
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <random>
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
|
||||
// THIS IS A DIRECT TRANSLATION TO C++11 FROM THE REFERENCE
|
||||
// JAVA IMPLEMENTATION OF THE IMPROVED PERLIN FUNCTION (see http://mrl.nyu.edu/~perlin/noise/)
|
||||
// THE ORIGINAL JAVA IMPLEMENTATION IS COPYRIGHT 2002 KEN PERLIN
|
||||
|
||||
// I ADDED AN EXTRA METHOD THAT GENERATES A NEW PERMUTATION VECTOR
|
||||
// (THIS IS NOT PRESENT IN THE ORIGINAL IMPLEMENTATION)
|
||||
|
||||
// Initialize with the reference values for the permutation vector
|
||||
PerlinNoise::PerlinNoise()
|
||||
{
|
||||
|
||||
// Initialize the permutation vector with the reference values
|
||||
p = {
|
||||
151,160,137,91,90,15,131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,
|
||||
8,99,37,240,21,10,23,190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,
|
||||
35,11,32,57,177,33,88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,
|
||||
134,139,48,27,166,77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,
|
||||
55,46,245,40,244,102,143,54, 65,25,63,161,1,216,80,73,209,76,132,187,208, 89,
|
||||
18,169,200,196,135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,
|
||||
250,124,123,5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,
|
||||
189,28,42,223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167,
|
||||
43,172,9,129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,
|
||||
97,228,251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,
|
||||
107,49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
|
||||
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180 };
|
||||
|
||||
// Duplicate the permutation vector
|
||||
p.insert(p.end(), p.begin(), p.end());
|
||||
}
|
||||
|
||||
// Generate a new permutation vector based on the value of seed
|
||||
PerlinNoise::PerlinNoise( unsigned int seed )
|
||||
{
|
||||
p.resize( 256 );
|
||||
|
||||
// Fill p with values from 0 to 255
|
||||
std::iota( p.begin(), p.end(), 0 );
|
||||
|
||||
// Initialize a random engine with seed
|
||||
std::default_random_engine engine( seed );
|
||||
|
||||
// Suffle using the above random engine
|
||||
std::shuffle( p.begin(), p.end(), engine );
|
||||
|
||||
// Duplicate the permutation vector
|
||||
p.insert( p.end(), p.begin(), p.end() );
|
||||
}
|
||||
|
||||
float PerlinNoise::noise( float x, float y, float z ) const
|
||||
{
|
||||
// Find the unit cube that contains the point
|
||||
int X = static_cast<int>( std::floor( x ) ) & 255;
|
||||
int Y = static_cast<int>( std::floor( y ) ) & 255;
|
||||
int Z = static_cast<int>( std::floor( z ) ) & 255;
|
||||
|
||||
// Find relative x, y,z of point in cube
|
||||
x -= std::floor( x );
|
||||
y -= std::floor( y );
|
||||
z -= std::floor( z );
|
||||
|
||||
// Compute fade curves for each of x, y, z
|
||||
const float u = fade( x );
|
||||
const float v = fade( y );
|
||||
const float w = fade( z );
|
||||
|
||||
// Hash coordinates of the 8 cube corners
|
||||
const int A = p[X] + Y;
|
||||
const int AA = p[A] + Z;
|
||||
const int AB = p[A + 1] + Z;
|
||||
const int B = p[X + 1] + Y;
|
||||
const int BA = p[B] + Z;
|
||||
const int BB = p[B + 1] + Z;
|
||||
|
||||
// Add blended results from 8 corners of cube
|
||||
const float res = lerp( w,
|
||||
lerp( v,
|
||||
lerp( u,
|
||||
grad( p[AA], x , y, z),
|
||||
grad( p[BA], x - 1, y, z) ),
|
||||
lerp( u,
|
||||
grad( p[AB], x , y - 1, z ),
|
||||
grad( p[BB], x - 1, y - 1, z) ) ),
|
||||
lerp( v,
|
||||
lerp( u,
|
||||
grad( p[AA + 1], x , y, z - 1 ),
|
||||
grad( p[BA + 1], x - 1, y, z - 1) ),
|
||||
lerp( u,
|
||||
grad( p[AB + 1], x , y - 1, z - 1 ),
|
||||
grad( p[BB + 1], x - 1, y - 1, z - 1 ) ) ) );
|
||||
|
||||
return (res + 1.0f) / 2.0f;
|
||||
}
|
||||
|
||||
|
||||
float PerlinNoise::noise( float x, float y ) const
|
||||
{
|
||||
// Find the unit cube that contains the point
|
||||
int X = static_cast<int>( std::floor( x ) ) & 255;
|
||||
int Y = static_cast<int>( std::floor( y ) ) & 255;
|
||||
|
||||
// Find relative x, y,z of point in cube
|
||||
x -= std::floor( x );
|
||||
y -= std::floor( y );
|
||||
|
||||
// Compute fade curves for each of x, y
|
||||
const float u = fade( x );
|
||||
const float v = fade( y );
|
||||
|
||||
// Hash coordinates of the 8 cube corners
|
||||
const int A = p[X] + Y;
|
||||
const int AA = p[A] + 0;
|
||||
const int AB = p[A + 1] + 0;
|
||||
const int B = p[X + 1] + Y;
|
||||
const int BA = p[B] + 0;
|
||||
const int BB = p[B + 1] + 0;
|
||||
|
||||
// Add blended results from 8 corners of cube
|
||||
const float res = lerp( v,
|
||||
lerp( u,
|
||||
grad( p[AA], x , y ),
|
||||
grad( p[BA], x - 1, y ) ),
|
||||
lerp( u,
|
||||
grad( p[AB], x , y - 1 ),
|
||||
grad( p[BB], x - 1, y - 1 ) ) );
|
||||
|
||||
return (res + 1.0f) / 2.0f;
|
||||
}
|
||||
|
||||
|
||||
float PerlinNoise::fade( float t ) const
|
||||
{
|
||||
return t * t * t * (t * (t * 6.0f - 15.0f) + 10.0f);
|
||||
}
|
||||
|
||||
|
||||
float PerlinNoise::lerp( float t, float a, float b ) const
|
||||
{
|
||||
return a + t * (b - a);
|
||||
}
|
||||
|
||||
|
||||
float PerlinNoise::grad( int hash, float x, float y, float z ) const
|
||||
{
|
||||
const int h = hash & 15;
|
||||
|
||||
// Convert lower 4 bits of hash inot 12 gradient directions
|
||||
const float u = h < 8 ? x : y;
|
||||
const float v = h < 4 ? y : h == 12 || h == 14 ? x : z;
|
||||
|
||||
return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
|
||||
}
|
||||
|
||||
|
||||
float PerlinNoise::grad( int hash, float x, float y ) const
|
||||
{
|
||||
const int h = hash & 15;
|
||||
|
||||
// Convert lower 4 bits of hash inot 12 gradient directions
|
||||
const float u = h < 8 ? x : y;
|
||||
const float v = h < 4 ? y : h == 12 || h == 14 ? x : 0.0f;
|
||||
|
||||
return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file PerlinNoise.h
|
||||
* @brief This source code comes from the project:
|
||||
* https://github.com/sol-prog/Perlin_Noise
|
||||
*
|
||||
* It was changed to work with floats instead of doubles
|
||||
*
|
||||
* Original copyright notice:
|
||||
*
|
||||
* Perlin_Noise
|
||||
* "Here you could find the code for "Perlin noise in C++11",
|
||||
* for more informations visit the project webpage:
|
||||
* http://solarianprogrammer.com/2012/07/18/perlin-noise-cpp-11/
|
||||
* You could use this program under the terms of GPL v3, for more details see:
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
* Copyright 2012 Sol from www.solarianprogrammer.com"
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
|
||||
// THIS CLASS IS A TRANSLATION TO C++11 FROM THE REFERENCE
|
||||
// JAVA IMPLEMENTATION OF THE IMPROVED PERLIN FUNCTION (see http://mrl.nyu.edu/~perlin/noise/)
|
||||
// THE ORIGINAL JAVA IMPLEMENTATION IS COPYRIGHT 2002 KEN PERLIN
|
||||
|
||||
// I ADDED AN EXTRA METHOD THAT GENERATES A NEW PERMUTATION VECTOR
|
||||
// (THIS IS NOT PRESENT IN THE ORIGINAL IMPLEMENTATION)
|
||||
|
||||
#ifndef PERLINNOISE_H
|
||||
#define PERLINNOISE_H
|
||||
|
||||
class PerlinNoise
|
||||
{
|
||||
// The permutation vector
|
||||
std::vector<int> p;
|
||||
|
||||
public:
|
||||
// Initialize with the reference values for the permutation vector
|
||||
PerlinNoise();
|
||||
|
||||
// Generate a new permutation vector based on the value of seed
|
||||
PerlinNoise( unsigned int seed );
|
||||
|
||||
// Returns between 0.0f and 1.0f
|
||||
float noise( float x, float y, float z ) const;
|
||||
float noise( float x, float y ) const;
|
||||
|
||||
private:
|
||||
float fade( float t ) const;
|
||||
float lerp( float t, float a, float b ) const;
|
||||
float grad( int hash, float x, float y, float z ) const;
|
||||
float grad( int hash, float x, float y ) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file caccelerator.cpp
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#include "caccelerator.h"
|
||||
|
||||
|
||||
CGENERICACCELERATOR::CGENERICACCELERATOR( )
|
||||
{
|
||||
m_bbox.Reset();
|
||||
}
|
||||
|
||||
CGENERICACCELERATOR::~CGENERICACCELERATOR()
|
||||
{
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file caccelerator.h
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef _CACCELERATOR_H_
|
||||
#define _CACCELERATOR_H_
|
||||
|
||||
#include "ccontainer.h"
|
||||
#include "../raypacket.h"
|
||||
|
||||
|
||||
class CGENERICACCELERATOR
|
||||
{
|
||||
protected:
|
||||
CBBOX m_bbox;
|
||||
|
||||
public:
|
||||
CGENERICACCELERATOR( );
|
||||
virtual ~CGENERICACCELERATOR();
|
||||
|
||||
virtual bool Intersect( const RAY &aRay, HITINFO &aHitInfo ) const = 0;
|
||||
|
||||
virtual bool Intersect( const RAY &aRay,
|
||||
HITINFO &aHitInfo,
|
||||
unsigned int aAccNodeInfo ) const = 0;
|
||||
|
||||
virtual bool Intersect( const RAYPACKET &aRayPacket,
|
||||
HITINFO_PACKET *aHitInfoPacket ) const = 0;
|
||||
|
||||
virtual bool IntersectP( const RAY &aRay, float aMaxDistance ) const = 0;
|
||||
};
|
||||
|
||||
#endif // _CACCELERATOR_H_
|
||||
@@ -1,295 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file cbvh_packet_traversal.cpp
|
||||
* @brief This file implementes packet traversal over the BVH PBRT implementation
|
||||
*/
|
||||
|
||||
#include "cbvh_pbrt.h"
|
||||
#include <wx/debug.h>
|
||||
|
||||
|
||||
#define BVH_RANGED_TRAVERSAL
|
||||
//#define BVH_PARTITION_TRAVERSAL
|
||||
|
||||
|
||||
#define MAX_TODOS 64
|
||||
|
||||
|
||||
struct StackNode
|
||||
{
|
||||
int cell;
|
||||
unsigned int ia; // Index to the first alive ray
|
||||
};
|
||||
|
||||
|
||||
static inline unsigned int getFirstHit( const RAYPACKET &aRayPacket,
|
||||
const CBBOX &aBBox,
|
||||
unsigned int ia,
|
||||
HITINFO_PACKET *aHitInfoPacket )
|
||||
{
|
||||
float hitT;
|
||||
|
||||
if( aBBox.Intersect( aRayPacket.m_ray[ia], &hitT ) )
|
||||
if( hitT < aHitInfoPacket[ia].m_HitInfo.m_tHit )
|
||||
return ia;
|
||||
|
||||
if( !aRayPacket.m_Frustum.Intersect( aBBox ) )
|
||||
return RAYPACKET_RAYS_PER_PACKET;
|
||||
|
||||
for( unsigned int i = ia + 1; i < RAYPACKET_RAYS_PER_PACKET; ++i )
|
||||
{
|
||||
if( aBBox.Intersect( aRayPacket.m_ray[i], &hitT ) )
|
||||
if( hitT < aHitInfoPacket[i].m_HitInfo.m_tHit )
|
||||
return i;
|
||||
}
|
||||
|
||||
return RAYPACKET_RAYS_PER_PACKET;
|
||||
}
|
||||
|
||||
|
||||
#ifdef BVH_RANGED_TRAVERSAL
|
||||
|
||||
static inline unsigned int getLastHit( const RAYPACKET &aRayPacket,
|
||||
const CBBOX &aBBox,
|
||||
unsigned int ia,
|
||||
HITINFO_PACKET *aHitInfoPacket )
|
||||
{
|
||||
for( unsigned int ie = (RAYPACKET_RAYS_PER_PACKET - 1); ie > ia; --ie )
|
||||
{
|
||||
float hitT;
|
||||
|
||||
if( aBBox.Intersect( aRayPacket.m_ray[ie], &hitT ) )
|
||||
if( hitT < aHitInfoPacket[ie].m_HitInfo.m_tHit )
|
||||
return ie + 1;
|
||||
}
|
||||
|
||||
return ia + 1;
|
||||
}
|
||||
|
||||
|
||||
// "Large Ray Packets for Real-time Whitted Ray Tracing"
|
||||
// http://cseweb.ucsd.edu/~ravir/whitted.pdf
|
||||
|
||||
// Ranged Traversal
|
||||
bool CBVH_PBRT::Intersect( const RAYPACKET &aRayPacket,
|
||||
HITINFO_PACKET *aHitInfoPacket ) const
|
||||
{
|
||||
if( m_nodes == NULL )
|
||||
return false;
|
||||
|
||||
if( (&m_nodes[0]) == NULL )
|
||||
return false;
|
||||
|
||||
bool anyHitted = false;
|
||||
int todoOffset = 0, nodeNum = 0;
|
||||
StackNode todo[MAX_TODOS];
|
||||
|
||||
unsigned int ia = 0;
|
||||
|
||||
while( true )
|
||||
{
|
||||
const LinearBVHNode *curCell = &m_nodes[nodeNum];
|
||||
|
||||
ia = getFirstHit( aRayPacket, curCell->bounds, ia, aHitInfoPacket );
|
||||
|
||||
if( ia < RAYPACKET_RAYS_PER_PACKET )
|
||||
{
|
||||
if( curCell->nPrimitives == 0 )
|
||||
{
|
||||
StackNode &node = todo[todoOffset++];
|
||||
node.cell = curCell->secondChildOffset;
|
||||
node.ia = ia;
|
||||
nodeNum = nodeNum + 1;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
const unsigned int ie = getLastHit( aRayPacket,
|
||||
curCell->bounds,
|
||||
ia,
|
||||
aHitInfoPacket );
|
||||
|
||||
for( int j = 0; j < curCell->nPrimitives; ++j )
|
||||
{
|
||||
const COBJECT *obj = m_primitives[curCell->primitivesOffset + j];
|
||||
|
||||
if( aRayPacket.m_Frustum.Intersect( obj->GetBBox() ) )
|
||||
{
|
||||
for( unsigned int i = ia; i < ie; ++i )
|
||||
{
|
||||
const bool hitted = obj->Intersect( aRayPacket.m_ray[i],
|
||||
aHitInfoPacket[i].m_HitInfo );
|
||||
|
||||
if( hitted )
|
||||
{
|
||||
anyHitted |= hitted;
|
||||
aHitInfoPacket[i].m_hitresult |= hitted;
|
||||
aHitInfoPacket[i].m_HitInfo.m_acc_node_info = nodeNum;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( todoOffset == 0 )
|
||||
break;
|
||||
|
||||
const StackNode &node = todo[--todoOffset];
|
||||
|
||||
nodeNum = node.cell;
|
||||
ia = node.ia;
|
||||
}
|
||||
|
||||
return anyHitted;
|
||||
|
||||
}// Ranged Traversal
|
||||
#endif
|
||||
|
||||
|
||||
// "Ray Tracing Deformable Scenes Using Dynamic Bounding Volume Hierarchies"
|
||||
// http://www.cs.cmu.edu/afs/cs/academic/class/15869-f11/www/readings/wald07_packetbvh.pdf
|
||||
|
||||
#ifdef BVH_PARTITION_TRAVERSAL
|
||||
|
||||
static inline unsigned int getLastHit( const RAYPACKET &aRayPacket,
|
||||
const CBBOX &aBBox,
|
||||
unsigned int ia,
|
||||
const unsigned int *aRayIndex,
|
||||
HITINFO_PACKET *aHitInfoPacket )
|
||||
{
|
||||
for( unsigned int ie = (RAYPACKET_RAYS_PER_PACKET - 1); ie > ia; --ie )
|
||||
{
|
||||
float hitT;
|
||||
|
||||
if( aBBox.Intersect( aRayPacket.m_ray[ aRayIndex[ie] ], &hitT ) )
|
||||
if( hitT < aHitInfoPacket[ aRayIndex[ie] ].m_HitInfo.m_tHit )
|
||||
return ie + 1;
|
||||
}
|
||||
|
||||
return ia + 1;
|
||||
}
|
||||
|
||||
|
||||
static inline unsigned int partRays( const RAYPACKET &aRayPacket,
|
||||
const CBBOX &aBBox,
|
||||
unsigned int ia,
|
||||
unsigned int *aRayIndex,
|
||||
HITINFO_PACKET *aHitInfoPacket )
|
||||
{
|
||||
|
||||
if( !aRayPacket.m_Frustum.Intersect( aBBox ) )
|
||||
return RAYPACKET_RAYS_PER_PACKET;
|
||||
|
||||
unsigned int ie = 0;
|
||||
|
||||
for( unsigned int i = 0; i < ia; ++i )
|
||||
{
|
||||
float hitT;
|
||||
if( aBBox.Intersect( aRayPacket.m_ray[ aRayIndex[i] ], &hitT ) )
|
||||
if( hitT < aHitInfoPacket[ aRayIndex[i] ].m_HitInfo.m_tHit )
|
||||
std::swap( aRayIndex[ie++], aRayIndex[i] );
|
||||
}
|
||||
|
||||
return ie;
|
||||
}
|
||||
|
||||
|
||||
bool CBVH_PBRT::Intersect( const RAYPACKET &aRayPacket,
|
||||
HITINFO_PACKET *aHitInfoPacket ) const
|
||||
{
|
||||
bool anyHitted = false;
|
||||
int todoOffset = 0, nodeNum = 0;
|
||||
StackNode todo[MAX_TODOS];
|
||||
|
||||
unsigned int I[RAYPACKET_RAYS_PER_PACKET];
|
||||
|
||||
memcpy( I, m_I, RAYPACKET_RAYS_PER_PACKET * sizeof( unsigned int ) );
|
||||
|
||||
unsigned int ia = 0;
|
||||
|
||||
while( true )
|
||||
{
|
||||
const LinearBVHNode *curCell = &m_nodes[nodeNum];
|
||||
|
||||
ia = partRays( aRayPacket, curCell->bounds, ia, I, aHitInfoPacket );
|
||||
|
||||
if( ia < RAYPACKET_RAYS_PER_PACKET )
|
||||
{
|
||||
if( curCell->nPrimitives == 0 )
|
||||
{
|
||||
StackNode &node = todo[todoOffset++];
|
||||
node.cell = curCell->secondChildOffset;
|
||||
node.ia = ia;
|
||||
nodeNum = nodeNum + 1;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int ie = getLastHit( aRayPacket,
|
||||
curCell->bounds,
|
||||
ia,
|
||||
I,
|
||||
aHitInfoPacket );
|
||||
|
||||
for( int j = 0; j < curCell->nPrimitives; ++j )
|
||||
{
|
||||
const COBJECT *obj = m_primitives[curCell->primitivesOffset + j];
|
||||
|
||||
if( aRayPacket.m_Frustum.Intersect( obj->GetBBox() ) )
|
||||
{
|
||||
for( unsigned int i = 0; i < ie; ++i )
|
||||
{
|
||||
unsigned int idx = I[i];
|
||||
|
||||
bool hitted = obj->Intersect(
|
||||
aRayPacket.m_ray[idx],
|
||||
aHitInfoPacket[idx].m_HitInfo );
|
||||
|
||||
if( hitted )
|
||||
{
|
||||
anyHitted |= hitted;
|
||||
aHitInfoPacket[idx].m_hitresult |= hitted;
|
||||
aHitInfoPacket[idx].m_HitInfo.m_acc_node_info = nodeNum;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( todoOffset == 0 )
|
||||
break;
|
||||
|
||||
const StackNode &node = todo[--todoOffset];
|
||||
|
||||
nodeNum = node.cell;
|
||||
ia = node.ia;
|
||||
}
|
||||
|
||||
return anyHitted;
|
||||
}// Partition Traversal
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,168 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file cbvh_pbrt.h
|
||||
* @brief This BVH implementation is based on the source code implementation
|
||||
* from the book "Physically Based Rendering" (v2 and v3)
|
||||
*
|
||||
* Adaptions performed:
|
||||
* - Types and class types adapted to KiCad project
|
||||
* - Convert some source to build in the C++ specification of KiCad
|
||||
* - Code style to match KiCad
|
||||
* - Asserts converted
|
||||
* - Use compare functions/structures for std::partition and std::nth_element
|
||||
*
|
||||
* The original source code have the following licence:
|
||||
*
|
||||
* "pbrt source code is Copyright(c) 1998-2015
|
||||
* Matt Pharr, Greg Humphreys, and Wenzel Jakob.
|
||||
*
|
||||
* This file is part of pbrt.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _CBVH_PBRT_H_
|
||||
#define _CBVH_PBRT_H_
|
||||
|
||||
#include "caccelerator.h"
|
||||
#include <list>
|
||||
#include <stdint.h>
|
||||
|
||||
// Forward Declarations
|
||||
struct BVHBuildNode;
|
||||
struct BVHPrimitiveInfo;
|
||||
struct MortonPrimitive;
|
||||
|
||||
struct LinearBVHNode
|
||||
{
|
||||
// 24 bytes
|
||||
CBBOX bounds;
|
||||
|
||||
// 4 bytes
|
||||
union
|
||||
{
|
||||
int primitivesOffset; ///< leaf
|
||||
int secondChildOffset; ///< interior
|
||||
};
|
||||
|
||||
// 4 bytes
|
||||
uint16_t nPrimitives; ///< 0 -> interior node
|
||||
uint8_t axis; ///< interior node: xyz
|
||||
uint8_t pad[1]; ///< ensure 32 byte total size
|
||||
};
|
||||
|
||||
|
||||
enum SPLITMETHOD
|
||||
{
|
||||
SPLIT_MIDDLE,
|
||||
SPLIT_EQUALCOUNTS,
|
||||
SPLIT_SAH,
|
||||
SPLIT_HLBVH
|
||||
};
|
||||
|
||||
|
||||
class CBVH_PBRT : public CGENERICACCELERATOR
|
||||
{
|
||||
|
||||
public:
|
||||
CBVH_PBRT( const CGENERICCONTAINER &aObjectContainer,
|
||||
int aMaxPrimsInNode = 4,
|
||||
SPLITMETHOD aSplitMethod = SPLIT_SAH );
|
||||
|
||||
~CBVH_PBRT();
|
||||
|
||||
// Imported from CGENERICACCELERATOR
|
||||
bool Intersect( const RAY &aRay, HITINFO &aHitInfo ) const override;
|
||||
bool Intersect( const RAY &aRay, HITINFO &aHitInfo, unsigned int aAccNodeInfo ) const override;
|
||||
bool Intersect( const RAYPACKET &aRayPacket, HITINFO_PACKET *aHitInfoPacket ) const override;
|
||||
bool IntersectP( const RAY &aRay, float aMaxDistance ) const override;
|
||||
|
||||
private:
|
||||
|
||||
BVHBuildNode *recursiveBuild( std::vector<BVHPrimitiveInfo> &primitiveInfo,
|
||||
int start,
|
||||
int end,
|
||||
int *totalNodes,
|
||||
CONST_VECTOR_OBJECT &orderedPrims );
|
||||
|
||||
BVHBuildNode *HLBVHBuild( const std::vector<BVHPrimitiveInfo> &primitiveInfo,
|
||||
int *totalNodes,
|
||||
CONST_VECTOR_OBJECT &orderedPrims );
|
||||
|
||||
//!TODO: after implement memory arena, put const back to this functions
|
||||
BVHBuildNode *emitLBVH( BVHBuildNode *&buildNodes,
|
||||
const std::vector<BVHPrimitiveInfo> &primitiveInfo,
|
||||
MortonPrimitive *mortonPrims,
|
||||
int nPrimitives,
|
||||
int *totalNodes,
|
||||
CONST_VECTOR_OBJECT &orderedPrims,
|
||||
int *orderedPrimsOffset,
|
||||
int bit );
|
||||
|
||||
BVHBuildNode *buildUpperSAH( std::vector<BVHBuildNode *> &treeletRoots,
|
||||
int start,
|
||||
int end,
|
||||
int *totalNodes );
|
||||
|
||||
int flattenBVHTree( BVHBuildNode *node,
|
||||
uint32_t *offset );
|
||||
|
||||
// BVH Private Data
|
||||
const int m_maxPrimsInNode;
|
||||
SPLITMETHOD m_splitMethod;
|
||||
CONST_VECTOR_OBJECT m_primitives;
|
||||
LinearBVHNode *m_nodes;
|
||||
|
||||
std::list<void *> m_addresses_pointer_to_mm_free;
|
||||
|
||||
// Partition traversal
|
||||
unsigned int m_I[RAYPACKET_RAYS_PER_PACKET];
|
||||
};
|
||||
|
||||
#endif // _CBVH_PBRT_H_
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user