Compare commits
890 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2758acfd42 | |||
| 54c3031d74 | |||
| 9a9c7856b3 | |||
| 401b2fb524 | |||
| 0a0a2da680 | |||
| e4df76d986 | |||
| 79028f1627 | |||
| d87e5cb809 | |||
| 3484334d15 | |||
| 9ab6571b3f | |||
| dad5600e7e | |||
| ee56d58173 | |||
| 9f8f2a2449 | |||
| f591534a0f | |||
| 7a2e0c6632 | |||
| 29519c5fda | |||
| 4b996f6bbe | |||
| e4a5bfc788 | |||
| 4c58397949 | |||
| 011b4027db | |||
| a1adc59cb8 | |||
| ee4a8fc05a | |||
| 420a3ce498 | |||
| 9b6798c479 | |||
| 765816ccb1 | |||
| f3e9e3497b | |||
| 8e9e1a618b | |||
| 7272020cd3 | |||
| 16fff71c31 | |||
| 190223949c | |||
| 38d463ae49 | |||
| 73193196d2 | |||
| 2975e85950 | |||
| b2fbf982a8 | |||
| 0843fbf904 | |||
| 8dab9041e4 | |||
| 6aed98f795 | |||
| c20a76f3e2 | |||
| 435b1720c3 | |||
| 22bdf37fc2 | |||
| 9e3ac0eafb | |||
| 5c1c24cdab | |||
| c9cc824761 | |||
| b3c1e0330a | |||
| 4506fb2022 | |||
| ecec324121 | |||
| 959b33c59b | |||
| d6646c34ef | |||
| b56ac54cb2 | |||
| 5bc47a0c3b | |||
| f2db83008a | |||
| 9a01cf1b35 | |||
| 0f6f30b26e | |||
| 8219334806 | |||
| e6997d87b3 | |||
| 13b453c21e | |||
| 4ec3f18fda | |||
| fc8ffd8421 | |||
| 4551651777 | |||
| 82f2e8c344 | |||
| b76c5c9433 | |||
| 1737927814 | |||
| 38d7ac6d9c | |||
| db1bf4351b | |||
| 2d491f9cbd | |||
| a58d0f8a67 | |||
| 42cd6ca4ca | |||
| f292f1628b | |||
| 20909d4948 | |||
| 1f6ff4a519 | |||
| 07568f87c3 | |||
| 267e510071 | |||
| 73b921d591 | |||
| 8677035989 | |||
| a179893d70 | |||
| 540fb91d34 | |||
| 591a07d2d9 | |||
| f607e913d5 | |||
| 3d57de91e8 | |||
| 9fbceaa458 | |||
| 281180512f | |||
| 50fa1937f9 | |||
| d79aee3f78 | |||
| f599185e2d | |||
| fd79c7ae46 | |||
| 9de0846f3e | |||
| f168ece461 | |||
| 4100650ce1 | |||
| 87bb437fd3 | |||
| 626c671448 | |||
| b532c4a2b8 | |||
| 276cb7590d | |||
| f66aae2213 | |||
| 17c4e21f34 | |||
| 3613bca5ea | |||
| eff9c46e59 | |||
| c186a42a54 | |||
| 676d35f559 | |||
| e8bc4632b4 | |||
| 222158e954 | |||
| dde87b2f45 | |||
| 789284f519 | |||
| 19576ae167 | |||
| be8fe7bdd6 | |||
| d7a6a2cc71 | |||
| 7eea344f91 | |||
| 2bd0b67591 | |||
| d9307a174d | |||
| 59c5b30f3f | |||
| 938859f10a | |||
| a9b53d94e8 | |||
| a33e2ed9b1 | |||
| 7687ca2080 | |||
| 2a1a6e8cbe | |||
| 45fa9e8448 | |||
| 0ca66d1af3 | |||
| 63baa69342 | |||
| 894291faba | |||
| 51708bab49 | |||
| 4497a754fb | |||
| 6223e7475c | |||
| bf97378168 | |||
| 5a6f291c72 | |||
| 3404f4e86b | |||
| 6c07ebe5f2 | |||
| 24a4f06013 | |||
| 73bf4cbce7 | |||
| 67c8071bf4 | |||
| 9b163cb444 | |||
| 83d6a77617 | |||
| e5e174a20e | |||
| 8aede85214 | |||
| c625b9e3cc | |||
| 222d44a8d8 | |||
| 386f827d38 | |||
| 831c51c875 | |||
| 2d25d37112 | |||
| a3172d643f | |||
| 02787784a4 | |||
| 967f390aec | |||
| 89951b01ff | |||
| ca8f026bc3 | |||
| 4c14d7ef5a | |||
| 8234c20e28 | |||
| 52e272954f | |||
| 77caf50265 | |||
| 2ab8751fd4 | |||
| 54589c0828 | |||
| 1fdb247167 | |||
| 49cc47afd1 | |||
| 673677c831 | |||
| c30dc04571 | |||
| f58de79ceb | |||
| 8d9bb7a63e | |||
| 18490162f7 | |||
| bf71a4e012 | |||
| d29edf6381 | |||
| b087b7743e | |||
| 8ee1a7f67f | |||
| 475385d876 | |||
| 1b967a07e5 | |||
| 1088d613d5 | |||
| 1b2d4d6522 | |||
| 0fd1214dea | |||
| 00547b7aac | |||
| 621bfe36a8 | |||
| c1849f7e00 | |||
| b23db7c4cb | |||
| b3525bc642 | |||
| 589951eaea | |||
| 74adbbcc5d | |||
| bab61dd249 | |||
| 5c3bcb09fa | |||
| f0b94dd0d4 | |||
| ba5ab99a03 | |||
| 9bc3028eb7 | |||
| 5ef9db6d67 | |||
| 86a710e175 | |||
| 1797a9c61a | |||
| fd49bc5d8d | |||
| de4c6c6fab | |||
| 78a7dd3269 | |||
| 0cf53da0fe | |||
| 13b8708e58 | |||
| b6d91bd28a | |||
| 5bdc78e3ba | |||
| bce8fb31ab | |||
| 77d7d21130 | |||
| fed1520a8e | |||
| 284d5861dd | |||
| ee6154c842 | |||
| 709197c294 | |||
| fd55b7b4ed | |||
| 5bca5e2d77 | |||
| ee96937fd4 | |||
| a370d69542 | |||
| 24aad2eed4 | |||
| 910605cc7d | |||
| 7194e25bba | |||
| 7f287cb8f9 | |||
| a0ce1491d9 | |||
| 26035d23fe | |||
| 835debe75e | |||
| b482deb8b0 | |||
| 76fd1e6f5a | |||
| abb45fbe45 | |||
| 567ce48cc1 | |||
| 56a17b4e68 | |||
| c027e72439 | |||
| 25b8da8e3b | |||
| 5b47d1a910 | |||
| a844c3043c | |||
| e099a82d15 | |||
| b681af4556 | |||
| 78d66a9ac3 | |||
| bfe4d9f3f4 | |||
| a02ee3719c | |||
| 542f713678 | |||
| 2395c6fdaa | |||
| c7f02d5e51 | |||
| 55a726e933 | |||
| 601633347c | |||
| 182973c0ee | |||
| a16e9ac76a | |||
| 66f70e5da6 | |||
| 5a187c6ca8 | |||
| c6042100f9 | |||
| fde7ae4d19 | |||
| e37e13e700 | |||
| d22003578e | |||
| 52139cf0c4 | |||
| 37b723d8ae | |||
| aec3649524 | |||
| 36d716bb50 | |||
| f61c692929 | |||
| 3f717f3baf | |||
| ffc95090aa | |||
| 2eaa9236f2 | |||
| e4bab37b62 | |||
| 105c9c71ee | |||
| e135229ca6 | |||
| 97dea6ede5 | |||
| d871a92d1c | |||
| a152aa125b | |||
| 4e217d4028 | |||
| e5da7a4606 | |||
| faace3090c | |||
| d3e2345f94 | |||
| a3e087ab51 | |||
| 3a614a8ea1 | |||
| 9cb60dcdf5 | |||
| af6db68816 | |||
| 305ed0b65a | |||
| 263efb41e8 | |||
| d6312c7b92 | |||
| b31af4891d | |||
| 0ba08f57f2 | |||
| a2d7881afe | |||
| d79e598bf8 | |||
| a6a39cb842 | |||
| 5d0883c0e4 | |||
| e6d49424cf | |||
| 72abcd5991 | |||
| 9c2bb85858 | |||
| e9b059ee94 | |||
| 7a913844e2 | |||
| f8be7e1f57 | |||
| d5c43c4675 | |||
| 85fa6d8025 | |||
| 6b2a8f54a1 | |||
| bd1fb845b1 | |||
| 9c64c9af5d | |||
| 1057eceb2f | |||
| 445bc75319 | |||
| 4fb7ee02cd | |||
| ad11b7ebd0 | |||
| 5d9bda6f97 | |||
| 54be07c17d | |||
| 2c7ab3a28e | |||
| 3cc3c1bbd3 | |||
| ddedf2e046 | |||
| a60c339f85 | |||
| ce2c5d6528 | |||
| fd81f70355 | |||
| 100bb7c6ca | |||
| 1ffcedd9d4 | |||
| fc1f713106 | |||
| 83c3a78e6d | |||
| e6a3e7024d | |||
| d62fde0d79 | |||
| a70cf464d6 | |||
| 546260348d | |||
| 693aec949c | |||
| 5c7ac1bb7e | |||
| 8862752523 | |||
| 201c380925 | |||
| c7230a6f77 | |||
| 6b78fdf822 | |||
| 3cb326e426 | |||
| d3f9332372 | |||
| be0f6a6af2 | |||
| 25aa233cef | |||
| 5fdc424202 | |||
| 9b74bb5c92 | |||
| 8bf8a649c8 | |||
| 7ba8d8b608 | |||
| e35328fece | |||
| 366d4d7b0b | |||
| 3af1e75084 | |||
| dabd80fe4c | |||
| cb711a648f | |||
| 5b58dbc980 | |||
| 8b3c0a941c | |||
| 3ce29a3d7e | |||
| dc3c6b2f39 | |||
| 1cbee4c504 | |||
| 798e4c288a | |||
| ac39e32bc9 | |||
| 52da7f931b | |||
| fcb6f814de | |||
| 9e6b56d783 | |||
| 923dad6ca8 | |||
| 9f17d91b32 | |||
| 2bcb04a3b1 | |||
| a530b600b8 | |||
| d494a2bee2 | |||
| 6a027662ae | |||
| 577bb7bf31 | |||
| df664bd55f | |||
| 8a2705f81f | |||
| fcaf11422a | |||
| 3444409554 | |||
| 683c01b301 | |||
| e2492f773d | |||
| 1f3a2dcd1d | |||
| 4205cb32c5 | |||
| 6ab9bdb346 | |||
| a4aec1919c | |||
| 5b97d70d57 | |||
| eeeb4596c3 | |||
| 23853cae14 | |||
| 87f6f33b37 | |||
| 8c03d1bdde | |||
| 7f1c7d808d | |||
| be12aece5b | |||
| d7605f1449 | |||
| ef80642dec | |||
| a5622c93d4 | |||
| b6f9bfe9a5 | |||
| 79954657e2 | |||
| 35d3f1f72a | |||
| 388d74faf4 | |||
| 0f8747e194 | |||
| 93f16ba9e3 | |||
| bea2d42e8c | |||
| 68d644fd28 | |||
| f6e33450ff | |||
| 65008c5c0b | |||
| dbfaf568fc | |||
| 58fd6ac03e | |||
| 1e64524afb | |||
| 20a5d8effd | |||
| 8c7e0bcb0a | |||
| c69080f11e | |||
| 5a48c800ee | |||
| c6eff4d373 | |||
| 5c056c2a3e | |||
| 61f593f350 | |||
| 6cc7dc7aaa | |||
| 239f040a98 | |||
| 3827c16fde | |||
| e299343807 | |||
| 4130ce2b93 | |||
| d6acb64514 | |||
| 8e233e2591 | |||
| 9cda16220e | |||
| 36acadbd52 | |||
| 37b6552c42 | |||
| 1903052d79 | |||
| 2b4cfd9a60 | |||
| decbb65f09 | |||
| 8e2ca37edc | |||
| 8fb6bcc8b1 | |||
| 2f36c670ff | |||
| d701c3a480 | |||
| cd7f3375b2 | |||
| 46cd185524 | |||
| e04d82e940 | |||
| 26d0863921 | |||
| 37f23fa537 | |||
| 167d408b5e | |||
| d4a8ff4872 | |||
| fb9b12a982 | |||
| 88a03f1a1d | |||
| ba7e400e13 | |||
| 57f0f88552 | |||
| 42a0cf6283 | |||
| b67acd5ea1 | |||
| 5e2721d2f5 | |||
| 2cd43aee0a | |||
| fb1570d290 | |||
| 79972ad4db | |||
| 61934c285c | |||
| a7d554971c | |||
| e54ea90607 | |||
| fda403a079 | |||
| f2e75c96be | |||
| 322eb2b8a8 | |||
| 6f71183d0e | |||
| 5d852cf6ae | |||
| 2d1ea1618b | |||
| 50723d07a6 | |||
| 1161562bc8 | |||
| 0c8b3aaced | |||
| b81b7decf6 | |||
| e5463330ef | |||
| 17c0b3e460 | |||
| 3bc3193805 | |||
| d6db6dedca | |||
| d931bc72c7 | |||
| 6506f77689 | |||
| 0d64b38dbc | |||
| 7856061cf0 | |||
| 0210e414d2 | |||
| 41231e8ae2 | |||
| ba2e34682e | |||
| b234ff9234 | |||
| 3442cc3d1a | |||
| e618e34c94 | |||
| 105c3b0a4c | |||
| 69d0446019 | |||
| 078045f73b | |||
| 78af1daa2e | |||
| 0bd0d57a81 | |||
| 9dd5b6ce37 | |||
| d862cdaa72 | |||
| 4f57de9688 | |||
| 92b6e05909 | |||
| 2bd0bae2f7 | |||
| 69b5d24f28 | |||
| e5dcb9d9da | |||
| 4db8638f7e | |||
| cec885daf9 | |||
| 90fbf27114 | |||
| f1436cec9b | |||
| cf968cb6b5 | |||
| 2278f40051 | |||
| 18a76d3a87 | |||
| 6a65461ec7 | |||
| a5a0a7c4f3 | |||
| f1e6f8042c | |||
| 848873d87e | |||
| 75bb864237 | |||
| d5275b16aa | |||
| 15d1b6cef0 | |||
| 6d4dd3e17a | |||
| 649c22a34e | |||
| 8d04d39036 | |||
| 0e90c719b0 | |||
| a79526cad8 | |||
| d05d8b6100 | |||
| 9856867954 | |||
| 19064b680e | |||
| 95265c765b | |||
| 1ed8912f57 | |||
| 82a0eb4413 | |||
| be7215402b | |||
| 4500b064d8 | |||
| 93d191d7c9 | |||
| 1607ceaf3e | |||
| 5b24ea9dd9 | |||
| c879dcaf7d | |||
| 86691dabbf | |||
| fe71a66bb9 | |||
| 80e0d848f2 | |||
| 8b3a2984bf | |||
| fccce265aa | |||
| a43a228f78 | |||
| dd8610fd5c | |||
| b991beb712 | |||
| 25f6483488 | |||
| efc0325e14 | |||
| d19ec021fe | |||
| b34a307936 | |||
| fb565caf7b | |||
| 6796e8fff6 | |||
| 213547f545 | |||
| 73851e962b | |||
| de22204514 | |||
| ebba15fe67 | |||
| c1cd3339fa | |||
| 713a296a59 | |||
| 06bde527d5 | |||
| dcd31f5701 | |||
| 65f2af5849 | |||
| 2dd7a8637c | |||
| 211d056728 | |||
| dc0aed5b16 | |||
| 5064df4ba2 | |||
| 469c31da97 | |||
| 5fb41e6ecc | |||
| a68a442bbb | |||
| 84db5644d6 | |||
| fc1fb7a590 | |||
| dc91d4eca8 | |||
| f6a42a36d6 | |||
| 2a769dc0b0 | |||
| 3475bfb2aa | |||
| f9f8fade89 | |||
| e404fb772b | |||
| 2a9412042c | |||
| e8ab661504 | |||
| 3f91db25d4 | |||
| 300381ba4d | |||
| 4363e6a213 | |||
| 450dac4b1e | |||
| 278127fe29 | |||
| 23d71de75f | |||
| d86789898d | |||
| c3dc1f65d4 | |||
| 238fb00727 | |||
| 2d48c81d58 | |||
| 0893e0043f | |||
| 72c0267fe6 | |||
| c9956def36 | |||
| 5d60fe6812 | |||
| 6051dfae30 | |||
| 3518153d5b | |||
| cf949609b2 | |||
| d482a8805c | |||
| 161dc9ce7e | |||
| 090073cc3b | |||
| 6ae718e4d6 | |||
| 783b1cb611 | |||
| 4b01f80e8d | |||
| c8278f377b | |||
| d34b664933 | |||
| c8f40e1d26 | |||
| 185a8d7582 | |||
| 8373e91a1b | |||
| 6aeedfb70c | |||
| e7f3851212 | |||
| 7df05ade4c | |||
| 24b032ce5b | |||
| b6fe4ff637 | |||
| 8f1aa28b37 | |||
| 55c1e22a67 | |||
| ca0d4511a9 | |||
| b56855c542 | |||
| 72e8eb3b94 | |||
| 281a1cdc2c | |||
| 3c8f901a1f | |||
| e0589d2908 | |||
| dfd53976d4 | |||
| 02d43be93c | |||
| 2e8bceb676 | |||
| 16f9e697ab | |||
| 269f88ee28 | |||
| f11d950448 | |||
| 6ba2c44e88 | |||
| d1ed4665de | |||
| 5b68cfa018 | |||
| 85f88b6b05 | |||
| ea467441d2 | |||
| 40ba502853 | |||
| 09d7d0f1bc | |||
| 3418d53a6d | |||
| d5440d60ab | |||
| 2ba237ec12 | |||
| 01a343f28e | |||
| 85220591e2 | |||
| ecadc8bbba | |||
| 26c92eaf0f | |||
| d129abb9c9 | |||
| 3b98b00d6f | |||
| ce329e13fb | |||
| be9cd98cb1 | |||
| 216acd98d6 | |||
| 10fd8a59b2 | |||
| 3974c6fd89 | |||
| f82962e42c | |||
| bf1ced4184 | |||
| cabfcbc73c | |||
| 574473c480 | |||
| 17143fd53f | |||
| b8fff99e68 | |||
| 3b038feae0 | |||
| 032bda223e | |||
| b16d4d18e0 | |||
| df3a57dcda | |||
| 3bf7ab910f | |||
| e8ce0ba6ef | |||
| d8fff5c820 | |||
| aa9897d932 | |||
| f265a52c96 | |||
| f214cfae12 | |||
| febc8cd6aa | |||
| 463e061740 | |||
| d80759efb8 | |||
| 1d66aad4df | |||
| f5284ced54 | |||
| c951ca6f47 | |||
| f25ae373bb | |||
| 845833e8fd | |||
| f0ac61a8fd | |||
| 8f7278e34f | |||
| b124599de3 | |||
| 697234dd51 | |||
| ba97494d6f | |||
| 1996fba8a6 | |||
| a6bbe907ee | |||
| 43579f4c02 | |||
| 909a25c147 | |||
| aa3aafc4ff | |||
| b32439a694 | |||
| ddbc25077c | |||
| b075886b19 | |||
| eae999a85a | |||
| 77f0799750 | |||
| 8de93ad8b4 | |||
| b377b5bbed | |||
| 75b5324762 | |||
| 610d200e8a | |||
| 8002692f3e | |||
| 9496b57b01 | |||
| a5cd5844ec | |||
| da16b479a0 | |||
| 44f1059000 | |||
| cf4b41f7d9 | |||
| a84ca5b147 | |||
| 71f5f96e64 | |||
| 2aa8e444ee | |||
| cfa187f477 | |||
| 1ed411e431 | |||
| 9233ae97d0 | |||
| 0ee38653f7 | |||
| df89b5bf8a | |||
| cca4037fec | |||
| e015da8d95 | |||
| 4ceb186251 | |||
| 370109b868 | |||
| 3b3165ad51 | |||
| 98e68cd66a | |||
| 407301a28c | |||
| 5ce0e7265b | |||
| f1704fd61a | |||
| 35e87128f5 | |||
| dd93f89931 | |||
| fb85612f81 | |||
| 966173c129 | |||
| 55757039fa | |||
| 1113e18c40 | |||
| 02947345e8 | |||
| 63f18f0b03 | |||
| cd6da987cc | |||
| 006d7ddd31 | |||
| 81842fc9d0 | |||
| ec9e0b2086 | |||
| 64b71644bb | |||
| 1e58b09d96 | |||
| 455136ee50 | |||
| 1058ba6a0f | |||
| f8c541c0d7 | |||
| b485e78030 | |||
| d8e7892081 | |||
| 1638c3b1c2 | |||
| 2d0e92d412 | |||
| f1a43f4977 | |||
| 18f7d0129a | |||
| 356ccd0314 | |||
| 4adf89b40b | |||
| eb4aded5d6 | |||
| 5230f45658 | |||
| b4e70e56a6 | |||
| cb3edf2607 | |||
| 720b26d11e | |||
| e35be13b23 | |||
| ba19d93df9 | |||
| 5d1dcb4387 | |||
| f101934909 | |||
| ede2575018 | |||
| fb80ee5a0e | |||
| 44fc69398c | |||
| c162337cab | |||
| 821faaf3c0 | |||
| bf85eb9b4e | |||
| 691c6614a8 | |||
| 6db7cb8937 | |||
| 6afc572eae | |||
| 2a932a2176 | |||
| b2bcde1bfc | |||
| ec6fd23636 | |||
| 6f34f95c52 | |||
| 94e5b36279 | |||
| f0ce4d6336 | |||
| d06b42b917 | |||
| 764986a9b0 | |||
| c4efa95b4a | |||
| 5a655779d7 | |||
| 0403437ad0 | |||
| b62f94f5c2 | |||
| daf09ed9fe | |||
| 72794f1416 | |||
| b00e20b23f | |||
| e99a2181ff | |||
| 65b38e8dcf | |||
| 9b8780a2fd | |||
| 9c0e4cae74 | |||
| deb387f54c | |||
| 5d5422b4c5 | |||
| 85b8dd8b34 | |||
| b93d34dff4 | |||
| e997a7db9a | |||
| d1a065119e | |||
| 1dab468e20 | |||
| c5cd0c73a3 | |||
| ae139403e4 | |||
| d3c9154f9a | |||
| caba60968a | |||
| 2e0def8670 | |||
| 8c3d16a395 | |||
| 3f48531da7 | |||
| 128cdca068 | |||
| bd997a3900 | |||
| 8e93eda449 | |||
| a6674ecd56 | |||
| 654651856f | |||
| c489659a20 | |||
| 18377e0c9f | |||
| cebba6c0b9 | |||
| 89f9bf545d | |||
| 055d36abd7 | |||
| 7bafc5fa8b | |||
| 6946c0bedb | |||
| bb40f86daa | |||
| 89d198659c | |||
| c56e540e5d | |||
| d3fd74246f | |||
| 616061a6ca | |||
| d94b8b9c0e | |||
| 89d39cf8ff | |||
| 0ba130dbd3 | |||
| 434935613c | |||
| 454585d3d2 | |||
| 65a6e341ad | |||
| fc933034db | |||
| 20c8b094d6 | |||
| 552ddfbdfa | |||
| 9743eec3ab | |||
| b3ad1dc26e | |||
| b6c9d4a88c | |||
| 25b6ac61cb | |||
| 9c9252e8a3 | |||
| 3a744ad72f | |||
| 554e2a4bce | |||
| 6e8979d8d8 | |||
| 583d416640 | |||
| 03b50b4f85 | |||
| 440e135e3a | |||
| ab39f06003 | |||
| 98f78f534c | |||
| d18b12c1a3 | |||
| 6a7b1aa39a | |||
| c4be74a9d0 | |||
| 9092048dbc | |||
| bb419f1201 | |||
| d505fd2b60 | |||
| a771e0eccb | |||
| 593a5181d7 | |||
| c29274e760 | |||
| 216573bf48 | |||
| 1c235a5c89 | |||
| f90049dd9e | |||
| 90787e84bf | |||
| c36c80a077 | |||
| 227333239f | |||
| 2d43fcf9ee | |||
| 3edad56e6b | |||
| 4e2d900775 | |||
| 4dae82054e | |||
| cb5948d3a5 | |||
| 9fc7281fab | |||
| bb779b237a | |||
| 1294b4fec8 | |||
| 0b754562f6 | |||
| 15cb032ab7 | |||
| c85d2fd3bf | |||
| bc821ff47d | |||
| 42d9f42807 | |||
| 7ceff4cf5d | |||
| 4147da312b | |||
| 439891c31f | |||
| 322524101d | |||
| fd698653d9 | |||
| 8b503a06fa | |||
| 4a201df556 | |||
| 577b9f478b | |||
| f5a2eb1ab0 | |||
| 4379480d4b | |||
| dfa4afa826 | |||
| a533514763 | |||
| 952aaef52a | |||
| a54016a6f7 | |||
| 0c8a95c44b | |||
| 403633d21f | |||
| cc6f1d784d | |||
| e07ef3be9c | |||
| f35f534ff4 | |||
| 3899ec136b | |||
| 91ee809558 | |||
| 4c94e2729f | |||
| 2a5a207148 | |||
| c75bd89d63 | |||
| f58844bf8b | |||
| 07ac3499f3 | |||
| 050b64b822 | |||
| 43aa94dcfc | |||
| b2e54a432b | |||
| e766732020 | |||
| 3a5e01c44a | |||
| d4883da98b | |||
| 7cc3e9a16d | |||
| 9ad352d4bd | |||
| 031173bc47 | |||
| 658820a25e | |||
| 17fdce01a9 | |||
| bc4cc00332 | |||
| b57e9492b1 | |||
| 712bdc9d8d | |||
| 33a7c95455 | |||
| f054dcc77d | |||
| 95858b77c1 | |||
| 4afbce5ad6 | |||
| 93956002ac | |||
| 006dd290e9 | |||
| fb875145aa | |||
| 77993ced7e | |||
| e1f64d6283 | |||
| 2b60ce484e | |||
| a21b336138 | |||
| 0655280f2c | |||
| 2793578dcb | |||
| f1a70662c5 | |||
| 8a7e501fe6 | |||
| 86fc2dc2ba | |||
| 9cff42b4ed | |||
| 55546126a1 | |||
| 5a11dacd9e | |||
| bb5873bf20 | |||
| 20eda54349 | |||
| c98461f59e | |||
| b154c9a5c4 | |||
| 12255e3680 | |||
| 473c41ddbf | |||
| b93382831c | |||
| 5ee61f5ae7 | |||
| 082bbd49e7 | |||
| 4e2e69c9cb | |||
| 6f78bb6960 | |||
| a00caac789 | |||
| 4e8f191f43 | |||
| b1c5afd72f | |||
| aa5a2225e7 | |||
| 4c7672b581 | |||
| 5f9fa05e21 | |||
| ee92fa51bc | |||
| 63b3960120 | |||
| e5c76ddf3e | |||
| 4b07979008 | |||
| 168fa09f5f | |||
| 4facd57cb7 | |||
| e999636048 | |||
| 5bd769ea40 | |||
| bd693f97a1 | |||
| af0cb68c1b | |||
| 761d7fd438 | |||
| c537e8a892 | |||
| 702e85cd96 | |||
| c93e0b6c5e | |||
| f7b4a20066 | |||
| 49ac89bfed | |||
| 16e62b29f9 | |||
| b8180b0459 | |||
| 37f250b384 | |||
| 5685ec525b | |||
| 5be59ea8dd | |||
| 5855f2d909 | |||
| 5424223949 | |||
| de22148b44 | |||
| 73664e610b |
@@ -1,5 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
Checks: '-clang-diagnostic-*,clang-analyzer-*, bugprone-*, modernize-deprecated-headers, modernize-loop-convert, modernize-use-override, modernize-redundant-void-arg, modernize-use-emplace, modernize-use-noexcept, modernize-use-bool-literals, modernize-pass-by-value, modernize-use-equals-default, modernize-use-equals-delete, modernize-use-default-member-init, cppcoreguidelines-prefer-member-initializer, cppcoreguidelines-init-variables, cppcoreguidelines-pro-type-member-init'
|
||||
WarningsAsErrors: ''
|
||||
HeaderFilterRegex: '.*'
|
||||
FormatStyle: 'file'
|
||||
+2
-3
@@ -1,9 +1,9 @@
|
||||
|
||||
# Custom attribute to mark source files using KiCad C++ formatting
|
||||
[attr]kicad-cpp-source text=auto whitepace=tab-in-indent format.clang-format-kicad
|
||||
[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 text=auto whitespace=tab-in-indent
|
||||
[attr]kicad-cmake-source whitespace=tab-in-indent
|
||||
|
||||
# Custom attribute for auto-generated sources:
|
||||
# * Do not perform whitespace checking
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
*.cmake kicad-cmake-source
|
||||
*.txt kicad-cmake-source
|
||||
*.md text=auto
|
||||
|
||||
# Compiled bitmap sources
|
||||
bitmaps_png/cpp_*/*.cpp generated
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
community_bridge: kicad
|
||||
custom: "https://donate.cernandsocietyfoundation.cern/b/my-donation?cid=4&_cv=1"
|
||||
@@ -1,26 +0,0 @@
|
||||
name: 'Redirect PRs'
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: opened
|
||||
|
||||
jobs:
|
||||
lockdown:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dessant/repo-lockdown@v2
|
||||
with:
|
||||
github-token: ${{ github.token }}
|
||||
pr-comment: >
|
||||
Thank you for offering to help improve KiCad.
|
||||
This repository is a one-way mirror that can not accept pull requests.
|
||||
Please submit your merge request to the official KiCad repository
|
||||
at https://gitlab.com/kicad/code/kicad/-/merge_requests
|
||||
While we know that _your_ PR is not spam, we mark it as such to dissuade
|
||||
the Hacktoberfest PRs. Please join us over at GitLab. You can even use
|
||||
your GitHub credentials to log in there without creating a new account.
|
||||
skip-closed-pr-comment: true
|
||||
pr-labels: 'spam'
|
||||
close-pr: true
|
||||
lock-pr: true
|
||||
pr-lock-reason: 'spam'
|
||||
+10
-24
@@ -4,12 +4,10 @@ boost_root
|
||||
Build*
|
||||
build*
|
||||
common/fp_lib_table_keywords.cpp
|
||||
common/drc_rules_keywords.cpp
|
||||
common/drc_rules_lexer.h
|
||||
common/netlist_keywords.*
|
||||
common/netlist_lexer.h
|
||||
common/pcb_plot_params_lexer.h
|
||||
common/drawing_sheet/drawing_sheet_reader_keywords.cpp
|
||||
common/page_layout/page_layout_reader_keywords.cpp
|
||||
common/lib_table_keywords.*
|
||||
common/gal/opengl/shader_src.h
|
||||
include/fp_lib_table_lexer.h
|
||||
@@ -20,13 +18,15 @@ eeschema/cmp_library_lexer.h
|
||||
eeschema/cmp_library_keywords.*
|
||||
eeschema/dialogs/dialog_bom_cfg_keywords.cpp
|
||||
eeschema/dialogs/dialog_bom_cfg_lexer.h
|
||||
common/template_fieldnames_keywords.cpp
|
||||
common/template_fieldnames_lexer.h
|
||||
eeschema/schematic_keywords.*
|
||||
eeschema/sch_text_help_md.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
|
||||
pcbnew/dialogs/panel_setup_rules_help_md.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
|
||||
@@ -49,12 +49,13 @@ 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 auxiliary files
|
||||
# demo project auxillary files
|
||||
demos/**/*-bak
|
||||
demos/**/_autosave-*
|
||||
demos/**/fp-info-cache
|
||||
@@ -77,9 +78,7 @@ pcbnew/Info.plist
|
||||
*.png
|
||||
*.kiface
|
||||
*.o
|
||||
*.o.*
|
||||
*.a
|
||||
*.a.*
|
||||
*.cmake
|
||||
*.orig
|
||||
*.rej
|
||||
@@ -93,7 +92,6 @@ pcbnew/Info.plist
|
||||
!CMakeModules/*.cmake
|
||||
|
||||
# Eclipse IDE
|
||||
.settings/
|
||||
.project
|
||||
.cproject
|
||||
.pydevproject
|
||||
@@ -115,15 +113,3 @@ CMakeSettings.json
|
||||
*.mo
|
||||
i18n_status.svg
|
||||
i18n_status.csv
|
||||
|
||||
# Project local settings files and backups (in demos and qa tests)
|
||||
*.kicad_prl
|
||||
*-backups
|
||||
|
||||
# Don't actually ignore any of these files, since we need them in the tree
|
||||
!resources/linux/icons/hicolor/**/**/*
|
||||
!CMakeModules/**/*
|
||||
!bitmaps_png/png/**/*
|
||||
|
||||
# Junk temp files generated by MSVC for resource files
|
||||
/resources/msw/RC*
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
stages:
|
||||
- build
|
||||
- test
|
||||
- report
|
||||
|
||||
default:
|
||||
image:
|
||||
name: registry.gitlab.com/kicad/kicad-ci/source_containers/master/fedora:34
|
||||
entrypoint: ["/bin/sh", "-c"]
|
||||
|
||||
|
||||
##########################################################################
|
||||
# Test the formatting in a merge request using clang-format
|
||||
##########################################################################
|
||||
# The variable CI_COMMIT_BEFORE_SHA is not available in normal merge requests
|
||||
# so we must build the commit hash ourselves, see:
|
||||
# https://gitlab.com/gitlab-org/gitlab/issues/12850
|
||||
test_formatting:
|
||||
stage: test
|
||||
needs: []
|
||||
only:
|
||||
- merge_requests
|
||||
allow_failure: true
|
||||
before_script:
|
||||
# We must manually add the KiCad remote to ensure it is named sensibly
|
||||
- git remote add product https://gitlab.com/kicad/code/kicad.git
|
||||
- git remote add source ${CI_MERGE_REQUEST_SOURCE_PROJECT_URL}.git
|
||||
- git fetch -n product
|
||||
- git fetch -n source
|
||||
# Get the SHAs of the commits
|
||||
- "TARGET_HEAD_SHA=$(git rev-parse product/${CI_MERGE_REQUEST_TARGET_BRANCH_NAME})"
|
||||
- "SOURCE_HEAD_SHA=$(git rev-parse source/${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME})"
|
||||
- "MERGE_BASE_SHA=$(git merge-base ${TARGET_HEAD_SHA} ${SOURCE_HEAD_SHA})"
|
||||
script:
|
||||
- echo "Testing formatting from commit ${MERGE_BASE_SHA}"
|
||||
- ./tools/check_coding.sh --diff --ci --commit ${MERGE_BASE_SHA}
|
||||
|
||||
|
||||
include:
|
||||
- local: '/.gitlab/templates.yml'
|
||||
- local: '/.gitlab/Fedora-Linux-CI.yml'
|
||||
- local: '/.gitlab/Ubuntu-20.04-CI.yml'
|
||||
- local: '/.gitlab/Windows-CI.yml'
|
||||
- local: '/.gitlab/coverity.yml'
|
||||
- local: '/.gitlab/linux-metadata-validate.yml'
|
||||
@@ -1,93 +0,0 @@
|
||||
##########################################################################
|
||||
# Build KiCad on Fedora and save the results
|
||||
##########################################################################
|
||||
fedora_build_linux:
|
||||
stage: build
|
||||
tags:
|
||||
- kicad-fedora
|
||||
image: registry.gitlab.com/kicad/kicad-ci/source_containers/master/fedora:34
|
||||
extends: .only_code
|
||||
interruptible: false
|
||||
cache:
|
||||
key: "cache-fedora-linux"
|
||||
paths:
|
||||
- ccache/
|
||||
before_script:
|
||||
# CCache Config
|
||||
- mkdir -p ccache
|
||||
- export CCACHE_BASEDIR=${PWD}
|
||||
- export CCACHE_DIR=${PWD}/ccache
|
||||
script:
|
||||
- mkdir -p build/linux
|
||||
- cd build/linux
|
||||
- cmake
|
||||
-G Ninja
|
||||
-DCMAKE_BUILD_TYPE=Debug
|
||||
-DKICAD_STDLIB_LIGHT_DEBUG=ON
|
||||
-DKICAD_USE_OCC=ON
|
||||
-DKICAD_SPICE=ON
|
||||
-DKICAD_BUILD_I18N=ON
|
||||
../../
|
||||
- ninja 2>&1 | tee compilation_log.txt
|
||||
- cd ../../
|
||||
artifacts:
|
||||
# Only save the artifacts that are needed for running the tests in the next stage
|
||||
# and the compilation log. The entire build directory is too large to save as an
|
||||
# artifact.
|
||||
expire_in: 2 hrs
|
||||
when: always
|
||||
paths:
|
||||
- build/linux/3d-viewer/
|
||||
- build/linux/pcbnew/pcbnew.py
|
||||
- build/linux/pcbnew/_pcbnew.so
|
||||
- build/linux/qa/
|
||||
- build/linux/compilation_log.txt
|
||||
|
||||
# Upload the compilation log in an easily downloadable form
|
||||
fedora_report_build_warn:
|
||||
stage: report
|
||||
extends: .only_code
|
||||
when: always
|
||||
needs:
|
||||
- job: fedora_build_linux
|
||||
artifacts: true
|
||||
script:
|
||||
- echo "Uploading compilation log"
|
||||
- cp build/linux/compilation_log.txt compilation_log.txt
|
||||
artifacts:
|
||||
expire_in: 1 year
|
||||
expose_as: 'Build log'
|
||||
name: "build_log.txt"
|
||||
paths:
|
||||
- compilation_log.txt
|
||||
|
||||
# Report on the metrics of the code
|
||||
fedora_report_metrics:
|
||||
stage: report
|
||||
extends: .only_code
|
||||
when: always
|
||||
needs:
|
||||
- job: fedora_build_linux
|
||||
artifacts: true
|
||||
script:
|
||||
- cat build/linux/compilation_log.txt | { grep "warning:" || test $? = 1; } | awk 'END{print "number_of_fedora_warnings "NR}' > metrics.txt
|
||||
- cat metrics.txt
|
||||
artifacts:
|
||||
reports:
|
||||
metrics: metrics.txt
|
||||
|
||||
|
||||
##########################################################################
|
||||
# Run the code unit tests.
|
||||
##########################################################################
|
||||
fedora_qa:
|
||||
extends:
|
||||
- .unit_test
|
||||
- .only_code
|
||||
parallel:
|
||||
matrix:
|
||||
# The name of the test without the qa_ prefix
|
||||
- TEST: [python, common, gerbview, pcbnew, eeschema, kimath, sexpr, kicad2step]
|
||||
needs:
|
||||
- job: fedora_build_linux
|
||||
artifacts: true
|
||||
@@ -1,115 +0,0 @@
|
||||
##########################################################################
|
||||
# Build KiCad on Ubuntu 20.04 and save the results
|
||||
##########################################################################
|
||||
.ubuntu20.04_build:
|
||||
stage: build
|
||||
tags:
|
||||
- kicad-ubuntu20.04
|
||||
image: registry.gitlab.com/kicad/kicad-ci/source_containers/master/ubuntu:20.04
|
||||
only:
|
||||
- branches@kicad/code/kicad
|
||||
- tags@kicad/code/kicad
|
||||
except:
|
||||
- schedules
|
||||
interruptible: false
|
||||
cache:
|
||||
key: "cache-ubuntu20.04-linux"
|
||||
paths:
|
||||
- ccache/
|
||||
before_script:
|
||||
# CCache Config
|
||||
- mkdir -p ccache
|
||||
- export CCACHE_BASEDIR=${PWD}
|
||||
- export CCACHE_DIR=${PWD}/ccache
|
||||
script:
|
||||
- mkdir -p build/linux
|
||||
- cd build/linux
|
||||
- cmake
|
||||
-G Ninja
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
-DCMAKE_BUILD_TYPE=Debug
|
||||
-DKICAD_STDLIB_LIGHT_DEBUG=ON
|
||||
-DKICAD_SCRIPTING_WXPYTHON=ON
|
||||
-DKICAD_USE_OCC=ON
|
||||
-DKICAD_SPICE=ON
|
||||
-DKICAD_BUILD_I18N=ON
|
||||
-DKICAD_BUILD_PNS_DEBUG_TOOL=ON
|
||||
../../
|
||||
- ninja 2>&1 | tee compilation_log.txt
|
||||
- cd ../../
|
||||
artifacts:
|
||||
# Only save the artifacts that are needed for running the tests in the next stage
|
||||
# and the compilation log. The entire build directory is too large to save as an
|
||||
# artifact.
|
||||
expire_in: 2 hrs
|
||||
when: always
|
||||
paths:
|
||||
- build/linux/3d-viewer/
|
||||
- build/linux/pcbnew/pcbnew.py
|
||||
- build/linux/pcbnew/_pcbnew.so
|
||||
- build/linux/qa/
|
||||
- build/linux/compilation_log.txt
|
||||
|
||||
# Upload the compilation log in an easily downloadable form
|
||||
.ubuntu20.04_report_build_warn:
|
||||
stage: report
|
||||
when: always
|
||||
only:
|
||||
- branches@kicad/code/kicad
|
||||
- tags@kicad/code/kicad
|
||||
except:
|
||||
- schedules
|
||||
needs:
|
||||
- job: ubuntu20.04_build
|
||||
artifacts: true
|
||||
script:
|
||||
- echo "Uploading compilation log"
|
||||
- cp build/linux/compilation_log.txt compilation_log.txt
|
||||
artifacts:
|
||||
expire_in: 1 year
|
||||
expose_as: 'Build log'
|
||||
name: "build_log.txt"
|
||||
paths:
|
||||
- compilation_log.txt
|
||||
|
||||
# Report on the metrics of the code
|
||||
.ubuntu20.04_report_metrics:
|
||||
stage: report
|
||||
when: always
|
||||
only:
|
||||
- branches@kicad/code/kicad
|
||||
- tags@kicad/code/kicad
|
||||
except:
|
||||
- schedules
|
||||
needs:
|
||||
- job: ubuntu20.04_build
|
||||
artifacts: true
|
||||
script:
|
||||
- cat build/linux/compilation_log.txt | { grep "warning:" || test $? = 1; } | awk 'END{print "number_of_ubuntu_20.04_warnings "NR}' > metrics.txt
|
||||
- cat metrics.txt
|
||||
artifacts:
|
||||
reports:
|
||||
metrics: metrics.txt
|
||||
|
||||
##########################################################################
|
||||
# Run the code unit tests.
|
||||
##########################################################################
|
||||
.ubuntu20.04_qa:
|
||||
extends:
|
||||
- .unit_test
|
||||
needs:
|
||||
- job: ubuntu20.04_build
|
||||
artifacts: true
|
||||
tags:
|
||||
- kicad-ubuntu20.04
|
||||
image: registry.gitlab.com/kicad/kicad-ci/source_containers/master/ubuntu:20.04
|
||||
only:
|
||||
- branches@kicad/code/kicad
|
||||
- tags@kicad/code/kicad
|
||||
except:
|
||||
- schedules
|
||||
parallel:
|
||||
matrix:
|
||||
# The name of the test without the qa_ prefix
|
||||
- TEST: [python, common, gerbview, pcbnew, eeschema, kimath, sexpr, kicad2step]
|
||||
@@ -1,35 +0,0 @@
|
||||
##########################################################################
|
||||
# Build KiCad on Windows and save the results
|
||||
##########################################################################
|
||||
win64_build:
|
||||
stage: build
|
||||
tags:
|
||||
- kicad-windows-1809
|
||||
extends: .only_code
|
||||
interruptible: false
|
||||
image: registry.gitlab.com/kicad/kicad-ci/source_containers/win64:msvc1809
|
||||
only:
|
||||
- branches@kicad/code/kicad
|
||||
- tags@kicad/code/kicad
|
||||
script:
|
||||
- mkdir -p build/windows -Force
|
||||
- cd build/windows
|
||||
- cmake `
|
||||
-G "Ninja" `
|
||||
-DCMAKE_TOOLCHAIN_FILE=C:\build\vcpkg\scripts\buildsystems\vcpkg.cmake `
|
||||
-DCMAKE_BUILD_TYPE=Debug `
|
||||
-DKICAD_SCRIPTING_WXPYTHON=OFF `
|
||||
-DKICAD_USE_OCC=ON `
|
||||
-DKICAD_SPICE=ON `
|
||||
-DKICAD_BUILD_PNS_DEBUG_TOOL=ON `
|
||||
../../
|
||||
- cmake --build . 2>&1 | tee compilation_log.txt
|
||||
- cd ../../
|
||||
artifacts:
|
||||
# Only save the artifacts that are needed for running the tests in the next stage
|
||||
# and the compilation log. The entire build directory is too large to save as an
|
||||
# artifact.
|
||||
expire_in: 2 hrs
|
||||
when: always
|
||||
paths:
|
||||
- build/windows/compilation_log.txt
|
||||
@@ -1,72 +0,0 @@
|
||||
# This script is responsible for configuring the coverity file from the cache
|
||||
# (e.g. extracting it or updating it if needed)
|
||||
.coverity_cache_prep: &coverity_cache_prep |
|
||||
echo "Downloading MD5 hash of current Coverity Scan version to compare against cache"
|
||||
curl --output cov-analysis-linux64.md5 https://scan.coverity.com/download/linux64 \
|
||||
--form project=$COVERITY_SCAN_PROJECT_NAME \
|
||||
--form token=$COVERITY_SCAN_TOKEN \
|
||||
--form md5=1
|
||||
echo " *cov-analysis-linux64.tgz" >> cov-analysis-linux64.md5
|
||||
(md5sum --ignore-missing -c cov-analysis-linux64.md5) || (
|
||||
echo "Downloading new Coverity Scan version"
|
||||
curl --output cov-analysis-linux64.tgz https://scan.coverity.com/download/linux64 \
|
||||
--form project=$COVERITY_SCAN_PROJECT_NAME \
|
||||
--form token=$COVERITY_SCAN_TOKEN
|
||||
)
|
||||
echo "Extracting Coverity Scan"
|
||||
mkdir coverity/
|
||||
tar xzf cov-analysis-linux64.tgz --strip-components=1 -C coverity
|
||||
test -d coverity/bin
|
||||
|
||||
# This script is responsible for tar'ing and submitting the results of the build.
|
||||
# These results will be saved for 1 day if the build fails.
|
||||
.coverity_submit: &coverity_submit |
|
||||
echo "Creating tar file of scan results"
|
||||
tar cfz cov-int.tar.gz cov-int
|
||||
echo "Submitting scan results"
|
||||
export KICAD_VERSION=$(sed 's/[()]//g' kicad_build_version.txt)
|
||||
curl -v https://scan.coverity.com/builds?project=$COVERITY_SCAN_PROJECT_NAME \
|
||||
--form token=$COVERITY_SCAN_TOKEN \
|
||||
--form email=$GITLAB_USER_EMAIL \
|
||||
--form file=@cov-int.tar.gz \
|
||||
--form version="$KICAD_VERSION" \
|
||||
--form description="$KICAD_VERSION / $CI_COMMIT_TITLE" 2>&1 \
|
||||
| tee curl-response.txt
|
||||
grep -q 'Build successfully submitted' curl-response.txt
|
||||
|
||||
|
||||
Coverity:
|
||||
tags:
|
||||
- coverity
|
||||
stage: build
|
||||
# Use Fedora 33 because Coverity needs GCC 10 still (as of 06/16/2021)
|
||||
image: registry.gitlab.com/kicad/kicad-ci/source_containers/master/fedora:33
|
||||
only:
|
||||
refs:
|
||||
- schedules
|
||||
variables:
|
||||
- $SCHEDULED_JOB_NAME == "coverity"
|
||||
cache:
|
||||
key: coverity
|
||||
paths:
|
||||
- cov-analysis-linux64.tgz
|
||||
before_script:
|
||||
- export COVERITY_SCAN_PROJECT_NAME="kicad"
|
||||
- test "$(git rev-parse --is-shallow-repository)" = "false" || (git fetch --unshallow)
|
||||
- git fetch origin
|
||||
script:
|
||||
- *coverity_cache_prep
|
||||
- cmake
|
||||
-DCMAKE_BUILD_TYPE=Debug
|
||||
-DKICAD_STDLIB_LIGHT_DEBUG=ON
|
||||
-DKICAD_SCRIPTING_WXPYTHON=ON
|
||||
-DKICAD_USE_OCC=ON
|
||||
-DKICAD_SPICE=ON
|
||||
- coverity/bin/cov-build --dir cov-int make -j8
|
||||
- *coverity_submit
|
||||
artifacts:
|
||||
expire_in: 1 year
|
||||
expose_as: 'Coverity log'
|
||||
name: "coverity_log.txt"
|
||||
paths:
|
||||
- cov-int/build-log.txt
|
||||
@@ -1,40 +0,0 @@
|
||||
##########################################################################
|
||||
# Run a validation of the metadata files for Linux
|
||||
##########################################################################
|
||||
validate_linux_metadata:
|
||||
stage: test
|
||||
needs: []
|
||||
interruptible: false
|
||||
# This is the only CI image with the utilities needed for this test
|
||||
image: registry.gitlab.com/kicad/kicad-ci/source_containers/master/fedora:34
|
||||
# Due to bug https://github.com/hughsie/appstream-glib/issues/381, this doesn't think our description tag
|
||||
# is localized even though it actually is.
|
||||
allow_failure: true
|
||||
only:
|
||||
refs:
|
||||
- master
|
||||
- branches
|
||||
- merge_requests
|
||||
- pushes
|
||||
changes:
|
||||
# Only run if the resources, its tests, or the translations are updated
|
||||
- resources/linux/**/*
|
||||
- qa/resources/linux/**/*
|
||||
- translation/**/*
|
||||
except:
|
||||
- schedules
|
||||
# Only build the metadata files in this CI job
|
||||
script:
|
||||
- mkdir -p build/linux
|
||||
- cd build/linux
|
||||
- cmake
|
||||
-DCMAKE_BUILD_TYPE=Debug
|
||||
-DKICAD_STDLIB_LIGHT_DEBUG=ON
|
||||
-DKICAD_SCRIPTING_WXPYTHON=ON
|
||||
-DKICAD_USE_OCC=ON
|
||||
-DKICAD_SPICE=ON
|
||||
-DKICAD_BUILD_I18N=ON
|
||||
../../
|
||||
- make metadata
|
||||
- cd ../../
|
||||
- ./qa/resources/linux/verifyMetadataFiles.sh ./ ./build/linux
|
||||
@@ -1,37 +0,0 @@
|
||||
##########################################################################
|
||||
# This will allow the job to run whenever code events trigger it.
|
||||
##########################################################################
|
||||
.only_code:
|
||||
only:
|
||||
- master
|
||||
- branches
|
||||
- merge_requests
|
||||
- pushes
|
||||
except:
|
||||
- schedules
|
||||
|
||||
##########################################################################
|
||||
# Define a template for all the unit tests, since each one is run in a separate
|
||||
# job to make the display nicer.
|
||||
##########################################################################
|
||||
.unit_test:
|
||||
stage: test
|
||||
when: on_success
|
||||
# We define this using a before script because GitLab cannot merge variable
|
||||
# definitions across inheritance (so the variables block from this would disappear)
|
||||
before_script:
|
||||
- export BOOST_TEST_LOGGER='JUNIT,all,test_results.${TEST}.xml:HRF,warning'
|
||||
- export CTEST_OUTPUT_ON_FAILURE=1
|
||||
script:
|
||||
- cd build/linux/qa
|
||||
- ctest -R qa_${TEST}
|
||||
# GitLab supports displaying the results in the GUI through JUNIT artifacts
|
||||
# (https://docs.gitlab.com/ee/ci/junit_test_reports.html)
|
||||
# so we upload the JUNIT results. Note that there is a bug with how paths
|
||||
# are processed in the junit report (https://gitlab.com/gitlab-org/gitlab/issues/23835)
|
||||
# so we can't use a glob and have to list out each hierarchy separately.
|
||||
artifacts:
|
||||
reports:
|
||||
junit:
|
||||
- build/linux/qa/*/*.xml
|
||||
- build/linux/qa/*/*/*.xml
|
||||
+219
-191
@@ -2,7 +2,7 @@
|
||||
* 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-2020 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
@@ -24,11 +24,13 @@
|
||||
|
||||
#define GLM_FORCE_RADIANS
|
||||
|
||||
#include <mutex>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <utility>
|
||||
#include <iterator>
|
||||
|
||||
#include <wx/datetime.h>
|
||||
#include <wx/dir.h>
|
||||
#include <wx/filename.h>
|
||||
#include <wx/log.h>
|
||||
#include <wx/stdpaths.h>
|
||||
@@ -41,35 +43,28 @@
|
||||
#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 "3d_plugin_manager.h"
|
||||
#include "sg/scenegraph.h"
|
||||
#include "filename_resolver.h"
|
||||
#include "3d_plugin_manager.h"
|
||||
#include "plugins/3dapi/ifsg_api.h"
|
||||
|
||||
#include <advanced_config.h>
|
||||
#include <common.h> // For ExpandEnvVarSubstitutions
|
||||
#include <filename_resolver.h>
|
||||
#include <paths.h>
|
||||
#include <pgm_base.h>
|
||||
#include <project.h>
|
||||
#include <settings/common_settings.h>
|
||||
#include <settings/settings_manager.h>
|
||||
|
||||
|
||||
#define MASK_3D_CACHE "3D_CACHE"
|
||||
|
||||
static std::mutex mutex3D_cache;
|
||||
static std::mutex mutex3D_cacheManager;
|
||||
static wxCriticalSection lock3D_cache;
|
||||
|
||||
|
||||
static bool isSHA1Same( const unsigned char* shaA, const unsigned char* shaB ) noexcept
|
||||
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;
|
||||
}
|
||||
@@ -77,7 +72,7 @@ static bool isSHA1Same( const unsigned char* shaA, const unsigned char* shaB ) n
|
||||
|
||||
static bool checkTag( const char* aTag, void* aPluginMgrPtr )
|
||||
{
|
||||
if( nullptr == aTag || nullptr == aPluginMgrPtr )
|
||||
if( NULL == aTag || NULL == aPluginMgrPtr )
|
||||
return false;
|
||||
|
||||
S3D_PLUGIN_MANAGER *pp = (S3D_PLUGIN_MANAGER*) aPluginMgrPtr;
|
||||
@@ -122,60 +117,62 @@ static const wxString sha1ToWXString( const unsigned char* aSHA1Sum )
|
||||
|
||||
class S3D_CACHE_ENTRY
|
||||
{
|
||||
public:
|
||||
S3D_CACHE_ENTRY();
|
||||
~S3D_CACHE_ENTRY();
|
||||
|
||||
void SetSHA1( const unsigned char* aSHA1Sum );
|
||||
const wxString GetCacheBaseName();
|
||||
|
||||
wxDateTime modTime; // file modification time
|
||||
unsigned char sha1sum[20];
|
||||
std::string pluginInfo; // PluginName:Version string
|
||||
SCENEGRAPH* sceneData;
|
||||
S3DMODEL* renderData;
|
||||
|
||||
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 = nullptr;
|
||||
renderData = nullptr;
|
||||
sceneData = NULL;
|
||||
renderData = NULL;
|
||||
memset( sha1sum, 0, 20 );
|
||||
}
|
||||
|
||||
|
||||
S3D_CACHE_ENTRY::~S3D_CACHE_ENTRY()
|
||||
{
|
||||
delete sceneData;
|
||||
if( NULL != sceneData )
|
||||
delete sceneData;
|
||||
|
||||
if( nullptr != renderData )
|
||||
if( NULL != renderData )
|
||||
S3D::Destroy3DModel( &renderData );
|
||||
}
|
||||
|
||||
|
||||
void S3D_CACHE_ENTRY::SetSHA1( const unsigned char* aSHA1Sum )
|
||||
{
|
||||
if( nullptr == aSHA1Sum )
|
||||
if( NULL == aSHA1Sum )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, wxT( "%s:%s:%d\n * [BUG] NULL passed for 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()
|
||||
const wxString S3D_CACHE_ENTRY::GetCacheBaseName( void )
|
||||
{
|
||||
if( m_CacheBaseName.empty() )
|
||||
m_CacheBaseName = sha1ToWXString( sha1sum );
|
||||
@@ -186,49 +183,45 @@ const wxString S3D_CACHE_ENTRY::GetCacheBaseName()
|
||||
|
||||
S3D_CACHE::S3D_CACHE()
|
||||
{
|
||||
m_DirtyCache = false;
|
||||
m_FNResolver = new FILENAME_RESOLVER;
|
||||
m_project = nullptr;
|
||||
m_Plugins = new S3D_PLUGIN_MANAGER;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
S3D_CACHE::~S3D_CACHE()
|
||||
{
|
||||
COMMON_SETTINGS* commonSettings = Pgm().GetCommonSettings();
|
||||
|
||||
FlushCache();
|
||||
|
||||
// We'll delete ".3dc" cache files older than this many days
|
||||
int clearCacheInterval = commonSettings->m_System.clear_3d_cache_interval;
|
||||
if( m_FNResolver )
|
||||
delete m_FNResolver;
|
||||
|
||||
// An interval of zero means the user doesn't want to ever clear the cache
|
||||
if( m_Plugins )
|
||||
delete m_Plugins;
|
||||
|
||||
if( clearCacheInterval > 0 )
|
||||
CleanCacheDir( clearCacheInterval );
|
||||
|
||||
delete m_FNResolver;
|
||||
delete m_Plugins;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SCENEGRAPH* S3D_CACHE::load( const wxString& aModelFile, S3D_CACHE_ENTRY** aCachePtr )
|
||||
{
|
||||
if( aCachePtr )
|
||||
*aCachePtr = nullptr;
|
||||
*aCachePtr = NULL;
|
||||
|
||||
wxString full3Dpath = m_FNResolver->ResolvePath( aModelFile );
|
||||
|
||||
if( full3Dpath.empty() )
|
||||
{
|
||||
// the model cannot be found; we cannot proceed
|
||||
wxLogTrace( MASK_3D_CACHE, wxT( "%s:%s:%d\n * [3D model] could not find model '%s'\n" ),
|
||||
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * [3D model] could not find model '%s'\n",
|
||||
__FILE__, __FUNCTION__, __LINE__, aModelFile );
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// check cache if file is already loaded
|
||||
std::lock_guard<std::mutex> lock( mutex3D_cache );
|
||||
|
||||
wxCriticalSectionLocker lock( lock3D_cache );
|
||||
std::map< wxString, S3D_CACHE_ENTRY*, rsort_wxString >::iterator mi;
|
||||
mi = m_CacheMap.find( full3Dpath );
|
||||
|
||||
@@ -238,7 +231,7 @@ SCENEGRAPH* S3D_CACHE::load( const wxString& aModelFile, S3D_CACHE_ENTRY** aCach
|
||||
|
||||
if( fname.FileExists() ) // Only check if file exists. If not, it will
|
||||
{ // use the same model in cache.
|
||||
bool reload = ADVANCED_CFG::GetCfg().m_Skip3DModelMemoryCache;
|
||||
bool reload = false;
|
||||
wxDateTime fmdate = fname.GetModificationTime();
|
||||
|
||||
if( fmdate != mi->second->modTime )
|
||||
@@ -256,21 +249,20 @@ SCENEGRAPH* S3D_CACHE::load( const wxString& aModelFile, S3D_CACHE_ENTRY** aCach
|
||||
|
||||
if( reload )
|
||||
{
|
||||
if( nullptr != mi->second->sceneData )
|
||||
if( NULL != mi->second->sceneData )
|
||||
{
|
||||
S3D::DestroyNode( mi->second->sceneData );
|
||||
mi->second->sceneData = nullptr;
|
||||
mi->second->sceneData = NULL;
|
||||
}
|
||||
|
||||
if( nullptr != mi->second->renderData )
|
||||
if( NULL != mi->second->renderData )
|
||||
S3D::Destroy3DModel( &mi->second->renderData );
|
||||
|
||||
mi->second->sceneData = m_Plugins->Load3DModel( full3Dpath,
|
||||
mi->second->pluginInfo );
|
||||
mi->second->sceneData = m_Plugins->Load3DModel( full3Dpath, mi->second->pluginInfo );
|
||||
}
|
||||
}
|
||||
|
||||
if( nullptr != aCachePtr )
|
||||
if( NULL != aCachePtr )
|
||||
*aCachePtr = mi->second;
|
||||
|
||||
return mi->second->sceneData;
|
||||
@@ -290,25 +282,24 @@ SCENEGRAPH* S3D_CACHE::Load( const wxString& aModelFile )
|
||||
SCENEGRAPH* S3D_CACHE::checkCache( const wxString& aFileName, S3D_CACHE_ENTRY** aCachePtr )
|
||||
{
|
||||
if( aCachePtr )
|
||||
*aCachePtr = nullptr;
|
||||
*aCachePtr = NULL;
|
||||
|
||||
unsigned char sha1sum[20];
|
||||
S3D_CACHE_ENTRY* ep = new S3D_CACHE_ENTRY;
|
||||
m_CacheList.push_back( ep );
|
||||
wxFileName fname( aFileName );
|
||||
ep->modTime = fname.GetModificationTime();
|
||||
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,
|
||||
wxT( "%s:%s:%d\n * [BUG] duplicate entry in map file; key = '%s'" ),
|
||||
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * [BUG] duplicate entry in map file; key = '%s'",
|
||||
__FILE__, __FUNCTION__, __LINE__, aFileName );
|
||||
|
||||
m_CacheList.pop_back();
|
||||
@@ -318,21 +309,26 @@ SCENEGRAPH* S3D_CACHE::checkCache( const wxString& aFileName, S3D_CACHE_ENTRY**
|
||||
{
|
||||
if( aCachePtr )
|
||||
*aCachePtr = ep;
|
||||
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
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,
|
||||
wxT( "%s:%s:%d\n * [BUG] duplicate entry in map file; key = '%s'" ),
|
||||
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 nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( aCachePtr )
|
||||
@@ -343,13 +339,12 @@ SCENEGRAPH* S3D_CACHE::checkCache( const wxString& aFileName, S3D_CACHE_ENTRY**
|
||||
wxString bname = ep->GetCacheBaseName();
|
||||
wxString cachename = m_CacheDir + bname + wxT( ".3dc" );
|
||||
|
||||
if( !ADVANCED_CFG::GetCfg().m_Skip3DModelFileCache && wxFileName::FileExists( cachename )
|
||||
&& loadCacheData( ep ) )
|
||||
if( wxFileName::FileExists( cachename ) && loadCacheData( ep ) )
|
||||
return ep->sceneData;
|
||||
|
||||
ep->sceneData = m_Plugins->Load3DModel( aFileName, ep->pluginInfo );
|
||||
|
||||
if( !ADVANCED_CFG::GetCfg().m_Skip3DModelFileCache && nullptr != ep->sceneData )
|
||||
if( NULL != ep->sceneData )
|
||||
saveCacheData( ep );
|
||||
|
||||
return ep->sceneData;
|
||||
@@ -360,27 +355,27 @@ bool S3D_CACHE::getSHA1( const wxString& aFileName, unsigned char* aSHA1Sum )
|
||||
{
|
||||
if( aFileName.empty() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, wxT( "%s:%s:%d\n * [BUG] empty filename" ),
|
||||
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * [BUG] empty filename",
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( nullptr == aSHA1Sum )
|
||||
if( NULL == aSHA1Sum )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, wxT( "%s\n * [BUG] NULL pointer passed for aMD5Sum" ),
|
||||
wxLogTrace( MASK_3D_CACHE, "%s\n * [BUG] NULL pointer passed for aMD5Sum",
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef _WIN32
|
||||
FILE* fp = _wfopen( aFileName.wc_str(), L"rb" );
|
||||
#else
|
||||
#else
|
||||
FILE* fp = fopen( aFileName.ToUTF8(), "rb" );
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if( nullptr == fp )
|
||||
if( NULL == fp )
|
||||
return false;
|
||||
|
||||
boost::uuids::detail::sha1 dblock;
|
||||
@@ -419,7 +414,7 @@ bool S3D_CACHE::loadCacheData( S3D_CACHE_ENTRY* aCacheItem )
|
||||
if( bname.empty() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
wxT( " * [3D model] cannot load cached model; no file hash available" ) );
|
||||
" * [3D model] cannot load cached model; no file hash available" );
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -427,7 +422,7 @@ bool S3D_CACHE::loadCacheData( S3D_CACHE_ENTRY* aCacheItem )
|
||||
if( m_CacheDir.empty() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
wxT( " * [3D model] cannot load cached model; config directory unknown" ) );
|
||||
" * [3D model] cannot load cached model; config directory unknown" );
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -436,16 +431,17 @@ bool S3D_CACHE::loadCacheData( S3D_CACHE_ENTRY* aCacheItem )
|
||||
|
||||
if( !wxFileName::FileExists( fname ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, wxT( " * [3D model] cannot open file '%s'" ), fname.GetData() );
|
||||
wxString errmsg = "cannot open file";
|
||||
wxLogTrace( MASK_3D_CACHE, " * [3D model] %s '%s'", errmsg.GetData(), fname.GetData() );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( nullptr != aCacheItem->sceneData )
|
||||
if( NULL != aCacheItem->sceneData )
|
||||
S3D::DestroyNode( (SGNODE*) aCacheItem->sceneData );
|
||||
|
||||
aCacheItem->sceneData = (SCENEGRAPH*)S3D::ReadCache( fname.ToUTF8(), m_Plugins, checkTag );
|
||||
|
||||
if( nullptr == aCacheItem->sceneData )
|
||||
if( NULL == aCacheItem->sceneData )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -454,17 +450,17 @@ bool S3D_CACHE::loadCacheData( S3D_CACHE_ENTRY* aCacheItem )
|
||||
|
||||
bool S3D_CACHE::saveCacheData( S3D_CACHE_ENTRY* aCacheItem )
|
||||
{
|
||||
if( nullptr == aCacheItem )
|
||||
if( NULL == aCacheItem )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, wxT( "%s:%s:%d\n * NULL passed for aCacheItem" ),
|
||||
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * NULL passed for aCacheItem",
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( nullptr == aCacheItem->sceneData )
|
||||
if( NULL == aCacheItem->sceneData )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, wxT( "%s:%s:%d\n * aCacheItem has no valid scene data" ),
|
||||
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * aCacheItem has no valid scene data",
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
return false;
|
||||
@@ -475,7 +471,7 @@ bool S3D_CACHE::saveCacheData( S3D_CACHE_ENTRY* aCacheItem )
|
||||
if( bname.empty() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
wxT( " * [3D model] cannot load cached model; no file hash available" ) );
|
||||
" * [3D model] cannot load cached model; no file hash available" );
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -483,7 +479,7 @@ bool S3D_CACHE::saveCacheData( S3D_CACHE_ENTRY* aCacheItem )
|
||||
if( m_CacheDir.empty() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
wxT( " * [3D model] cannot load cached model; config directory unknown" ) );
|
||||
" * [3D model] cannot load cached model; config directory unknown" );
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -494,15 +490,15 @@ bool S3D_CACHE::saveCacheData( S3D_CACHE_ENTRY* aCacheItem )
|
||||
{
|
||||
if( !wxFileName::FileExists( fname ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
wxT( " * [3D model] path exists but is not a regular file '%s'" ), 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() );
|
||||
aCacheItem->pluginInfo.c_str() );
|
||||
}
|
||||
|
||||
|
||||
@@ -511,7 +507,12 @@ bool S3D_CACHE::Set3DConfigDir( const wxString& aConfigDir )
|
||||
if( !m_ConfigDir.empty() )
|
||||
return false;
|
||||
|
||||
wxFileName cfgdir( ExpandEnvVarSubstitutions( aConfigDir, m_project ), wxEmptyString );
|
||||
wxFileName cfgdir;
|
||||
|
||||
if( aConfigDir.StartsWith( "${" ) || aConfigDir.StartsWith( "$(" ) )
|
||||
cfgdir.Assign( ExpandEnvVarSubstitutions( aConfigDir ), "" );
|
||||
else
|
||||
cfgdir.Assign( aConfigDir, "" );
|
||||
|
||||
cfgdir.Normalize();
|
||||
|
||||
@@ -522,7 +523,7 @@ bool S3D_CACHE::Set3DConfigDir( const wxString& aConfigDir )
|
||||
if( !cfgdir.DirExists() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
wxT( "%s:%s:%d\n * failed to create 3D configuration directory '%s'" ),
|
||||
"%s:%s:%d\n * failed to create 3D configuration directory '%s'",
|
||||
__FILE__, __FUNCTION__, __LINE__, cfgdir.GetPath() );
|
||||
|
||||
return false;
|
||||
@@ -535,8 +536,8 @@ bool S3D_CACHE::Set3DConfigDir( const wxString& aConfigDir )
|
||||
if( !m_FNResolver->Set3DConfigDir( m_ConfigDir ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
wxT( "%s:%s:%d\n * could not set 3D Config Directory on filename resolver\n"
|
||||
" * config directory: '%s'" ),
|
||||
"%s:%s:%d\n * could not set 3D Config Directory on filename resolver\n"
|
||||
" * config directory: '%s'",
|
||||
__FILE__, __FUNCTION__, __LINE__, m_ConfigDir );
|
||||
}
|
||||
|
||||
@@ -547,36 +548,104 @@ bool S3D_CACHE::Set3DConfigDir( const wxString& aConfigDir )
|
||||
// 1. OSX: ~/Library/Caches/kicad/3d/
|
||||
// 2. Linux: ${XDG_CACHE_HOME}/kicad/3d ~/.cache/kicad/3d/
|
||||
// 3. MSWin: AppData\Local\kicad\3d
|
||||
wxFileName cacheDir;
|
||||
cacheDir.AssignDir( PATHS::GetUserCachePath() );
|
||||
cacheDir.AppendDir( wxT( "3d" ) );
|
||||
wxString cacheDir;
|
||||
|
||||
if( !cacheDir.DirExists() )
|
||||
#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() )
|
||||
{
|
||||
cacheDir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
|
||||
cfgdir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
|
||||
|
||||
if( !cacheDir.DirExists() )
|
||||
if( !cfgdir.DirExists() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
wxT( "%s:%s:%d\n * failed to create 3D cache directory '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, cacheDir.GetPath() );
|
||||
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * failed to create 3D cache directory '%s'",
|
||||
__FILE__, __FUNCTION__, __LINE__, cfgdir.GetPath() );
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_CacheDir = cacheDir.GetPathWithSep();
|
||||
m_CacheDir = cfgdir.GetPathWithSep();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool S3D_CACHE::SetProject( PROJECT* aProject )
|
||||
wxString S3D_CACHE::Get3DConfigDir( bool createDefault )
|
||||
{
|
||||
m_project = aProject;
|
||||
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->SetProject( aProject, &hasChanged ) && hasChanged )
|
||||
if( m_FNResolver->SetProjectDir( aProjDir, &hasChanged ) && hasChanged )
|
||||
{
|
||||
m_CacheMap.clear();
|
||||
|
||||
@@ -601,16 +670,23 @@ bool S3D_CACHE::SetProject( PROJECT* aProject )
|
||||
void S3D_CACHE::SetProgramBase( PGM_BASE* aBase )
|
||||
{
|
||||
m_FNResolver->SetProgramBase( aBase );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
FILENAME_RESOLVER* S3D_CACHE::GetResolver() noexcept
|
||||
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() const
|
||||
std::list< wxString > const* S3D_CACHE::GetFileFilters( void ) const
|
||||
{
|
||||
return m_Plugins->GetFileFilters();
|
||||
}
|
||||
@@ -632,31 +708,35 @@ void S3D_CACHE::FlushCache( bool closePlugins )
|
||||
|
||||
if( closePlugins )
|
||||
ClosePlugins();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D_CACHE::ClosePlugins()
|
||||
void S3D_CACHE::ClosePlugins( void )
|
||||
{
|
||||
if( m_Plugins )
|
||||
if( NULL != m_Plugins )
|
||||
m_Plugins->ClosePlugins();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
S3DMODEL* S3D_CACHE::GetModel( const wxString& aModelFileName )
|
||||
{
|
||||
S3D_CACHE_ENTRY* cp = nullptr;
|
||||
S3D_CACHE_ENTRY* cp = NULL;
|
||||
SCENEGRAPH* sp = load( aModelFileName, &cp );
|
||||
|
||||
if( !sp )
|
||||
return nullptr;
|
||||
return NULL;
|
||||
|
||||
if( !cp )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
wxT( "%s:%s:%d\n * [BUG] model loaded with no associated S3D_CACHE_ENTRY" ),
|
||||
"%s:%s:%d\n * [BUG] model loaded with no associated S3D_CACHE_ENTRY",
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( cp->renderData )
|
||||
@@ -668,79 +748,27 @@ S3DMODEL* S3D_CACHE::GetModel( const wxString& aModelFileName )
|
||||
return mp;
|
||||
}
|
||||
|
||||
void S3D_CACHE::CleanCacheDir( int aNumDaysOld )
|
||||
|
||||
wxString S3D_CACHE::GetModelHash( const wxString& aModelFileName )
|
||||
{
|
||||
wxDir dir;
|
||||
wxString fileSpec = wxT( "*.3dc" );
|
||||
wxArrayString fileList; // Holds list of ".3dc" files found in cache directory
|
||||
size_t numFilesFound = 0;
|
||||
wxString full3Dpath = m_FNResolver->ResolvePath( aModelFileName );
|
||||
|
||||
wxFileName thisFile;
|
||||
wxDateTime lastAccess, thresholdDate;
|
||||
wxDateSpan durationInDays;
|
||||
if( full3Dpath.empty() || !wxFileName::FileExists( full3Dpath ) )
|
||||
return wxEmptyString;
|
||||
|
||||
// Calc the threshold date above which we delete cache files
|
||||
durationInDays.SetDays( aNumDaysOld );
|
||||
thresholdDate = wxDateTime::Now() - durationInDays;
|
||||
// check cache if file is already loaded
|
||||
std::map< wxString, S3D_CACHE_ENTRY*, rsort_wxString >::iterator mi;
|
||||
mi = m_CacheMap.find( full3Dpath );
|
||||
|
||||
// If the cache directory can be found and opened, then we'll try and clean it up
|
||||
if( dir.Open( m_CacheDir ) )
|
||||
{
|
||||
thisFile.SetPath( m_CacheDir ); // Set the base path to the cache folder
|
||||
if( mi != m_CacheMap.end() )
|
||||
return mi->second->GetCacheBaseName();
|
||||
|
||||
// Get a list of all the ".3dc" files in the cache directory
|
||||
numFilesFound = dir.GetAllFiles( m_CacheDir, &fileList, fileSpec );
|
||||
// a cache item does not exist; search the Filename->Cachename map
|
||||
S3D_CACHE_ENTRY* cp = NULL;
|
||||
checkCache( full3Dpath, &cp );
|
||||
|
||||
for( unsigned int i = 0; i < numFilesFound; i++ )
|
||||
{
|
||||
// Completes path to specific file so we can get its "last access" date
|
||||
thisFile.SetFullName( fileList[i] );
|
||||
if( NULL != cp )
|
||||
return cp->GetCacheBaseName();
|
||||
|
||||
// Only get "last access" time to compare against. Don't need the other 2 timestamps.
|
||||
if( thisFile.GetTimes( &lastAccess, nullptr, nullptr ) )
|
||||
{
|
||||
if( lastAccess.IsEarlierThan( thresholdDate ) )
|
||||
{
|
||||
// This file is older than the threshold so delete it
|
||||
wxRemoveFile( thisFile.GetFullPath() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
S3D_CACHE* PROJECT::Get3DCacheManager( bool aUpdateProjDir )
|
||||
{
|
||||
std::lock_guard<std::mutex> lock( mutex3D_cacheManager );
|
||||
|
||||
// Get the existing cache from the project
|
||||
S3D_CACHE* cache = dynamic_cast<S3D_CACHE*>( GetElem( ELEM_3DCACHE ) );
|
||||
|
||||
if( !cache )
|
||||
{
|
||||
// Create a cache if there is not one already
|
||||
cache = new S3D_CACHE();
|
||||
|
||||
wxFileName cfgpath;
|
||||
cfgpath.AssignDir( SETTINGS_MANAGER::GetUserSettingsPath() );
|
||||
cfgpath.AppendDir( wxT( "3d" ) );
|
||||
|
||||
cache->SetProgramBase( &Pgm() );
|
||||
cache->Set3DConfigDir( cfgpath.GetFullPath() );
|
||||
|
||||
SetElem( ELEM_3DCACHE, cache );
|
||||
aUpdateProjDir = true;
|
||||
}
|
||||
|
||||
if( aUpdateProjDir )
|
||||
cache->SetProject( this );
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
|
||||
FILENAME_RESOLVER* PROJECT::Get3DFilenameResolver()
|
||||
{
|
||||
return Get3DCacheManager()->GetResolver();
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
+139
-117
@@ -2,7 +2,6 @@
|
||||
* 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) 2020 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
|
||||
@@ -24,136 +23,77 @@
|
||||
|
||||
/**
|
||||
* @file 3d_cache.h
|
||||
* defines the display data cache manager for 3D models
|
||||
*/
|
||||
|
||||
#ifndef CACHE_3D_H
|
||||
#define CACHE_3D_H
|
||||
|
||||
#include "3d_info.h"
|
||||
#include <core/typeinfo.h>
|
||||
#include "string_utils.h"
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include "plugins/3dapi/c3dmodel.h"
|
||||
#include <project.h>
|
||||
#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;
|
||||
|
||||
|
||||
/**
|
||||
* Cache for storing the 3D shapes. This cache is able to be stored as a project
|
||||
* element (since it inherits from PROJECT::_ELEM).
|
||||
*/
|
||||
class S3D_CACHE : public PROJECT::_ELEM
|
||||
class S3D_CACHE
|
||||
{
|
||||
public:
|
||||
S3D_CACHE();
|
||||
virtual ~S3D_CACHE();
|
||||
|
||||
KICAD_T Type() noexcept override
|
||||
{
|
||||
return S3D_CACHE_T;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 );
|
||||
|
||||
/**
|
||||
* Set the current project's working directory; this affects the model search path.
|
||||
*/
|
||||
bool SetProject( PROJECT* aProject );
|
||||
|
||||
/**
|
||||
* Set the filename resolver's pointer to the application's PGM_BASE instance.
|
||||
*
|
||||
* The pointer is used to extract the local environment variables.
|
||||
*/
|
||||
void SetProgramBase( PGM_BASE* aBase );
|
||||
|
||||
/**
|
||||
* Attempt 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. The model may fail to load if, for example,
|
||||
* the plugin does not support rendering of the 3D model.
|
||||
|
||||
*
|
||||
* @param aModelFile is the partial or full path to the model to be loaded.
|
||||
* @return true if the model was successfully loaded, otherwise false.
|
||||
*/
|
||||
SCENEGRAPH* Load( const wxString& aModelFile );
|
||||
|
||||
FILENAME_RESOLVER* GetResolver() noexcept;
|
||||
|
||||
/**
|
||||
* Return 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() const;
|
||||
|
||||
/**
|
||||
* Free all data in the cache and by default closes all plugins.
|
||||
*/
|
||||
void FlushCache( bool closePlugins = true );
|
||||
|
||||
/**
|
||||
* Unload plugins to free memory.
|
||||
*/
|
||||
void ClosePlugins();
|
||||
|
||||
/**
|
||||
* Attempt 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 );
|
||||
|
||||
/**
|
||||
* Delete up old cache files in cache directory.
|
||||
*
|
||||
* Deletes ".3dc" files in the cache directory that are older than \a aNumDaysOld.
|
||||
*
|
||||
* @param aNumDaysOld is age threshold to delete ".3dc" cache files.
|
||||
*/
|
||||
void CleanCacheDir( int aNumDaysOld );
|
||||
|
||||
private:
|
||||
/**
|
||||
* Find or create cache entry for file name
|
||||
/// 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.
|
||||
* 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 aFileName is the file name (full or partial path).
|
||||
* @param aCachePtr is an optional return address for cache entry pointer.
|
||||
* @return SCENEGRAPH object associated with file name or NULL on error.
|
||||
* @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 = nullptr );
|
||||
SCENEGRAPH* checkCache( const wxString& aFileName, S3D_CACHE_ENTRY** aCachePtr = NULL );
|
||||
|
||||
/**
|
||||
* Calculate the SHA1 hash of the given file.
|
||||
* Function getSHA1
|
||||
* calculates the SHA1 hash of the given file
|
||||
*
|
||||
* @param aFileName file name (full path).
|
||||
* @param aSHA1Sum a 20 byte character array to hold the SHA1 hash.
|
||||
* @return true on success, otherwise false.
|
||||
* @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 );
|
||||
|
||||
@@ -164,21 +104,103 @@ private:
|
||||
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 = nullptr );
|
||||
SCENEGRAPH* load( const wxString& aModelFile, S3D_CACHE_ENTRY** aCachePtr = NULL );
|
||||
|
||||
/// cache entries
|
||||
std::list< S3D_CACHE_ENTRY* > m_CacheList;
|
||||
public:
|
||||
S3D_CACHE();
|
||||
virtual ~S3D_CACHE();
|
||||
|
||||
/// mapping of file names to cache names and data
|
||||
std::map< wxString, S3D_CACHE_ENTRY*, rsort_wxString > m_CacheMap;
|
||||
/**
|
||||
* 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 );
|
||||
|
||||
FILENAME_RESOLVER* m_FNResolver;
|
||||
/**
|
||||
* 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 );
|
||||
|
||||
S3D_PLUGIN_MANAGER* m_Plugins;
|
||||
/**
|
||||
* Function SetProjectDir
|
||||
* sets the current project's working directory; this
|
||||
* affects the model search path
|
||||
*/
|
||||
bool SetProjectDir( const wxString& aProjDir );
|
||||
|
||||
PROJECT* m_project;
|
||||
wxString m_CacheDir;
|
||||
wxString m_ConfigDir; /// base configuration path for 3D items
|
||||
/**
|
||||
* 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
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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
|
||||
@@ -36,12 +36,12 @@
|
||||
#include <wx/string.h>
|
||||
#include <plugins/3dapi/sg_base.h>
|
||||
|
||||
class FP_3DMODEL;
|
||||
class MODULE_3D_SETTINGS;
|
||||
|
||||
struct S3D_INFO
|
||||
{
|
||||
S3D_INFO();
|
||||
S3D_INFO( const FP_3DMODEL& aModel );
|
||||
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
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* 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) 2020 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
|
||||
@@ -27,6 +26,7 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include <wx/config.h>
|
||||
#include <wx/dir.h>
|
||||
#include <wx/dynlib.h>
|
||||
#include <wx/filename.h>
|
||||
@@ -34,28 +34,21 @@
|
||||
#include <wx/stdpaths.h>
|
||||
#include <wx/string.h>
|
||||
|
||||
#include <common.h>
|
||||
#include <paths.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"
|
||||
|
||||
|
||||
/**
|
||||
* Flag to enable 3D plugin manager debug tracing.
|
||||
*
|
||||
* Use "KI_TRACE_EDA_3D_VIEWER" to enable.
|
||||
*
|
||||
* @ingroup trace_env_vars
|
||||
*/
|
||||
#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" ) + wxT( " (*.*)|*.*" ) );
|
||||
m_FileFilters.push_back( _( "All Files (*.*)|*.*" ) );
|
||||
|
||||
// discover and load plugins
|
||||
loadPlugins();
|
||||
@@ -65,19 +58,19 @@ S3D_PLUGIN_MANAGER::S3D_PLUGIN_MANAGER()
|
||||
{
|
||||
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, wxT( " * Extension [plugin name]:\n" ) );
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " * Extension [plugin name]:\n" );
|
||||
|
||||
while( sM != eM )
|
||||
{
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( " + '%s' [%s]\n" ), sM->first.GetData(),
|
||||
sM->second->GetKicadPluginName() );
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " + '%s' [%s]\n", sM->first.GetData(),
|
||||
sM->second->GetKicadPluginName() );
|
||||
++sM;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( " * No plugins available\n" ) );
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " * No plugins available\n" );
|
||||
}
|
||||
|
||||
|
||||
@@ -86,19 +79,21 @@ S3D_PLUGIN_MANAGER::S3D_PLUGIN_MANAGER()
|
||||
/// 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, wxT( " * File filters:\n" ) );
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " * File filters:\n" );
|
||||
|
||||
while( sFF != eFF )
|
||||
{
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( " + '%s'\n" ), (*sFF).GetData() );
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " + '%s'\n", (*sFF).GetData() );
|
||||
++sFF;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( " * No file filters available\n" ) );
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " * No file filters available\n" );
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -115,6 +110,7 @@ S3D_PLUGIN_MANAGER::~S3D_PLUGIN_MANAGER()
|
||||
}
|
||||
|
||||
m_Plugins.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -126,12 +122,12 @@ void S3D_PLUGIN_MANAGER::loadPlugins( void )
|
||||
|
||||
#ifndef __WXMAC__
|
||||
|
||||
#ifdef DEBUG
|
||||
#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" ) );
|
||||
fn.AppendDir( wxT("..") );
|
||||
fn.AppendDir( wxT("plugins") );
|
||||
fn.AppendDir( wxT("3d") );
|
||||
|
||||
std::string testpath = std::string( fn.GetPathWithSep().ToUTF8() );
|
||||
checkPluginPath( testpath, searchpaths );
|
||||
@@ -142,33 +138,59 @@ void S3D_PLUGIN_MANAGER::loadPlugins( void )
|
||||
|
||||
debugPluginDir.Open( testpath );
|
||||
|
||||
if( debugPluginDir.IsOpened() && debugPluginDir.GetFirst( &subdir, wxEmptyString, wxDIR_DIRS ) )
|
||||
if( debugPluginDir.IsOpened() &&
|
||||
debugPluginDir.GetFirst( &subdir, wxEmptyString, wxDIR_DIRS ) )
|
||||
{
|
||||
checkPluginPath( testpath + subdir, searchpaths );
|
||||
|
||||
while( debugPluginDir.GetNext( &subdir ) )
|
||||
checkPluginPath( testpath + subdir, searchpaths );
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
fn.AssignDir( PATHS::GetStockPlugins3DPath() );
|
||||
#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.AssignDir( PATHS::GetUserPlugins3DPath() );
|
||||
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( PATHS::GetOSXKicadUserDataDir() + wxT( "/PlugIns/3d" ), searchpaths );
|
||||
|
||||
checkPluginPath( GetOSXKicadUserDataDir() + wxT( "/PlugIns/3d" ), searchpaths );
|
||||
// (2) Machine /Library/Application Support/kicad/PlugIns/3d
|
||||
checkPluginPath( PATHS::GetOSXKicadMachineDataDir() + wxT( "/PlugIns/3d" ), searchpaths );
|
||||
|
||||
checkPluginPath( GetOSXKicadMachineDataDir() + wxT( "/PlugIns/3d" ), searchpaths );
|
||||
// (3) Bundle kicad.app/Contents/PlugIns/3d
|
||||
fn.AssignDir( PATHS::GetStockPlugins3DPath() );
|
||||
fn.Assign( Pgm().GetExecutablePath() );
|
||||
fn.AppendDir( wxT( "Contents" ) );
|
||||
fn.AppendDir( wxT( "PlugIns" ) );
|
||||
fn.AppendDir( wxT( "3d" ) );
|
||||
checkPluginPath( fn.GetPathWithSep(), searchpaths );
|
||||
|
||||
#endif
|
||||
@@ -178,9 +200,14 @@ void S3D_PLUGIN_MANAGER::loadPlugins( void )
|
||||
|
||||
while( sPL != ePL )
|
||||
{
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( "%s:%s:%d * [DEBUG] searching path: '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, (*sPL).ToUTF8() );
|
||||
|
||||
#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;
|
||||
}
|
||||
@@ -197,14 +224,25 @@ void S3D_PLUGIN_MANAGER::loadPlugins( void )
|
||||
|
||||
if( pp->Open( sPL->ToUTF8() ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( "%s:%s:%d * [DEBUG] adding plugin" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
#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();
|
||||
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( "%s:%s:%d * [DEBUG] adding %d filters" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, nf );
|
||||
#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 )
|
||||
{
|
||||
@@ -221,24 +259,39 @@ void S3D_PLUGIN_MANAGER::loadPlugins( void )
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( "%s:%s:%d * [DEBUG] deleting plugin" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( "%s:%s:%d * [DEBUG] plugins loaded" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#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 )
|
||||
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 footprints)
|
||||
|
||||
wxString nameFilter; // filter for user-loadable libraries (aka modules)
|
||||
wxString lName; // stores name of enumerated files
|
||||
wxString fName; // full name of file
|
||||
wxDir wd;
|
||||
@@ -275,18 +328,25 @@ void S3D_PLUGIN_MANAGER::listPlugins( const wxString& aPath, std::list< wxString
|
||||
}
|
||||
|
||||
wd.Close();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D_PLUGIN_MANAGER::checkPluginName( const wxString& aPath,
|
||||
std::list< wxString >& aPluginList )
|
||||
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( ExpandEnvVarSubstitutions( aPath, nullptr ) );
|
||||
wxFileName path;
|
||||
|
||||
if( aPath.StartsWith( "${" ) || aPath.StartsWith( "$(" ) )
|
||||
path.Assign( ExpandEnvVarSubstitutions( aPath ) );
|
||||
else
|
||||
path.Assign( aPath );
|
||||
|
||||
path.Normalize();
|
||||
|
||||
@@ -305,26 +365,33 @@ void S3D_PLUGIN_MANAGER::checkPluginName( const wxString& aPath,
|
||||
|
||||
aPluginList.push_back( wxpath );
|
||||
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( " * [INFO] found 3D plugin '%s'\n" ), wxpath.GetData() );
|
||||
#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 )
|
||||
std::list< wxString >& aSearchList )
|
||||
{
|
||||
// check the existence of a path and add it to the path search list
|
||||
if( aPath.empty() )
|
||||
return;
|
||||
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( " * [INFO] checking for 3D plugins in '%s'\n" ),
|
||||
aPath.GetData() );
|
||||
#ifdef DEBUG
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " * [INFO] checking for 3D plugins in '%s'\n",
|
||||
aPath.GetData() );
|
||||
#endif
|
||||
|
||||
wxFileName path;
|
||||
|
||||
if( aPath.StartsWith( wxT( "${" ) ) || aPath.StartsWith( wxT( "$(" ) ) )
|
||||
path.Assign( ExpandEnvVarSubstitutions( aPath, nullptr ), wxEmptyString );
|
||||
if( aPath.StartsWith( "${" ) || aPath.StartsWith( "$(" ) )
|
||||
path.Assign( ExpandEnvVarSubstitutions( aPath ), "" );
|
||||
else
|
||||
path.Assign( aPath, wxEmptyString );
|
||||
path.Assign( aPath, "" );
|
||||
|
||||
path.Normalize();
|
||||
|
||||
@@ -345,6 +412,8 @@ void S3D_PLUGIN_MANAGER::checkPluginPath( const wxString& aPath,
|
||||
}
|
||||
|
||||
aSearchList.push_back( wxpath );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -373,13 +442,19 @@ void S3D_PLUGIN_MANAGER::addFilterString( const wxString& aFilterString )
|
||||
void S3D_PLUGIN_MANAGER::addExtensionMap( KICAD_PLUGIN_LDR_3D* aPlugin )
|
||||
{
|
||||
// add entries to the extension map
|
||||
if( nullptr == aPlugin )
|
||||
if( NULL == aPlugin )
|
||||
return;
|
||||
|
||||
int nExt = aPlugin->GetNExtensions();
|
||||
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( "%s:%s:%d * [INFO] adding %d extensions" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, nExt );
|
||||
#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 )
|
||||
{
|
||||
@@ -395,10 +470,12 @@ void S3D_PLUGIN_MANAGER::addExtensionMap( KICAD_PLUGIN_LDR_3D* aPlugin )
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
std::list< wxString > const* S3D_PLUGIN_MANAGER::GetFileFilters( void ) const noexcept
|
||||
std::list< wxString > const* S3D_PLUGIN_MANAGER::GetFileFilters( void ) const
|
||||
{
|
||||
return &m_FileFilters;
|
||||
}
|
||||
@@ -407,25 +484,18 @@ std::list< wxString > const* S3D_PLUGIN_MANAGER::GetFileFilters( void ) const no
|
||||
SCENEGRAPH* S3D_PLUGIN_MANAGER::Load3DModel( const wxString& aFileName, std::string& aPluginInfo )
|
||||
{
|
||||
wxFileName raw( aFileName );
|
||||
wxString ext_to_find = raw.GetExt();
|
||||
wxString ext = raw.GetExt();
|
||||
|
||||
#ifdef _WIN32
|
||||
#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_to_find.MakeLower();
|
||||
#endif
|
||||
|
||||
// .gz files are compressed versions that may have additional information in the previous extension
|
||||
if( ext_to_find == wxT( "gz" ) )
|
||||
{
|
||||
wxFileName second( raw.GetName() );
|
||||
ext_to_find = second.GetExt() + wxT( ".gz" );
|
||||
}
|
||||
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_to_find );
|
||||
items = m_ExtMap.equal_range( ext );
|
||||
std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* >::iterator sL = items.first;
|
||||
|
||||
while( sL != items.second )
|
||||
@@ -434,7 +504,7 @@ SCENEGRAPH* S3D_PLUGIN_MANAGER::Load3DModel( const wxString& aFileName, std::str
|
||||
{
|
||||
SCENEGRAPH* sp = sL->second->Load( aFileName.ToUTF8() );
|
||||
|
||||
if( nullptr != sp )
|
||||
if( NULL != sp )
|
||||
{
|
||||
sL->second->GetPluginInfo( aPluginInfo );
|
||||
return sp;
|
||||
@@ -444,7 +514,7 @@ SCENEGRAPH* S3D_PLUGIN_MANAGER::Load3DModel( const wxString& aFileName, std::str
|
||||
++sL;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -453,20 +523,28 @@ 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();
|
||||
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( "%s:%s:%d * [INFO] closing %d extensions" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, static_cast<int>( m_Plugins.size() ) );
|
||||
#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( nullptr == aTag || aTag[0] == 0 || m_Plugins.empty() )
|
||||
if( NULL == aTag || aTag[0] == 0 || m_Plugins.empty() )
|
||||
return false;
|
||||
|
||||
std::string tname = aTag;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* 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) 2020 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
|
||||
@@ -41,35 +40,16 @@ class SCENEGRAPH;
|
||||
|
||||
class S3D_PLUGIN_MANAGER
|
||||
{
|
||||
public:
|
||||
S3D_PLUGIN_MANAGER();
|
||||
virtual ~S3D_PLUGIN_MANAGER();
|
||||
|
||||
/**
|
||||
* Return 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 noexcept;
|
||||
|
||||
SCENEGRAPH* Load3DModel( const wxString& aFileName, std::string& aPluginInfo );
|
||||
|
||||
/**
|
||||
* Iterate 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 );
|
||||
|
||||
/**
|
||||
* Check 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 );
|
||||
|
||||
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 );
|
||||
|
||||
@@ -88,14 +68,36 @@ private:
|
||||
/// add entries to the extension map
|
||||
void addExtensionMap( KICAD_PLUGIN_LDR_3D* aPlugin );
|
||||
|
||||
/// list of discovered plugins
|
||||
std::list< KICAD_PLUGIN_LDR_3D* > m_Plugins;
|
||||
public:
|
||||
S3D_PLUGIN_MANAGER();
|
||||
virtual ~S3D_PLUGIN_MANAGER();
|
||||
|
||||
/// mapping of extensions to available plugins
|
||||
std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* > m_ExtMap;
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/// list of file filters
|
||||
std::list< wxString > m_FileFilters;
|
||||
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
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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 );
|
||||
}
|
||||
+2
-2
@@ -31,8 +31,8 @@ class FILENAME_RESOLVER;
|
||||
|
||||
namespace S3D
|
||||
{
|
||||
bool Select3DModel( wxWindow* aParent, S3D_CACHE* aCache, wxString& prevModelSelectDir,
|
||||
int& prevModelWildcard, FP_3DMODEL* aModel );
|
||||
bool Select3DModel( wxWindow* aParent, S3D_CACHE* aCache,
|
||||
wxString& prevModelSelectDir, int& prevModelWildcard, MODULE_3D_SETTINGS* aModel );
|
||||
|
||||
bool Configure3DPaths( wxWindow* aParent, FILENAME_RESOLVER* aResolver );
|
||||
}
|
||||
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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
|
||||
@@ -0,0 +1,310 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 3.9.0 Nov 1 2020)
|
||||
// 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, const wxString& name ) : wxPanel( parent, id, pos, size, style, name )
|
||||
{
|
||||
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, wxALL, 5 );
|
||||
|
||||
m_SizerPanelView = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
|
||||
bSizerRight->Add( m_SizerPanelView, 1, wxEXPAND|wxBOTTOM, 5 );
|
||||
|
||||
|
||||
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( -1,-1 ), wxBU_AUTODRAW|0 );
|
||||
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( -1,-1 ), wxBU_AUTODRAW|0 );
|
||||
bSizer3DButtons->Add( m_bpvLeft, 0, 0, 5 );
|
||||
|
||||
m_bpvRight = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 );
|
||||
bSizer3DButtons->Add( m_bpvRight, 0, wxTOP, 5 );
|
||||
|
||||
m_bpvFront = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 );
|
||||
bSizer3DButtons->Add( m_bpvFront, 0, wxTOP, 5 );
|
||||
|
||||
m_bpvBack = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 );
|
||||
bSizer3DButtons->Add( m_bpvBack, 0, wxTOP, 5 );
|
||||
|
||||
m_bpvTop = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 );
|
||||
bSizer3DButtons->Add( m_bpvTop, 0, wxTOP, 5 );
|
||||
|
||||
m_bpvBottom = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 );
|
||||
bSizer3DButtons->Add( m_bpvBottom, 0, wxTOP, 5 );
|
||||
|
||||
m_bpUpdate = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 );
|
||||
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
@@ -0,0 +1,105 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 3.9.0 Nov 1 2020)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#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/bmpbuttn.h>
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/icon.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, const wxString& name = wxEmptyString );
|
||||
~PANEL_PREV_3D_BASE();
|
||||
|
||||
};
|
||||
|
||||
@@ -0,0 +1,404 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* 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
|
||||
@@ -104,8 +104,3 @@ install( TARGETS
|
||||
LIBRARY DESTINATION ${KICAD_LIB}
|
||||
COMPONENT binary
|
||||
)
|
||||
|
||||
if( KICAD_WIN32_INSTALL_PDBS )
|
||||
# Get the PDBs to copy over for MSVC
|
||||
install(FILES $<TARGET_PDB_FILE:kicad_3dsg> DESTINATION ${KICAD_BIN})
|
||||
endif()
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2020 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
|
||||
@@ -25,7 +24,6 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <wx/filename.h>
|
||||
#include <wx/log.h>
|
||||
#include "plugins/3dapi/ifsg_api.h"
|
||||
@@ -38,6 +36,10 @@
|
||||
#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"
|
||||
|
||||
@@ -71,13 +73,15 @@ static void formatMaterial( SMATERIAL& mat, SGAPPEARANCE const* app )
|
||||
|
||||
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 )
|
||||
bool reuse, bool renameNodes )
|
||||
{
|
||||
if( nullptr == filename || filename[0] == 0 )
|
||||
if( NULL == filename || filename[0] == 0 )
|
||||
return false;
|
||||
|
||||
wxString ofile = wxString::FromUTF8Unchecked( filename );
|
||||
@@ -92,19 +96,46 @@ bool S3D::WriteVRML( const char* filename, bool overwrite, SGNODE* aTopNode,
|
||||
return false;
|
||||
}
|
||||
|
||||
wxCHECK( aTopNode && aTopNode->GetNodeType() == S3D::SGTYPE_TRANSFORM, 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() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] failed to open file '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, filename );
|
||||
|
||||
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::classic() );
|
||||
op.imbue( std::locale( "C" ) );
|
||||
op << "#VRML V2.0 utf8\n";
|
||||
|
||||
if( renameNodes )
|
||||
@@ -123,8 +154,10 @@ bool S3D::WriteVRML( const char* filename, bool overwrite, SGNODE* aTopNode,
|
||||
|
||||
CLOSE_STREAM( op );
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] problems encountered writing file '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, filename );
|
||||
wxString errmsg;
|
||||
errmsg << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
errmsg << " * [INFO] " << "problems encountered writing file" << " '" << filename << "'";
|
||||
wxLogTrace( MASK_3D_SG, errmsg );
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -132,44 +165,102 @@ bool S3D::WriteVRML( const char* filename, bool overwrite, SGNODE* aTopNode,
|
||||
|
||||
void S3D::ResetNodeIndex( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK( aNode, /* void */ );
|
||||
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 )
|
||||
{
|
||||
wxCHECK( aNode, /* void */ );
|
||||
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 ) noexcept
|
||||
void S3D::DestroyNode( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK( aNode, /* void */ );
|
||||
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 )
|
||||
const char* aPluginInfo )
|
||||
{
|
||||
if( nullptr == aFileName || aFileName[0] == 0 )
|
||||
if( NULL == aFileName || aFileName[0] == 0 )
|
||||
return false;
|
||||
|
||||
wxString ofile = wxString::FromUTF8Unchecked( aFileName );
|
||||
|
||||
wxCHECK( aNode, false );
|
||||
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 )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] file exists not overwriting '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aFileName );
|
||||
wxString errmsg;
|
||||
errmsg << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
errmsg << " * [INFO] " << "file exists; not overwriting" << " '";
|
||||
errmsg << aFileName << "'";
|
||||
wxLogTrace( MASK_3D_SG, errmsg );
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -177,9 +268,11 @@ bool S3D::WriteCache( const char* aFileName, bool overwrite, SGNODE* aNode,
|
||||
// make sure we make no attempt to write a directory
|
||||
if( !wxFileName::FileExists( aFileName ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] specified path is a directory '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aFileName );
|
||||
|
||||
wxString errmsg;
|
||||
errmsg << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
errmsg << " * [INFO] " << "specified path is a directory" << " '";
|
||||
errmsg << aFileName << "'";
|
||||
wxLogTrace( MASK_3D_SG, errmsg );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -188,27 +281,34 @@ bool S3D::WriteCache( const char* aFileName, bool overwrite, SGNODE* aNode,
|
||||
|
||||
if( output.fail() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] failed to open file '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aFileName );
|
||||
|
||||
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( nullptr != aPluginInfo && aPluginInfo[0] != 0 )
|
||||
if( NULL != aPluginInfo && aPluginInfo[0] != 0 )
|
||||
output << "(" << aPluginInfo << ")";
|
||||
else
|
||||
output << "(INTERNAL:0.0.0.0)";
|
||||
|
||||
bool rval = aNode->WriteCache( output, nullptr );
|
||||
bool rval = aNode->WriteCache( output, NULL );
|
||||
CLOSE_STREAM( output );
|
||||
|
||||
if( !rval )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [INFO] problems encountered writing cache file '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aFileName );
|
||||
#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 );
|
||||
@@ -219,31 +319,53 @@ bool S3D::WriteCache( const char* aFileName, bool overwrite, SGNODE* aNode,
|
||||
|
||||
|
||||
SGNODE* S3D::ReadCache( const char* aFileName, void* aPluginMgr,
|
||||
bool (*aTagCheck)( const char*, void* ) )
|
||||
bool (*aTagCheck)( const char*, void* ) )
|
||||
{
|
||||
if( nullptr == aFileName || aFileName[0] == 0 )
|
||||
return nullptr;
|
||||
if( NULL == aFileName || aFileName[0] == 0 )
|
||||
return NULL;
|
||||
|
||||
wxString ofile = wxString::FromUTF8Unchecked( aFileName );
|
||||
|
||||
if( !wxFileName::FileExists( aFileName ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] no such file '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, 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 nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
std::unique_ptr<SGNODE> np = std::make_unique<SCENEGRAPH>( nullptr );
|
||||
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() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] failed to open file '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aFileName );
|
||||
|
||||
return nullptr;
|
||||
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
|
||||
@@ -256,13 +378,18 @@ SGNODE* S3D::ReadCache( const char* aFileName, void* aPluginMgr,
|
||||
|
||||
if( '(' != schar )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; missing left parenthesis"
|
||||
" at position '%d'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<int>( file.tellg() ) );
|
||||
#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 nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
file.get( schar );
|
||||
@@ -276,7 +403,7 @@ SGNODE* S3D::ReadCache( const char* aFileName, void* aPluginMgr,
|
||||
if( name.compare( SG_VERSION_TAG ) )
|
||||
{
|
||||
CLOSE_STREAM( file );
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
@@ -291,13 +418,18 @@ SGNODE* S3D::ReadCache( const char* aFileName, void* aPluginMgr,
|
||||
|
||||
if( '(' != schar )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; missing left parenthesis"
|
||||
" at position '%d'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<int>( file.tellg() ) );
|
||||
#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 nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
file.get( schar );
|
||||
@@ -309,39 +441,40 @@ SGNODE* S3D::ReadCache( const char* aFileName, void* aPluginMgr,
|
||||
}
|
||||
|
||||
// check the plugin tag
|
||||
if( nullptr != aTagCheck && nullptr != aPluginMgr
|
||||
&& !aTagCheck( name.c_str(), aPluginMgr ) )
|
||||
if( NULL != aTagCheck && NULL != aPluginMgr && !aTagCheck( name.c_str(), aPluginMgr ) )
|
||||
{
|
||||
CLOSE_STREAM( file );
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
|
||||
bool rval = np->ReadCache( file, nullptr );
|
||||
bool rval = np->ReadCache( file, NULL );
|
||||
CLOSE_STREAM( file );
|
||||
|
||||
if( !rval )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] problems encountered reading cache file "
|
||||
"'%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aFileName );
|
||||
|
||||
return nullptr;
|
||||
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.release();
|
||||
return np;
|
||||
}
|
||||
|
||||
|
||||
S3DMODEL* S3D::GetModel( SCENEGRAPH* aNode )
|
||||
{
|
||||
if( nullptr == aNode )
|
||||
return nullptr;
|
||||
if( NULL == aNode )
|
||||
return NULL;
|
||||
|
||||
if( aNode->GetNodeType() != S3D::SGTYPE_TRANSFORM )
|
||||
return nullptr;
|
||||
return NULL;
|
||||
|
||||
S3D::MATLIST materials;
|
||||
std::vector< SMESH > meshes;
|
||||
@@ -351,20 +484,20 @@ S3DMODEL* S3D::GetModel( SCENEGRAPH* aNode )
|
||||
// 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( nullptr );
|
||||
app.ambient = SGCOLOR( 0.6f, 0.6f, 0.6f );
|
||||
app.diffuse = SGCOLOR( 0.6f, 0.6f, 0.6f );
|
||||
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.05f;
|
||||
app.transparency = 0.0f;
|
||||
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( nullptr, materials, meshes ) )
|
||||
if( aNode->Prepare( NULL, materials, meshes ) )
|
||||
{
|
||||
if( meshes.empty() )
|
||||
return nullptr;
|
||||
return NULL;
|
||||
|
||||
S3DMODEL* model = S3D::New3DModel();
|
||||
|
||||
@@ -396,31 +529,35 @@ S3DMODEL* S3D::GetModel( SCENEGRAPH* aNode )
|
||||
for( size_t i = 0; i < j; ++i )
|
||||
S3D::Free3DMesh( meshes[i] );
|
||||
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void S3D::Destroy3DModel( S3DMODEL** aModel )
|
||||
{
|
||||
if( nullptr == aModel || nullptr == *aModel )
|
||||
if( NULL == aModel || NULL == *aModel )
|
||||
return;
|
||||
|
||||
S3DMODEL* m = *aModel;
|
||||
S3D::FREE_S3DMODEL( *m );
|
||||
delete m;
|
||||
*aModel = nullptr;
|
||||
*aModel = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void Free3DModel( S3DMODEL& aModel )
|
||||
{
|
||||
S3D::FREE_S3DMODEL( aModel );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D::Free3DMesh( SMESH& aMesh )
|
||||
{
|
||||
S3D::FREE_SMESH( aMesh );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -435,17 +572,20 @@ S3DMODEL* S3D::New3DModel( void )
|
||||
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 ) noexcept
|
||||
void S3D::GetLibVersion( unsigned char* Major, unsigned char* Minor,
|
||||
unsigned char* Patch, unsigned char* Revision )
|
||||
{
|
||||
if( Major )
|
||||
*Major = KICADSG_VERSION_MAJOR;
|
||||
@@ -458,6 +598,8 @@ void S3D::GetLibVersion( unsigned char* Major, unsigned char* Minor, unsigned ch
|
||||
|
||||
if( Patch )
|
||||
*Patch = KICADSG_VERSION_PATCH;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -484,7 +626,7 @@ SGVECTOR S3D::CalcTriNorm( const SGPOINT& p1, const SGPOINT& p2, const SGPOINT&
|
||||
|
||||
S3D::SGTYPES S3D::GetSGNodeType( SGNODE* aNode )
|
||||
{
|
||||
if( nullptr == aNode )
|
||||
if( NULL == aNode )
|
||||
return SGTYPE_END;
|
||||
|
||||
return aNode->GetNodeType();
|
||||
@@ -493,8 +635,8 @@ S3D::SGTYPES S3D::GetSGNodeType( SGNODE* aNode )
|
||||
|
||||
SGNODE* S3D::GetSGNodeParent( SGNODE* aNode )
|
||||
{
|
||||
if( nullptr == aNode )
|
||||
return nullptr;
|
||||
if( NULL == aNode )
|
||||
return NULL;
|
||||
|
||||
return aNode->GetParent();
|
||||
}
|
||||
@@ -502,7 +644,7 @@ SGNODE* S3D::GetSGNodeParent( SGNODE* aNode )
|
||||
|
||||
bool S3D::AddSGNodeRef( SGNODE* aParent, SGNODE* aChild )
|
||||
{
|
||||
if( nullptr == aParent || nullptr == aChild )
|
||||
if( NULL == aParent || NULL == aChild )
|
||||
return false;
|
||||
|
||||
return aParent->AddRefNode( aChild );
|
||||
@@ -511,7 +653,7 @@ bool S3D::AddSGNodeRef( SGNODE* aParent, SGNODE* aChild )
|
||||
|
||||
bool S3D::AddSGNodeChild( SGNODE* aParent, SGNODE* aChild )
|
||||
{
|
||||
if( nullptr == aParent || nullptr == aChild )
|
||||
if( NULL == aParent || NULL == aChild )
|
||||
return false;
|
||||
|
||||
return aParent->AddChildNode( aChild );
|
||||
@@ -520,8 +662,10 @@ bool S3D::AddSGNodeChild( SGNODE* aParent, SGNODE* aChild )
|
||||
|
||||
void S3D::AssociateSGNodeWrapper( SGNODE* aObject, SGNODE** aRefPtr )
|
||||
{
|
||||
if( nullptr == aObject || nullptr == aRefPtr || aObject != *aRefPtr )
|
||||
if( NULL == aObject || NULL == aRefPtr || aObject != *aRefPtr )
|
||||
return;
|
||||
|
||||
aObject->AssociateWrapper( aRefPtr );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* 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) 2020 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
|
||||
@@ -30,39 +29,55 @@
|
||||
#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 = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return ;
|
||||
|
||||
m_node = new SGAPPEARANCE( nullptr );
|
||||
m_node = new SGAPPEARANCE( NULL );
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_APPEARANCE::IFSG_APPEARANCE( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGAPPEARANCE( nullptr );
|
||||
m_node = new SGAPPEARANCE( NULL );
|
||||
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#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;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -70,28 +85,39 @@ IFSG_APPEARANCE::IFSG_APPEARANCE( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* pp = aParent.GetRawPtr();
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef DEBUG
|
||||
if( ! pp )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
BadParent );
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
m_node = new SGAPPEARANCE( nullptr );
|
||||
m_node = new SGAPPEARANCE( NULL );
|
||||
|
||||
if( !m_node->SetParent( pp ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -100,7 +126,7 @@ bool IFSG_APPEARANCE::Attach( SGNODE* aNode )
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
@@ -126,13 +152,17 @@ bool IFSG_APPEARANCE::NewNode( SGNODE* aParent )
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [BUG] invalid SGNODE parent (%s) to SGAPPEARANCE" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeTypeName( aParent->GetNodeType() ) );
|
||||
#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 = nullptr;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -146,7 +176,17 @@ bool IFSG_APPEARANCE::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
wxCHECK( np, false );
|
||||
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 );
|
||||
}
|
||||
@@ -154,131 +194,279 @@ bool IFSG_APPEARANCE::NewNode( IFSG_NODE& aParent )
|
||||
|
||||
bool IFSG_APPEARANCE::SetEmissive( float aRVal, float aGVal, float aBVal )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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 ( (SGAPPEARANCE*) m_node )->SetEmissive( aRVal, aGVal, aBVal );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetEmissive( aRVal, aGVal, aBVal );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetEmissive( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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 ( (SGAPPEARANCE*) m_node )->SetEmissive( aRGBColor );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetEmissive( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetEmissive( const SGCOLOR& aRGBColor )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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 ( (SGAPPEARANCE*) m_node )->SetEmissive( aRGBColor );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetEmissive( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetDiffuse( float aRVal, float aGVal, float aBVal )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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 ( (SGAPPEARANCE*) m_node )->SetDiffuse( aRVal, aGVal, aBVal );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetDiffuse( aRVal, aGVal, aBVal );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetDiffuse( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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 ( (SGAPPEARANCE*) m_node )->SetDiffuse( aRGBColor );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetDiffuse( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetDiffuse( const SGCOLOR& aRGBColor )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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 ( (SGAPPEARANCE*) m_node )->SetDiffuse( aRGBColor );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetDiffuse( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetSpecular( float aRVal, float aGVal, float aBVal )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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 ( (SGAPPEARANCE*) m_node )->SetSpecular( aRVal, aGVal, aBVal );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetSpecular( aRVal, aGVal, aBVal );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetSpecular( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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 ( (SGAPPEARANCE*) m_node )->SetSpecular( aRGBColor );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetSpecular( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetSpecular( const SGCOLOR& aRGBColor )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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 ( (SGAPPEARANCE*) m_node )->SetSpecular( aRGBColor );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetSpecular( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetAmbient( float aRVal, float aGVal, float aBVal )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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 ( (SGAPPEARANCE*) m_node )->SetAmbient( aRVal, aGVal, aBVal );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetAmbient( aRVal, aGVal, aBVal );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetAmbient( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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 ( (SGAPPEARANCE*) m_node )->SetAmbient( aRGBColor );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetAmbient( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetAmbient( const SGCOLOR& aRGBColor )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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 ( (SGAPPEARANCE*) m_node )->SetAmbient( aRGBColor );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetAmbient( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetShininess( float aShininess ) noexcept
|
||||
bool IFSG_APPEARANCE::SetShininess( float aShininess )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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 )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] shininess out of range [0..1]" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#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;
|
||||
((SGAPPEARANCE*)m_node)->shininess = aShininess;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetTransparency( float aTransparency ) noexcept
|
||||
bool IFSG_APPEARANCE::SetTransparency( float aTransparency )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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 )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] transparency out of range [0..1]" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#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;
|
||||
((SGAPPEARANCE*)m_node)->transparency = aTransparency;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* 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) 2020 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
|
||||
@@ -30,38 +29,52 @@
|
||||
#include "3d_cache/sg/sg_colors.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_COLORS::IFSG_COLORS( bool create )
|
||||
{
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return;
|
||||
return ;
|
||||
|
||||
m_node = new SGCOLORS( nullptr );
|
||||
m_node = new SGCOLORS( NULL );
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_COLORS::IFSG_COLORS( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGCOLORS( nullptr );
|
||||
m_node = new SGCOLORS( NULL );
|
||||
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d" ), __FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -69,29 +82,39 @@ IFSG_COLORS::IFSG_COLORS( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* pp = aParent.GetRawPtr();
|
||||
|
||||
#ifdef DEBUG
|
||||
// Braces needed due to dangling else warning from wxLogTrace macro
|
||||
if( !pp )
|
||||
#ifdef DEBUG
|
||||
if( ! pp )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
BadParent );
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
m_node = new SGCOLORS( nullptr );
|
||||
m_node = new SGCOLORS( NULL );
|
||||
|
||||
if( !m_node->SetParent( pp ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -100,7 +123,7 @@ bool IFSG_COLORS::Attach( SGNODE* aNode )
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
@@ -126,12 +149,17 @@ bool IFSG_COLORS::NewNode( SGNODE* aParent )
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] invalid SGNODE parent (%s) to SGCOLORS" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeTypeName( aParent->GetNodeType() ) );
|
||||
#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 = nullptr;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -145,7 +173,17 @@ bool IFSG_COLORS::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
wxCHECK( np, false );
|
||||
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 );
|
||||
}
|
||||
@@ -153,17 +191,37 @@ bool IFSG_COLORS::NewNode( IFSG_NODE& aParent )
|
||||
|
||||
bool IFSG_COLORS::GetColorList( size_t& aListSize, SGCOLOR*& aColorList )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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 ( (SGCOLORS*) m_node )->GetColorList( aListSize, aColorList );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGCOLORS*)m_node)->GetColorList( aListSize, aColorList );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COLORS::SetColorList( size_t aListSize, const SGCOLOR* aColorList )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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
|
||||
|
||||
( (SGCOLORS*) m_node )->SetColorList( aListSize, aColorList );
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGCOLORS*)m_node)->SetColorList( aListSize, aColorList );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -171,9 +229,19 @@ bool IFSG_COLORS::SetColorList( size_t aListSize, const SGCOLOR* aColorList )
|
||||
|
||||
bool IFSG_COLORS::AddColor( double aRedValue, double aGreenValue, double aBlueValue )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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
|
||||
|
||||
( (SGCOLORS*) m_node )->AddColor( aRedValue, aGreenValue, aBlueValue );
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGCOLORS*)m_node)->AddColor( aRedValue, aGreenValue, aBlueValue );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -181,9 +249,19 @@ bool IFSG_COLORS::AddColor( double aRedValue, double aGreenValue, double aBlueVa
|
||||
|
||||
bool IFSG_COLORS::AddColor( const SGCOLOR& aColor )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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
|
||||
|
||||
( (SGCOLORS*) m_node )->AddColor( aColor );
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGCOLORS*)m_node)->AddColor( aColor );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* 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) 2020 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
|
||||
@@ -31,39 +30,50 @@
|
||||
#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 = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return;
|
||||
|
||||
m_node = new SGCOORDINDEX( nullptr );
|
||||
m_node = new SGCOORDINDEX( NULL );
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_COORDINDEX::IFSG_COORDINDEX( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGCOORDINDEX( nullptr );
|
||||
m_node = new SGCOORDINDEX( NULL );
|
||||
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
@@ -73,25 +83,35 @@ IFSG_COORDINDEX::IFSG_COORDINDEX( IFSG_NODE& aParent )
|
||||
|
||||
if( !pp )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
BadParent );
|
||||
#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( nullptr );
|
||||
m_node = new SGCOORDINDEX( NULL );
|
||||
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#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 = nullptr;
|
||||
m_node = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -100,7 +120,7 @@ bool IFSG_COORDINDEX::Attach( SGNODE* aNode )
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
@@ -126,13 +146,17 @@ bool IFSG_COORDINDEX::NewNode( SGNODE* aParent )
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [BUG] invalid SGNODE parent (%s) to SGCOORDINDEX" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeTypeName( aParent->GetNodeType() ) );
|
||||
#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 = nullptr;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -146,7 +170,17 @@ bool IFSG_COORDINDEX::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
wxCHECK( np, false );
|
||||
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 );
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* 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) 2020 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
|
||||
@@ -30,39 +29,52 @@
|
||||
#include "3d_cache/sg/sg_coords.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_COORDS::IFSG_COORDS( bool create )
|
||||
{
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return ;
|
||||
|
||||
m_node = new SGCOORDS( nullptr );
|
||||
m_node = new SGCOORDS( NULL );
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_COORDS::IFSG_COORDS( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGCOORDS( nullptr );
|
||||
m_node = new SGCOORDS( NULL );
|
||||
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -70,28 +82,39 @@ IFSG_COORDS::IFSG_COORDS( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* pp = aParent.GetRawPtr();
|
||||
|
||||
#ifdef DEBUG
|
||||
if( !pp )
|
||||
#ifdef DEBUG
|
||||
if( ! pp )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
BadParent );
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
m_node = new SGCOORDS( nullptr );
|
||||
m_node = new SGCOORDS( NULL );
|
||||
|
||||
if( !m_node->SetParent( pp ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -100,7 +123,7 @@ bool IFSG_COORDS::Attach( SGNODE* aNode )
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
@@ -126,12 +149,17 @@ bool IFSG_COORDS::NewNode( SGNODE* aParent )
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] invalid SGNODE parent (%s) to SGCOORDS" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeTypeName( aParent->GetNodeType() ) );
|
||||
#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 = nullptr;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -145,7 +173,17 @@ bool IFSG_COORDS::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
wxCHECK( np, false );
|
||||
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 );
|
||||
}
|
||||
@@ -153,17 +191,37 @@ bool IFSG_COORDS::NewNode( IFSG_NODE& aParent )
|
||||
|
||||
bool IFSG_COORDS::GetCoordsList( size_t& aListSize, SGPOINT*& aCoordsList )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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 ( (SGCOORDS*) m_node )->GetCoordsList( aListSize, aCoordsList );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGCOORDS*)m_node)->GetCoordsList( aListSize, aCoordsList );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COORDS::SetCoordsList( size_t aListSize, const SGPOINT* aCoordsList )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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
|
||||
|
||||
( (SGCOORDS*) m_node )->SetCoordsList( aListSize, aCoordsList );
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGCOORDS*)m_node)->SetCoordsList( aListSize, aCoordsList );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -171,9 +229,19 @@ bool IFSG_COORDS::SetCoordsList( size_t aListSize, const SGPOINT* aCoordsList )
|
||||
|
||||
bool IFSG_COORDS::AddCoord( double aXValue, double aYValue, double aZValue )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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
|
||||
|
||||
( (SGCOORDS*) m_node )->AddCoord( aXValue, aYValue, aZValue );
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGCOORDS*)m_node)->AddCoord( aXValue, aYValue, aZValue );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -181,9 +249,19 @@ bool IFSG_COORDS::AddCoord( double aXValue, double aYValue, double aZValue )
|
||||
|
||||
bool IFSG_COORDS::AddCoord( const SGPOINT& aPoint )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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
|
||||
|
||||
( (SGCOORDS*) m_node )->AddCoord( aPoint );
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGCOORDS*)m_node)->AddCoord( aPoint );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* 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) 2020 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
|
||||
@@ -31,39 +30,52 @@
|
||||
#include "3d_cache/sg/sg_faceset.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_FACESET::IFSG_FACESET( bool create )
|
||||
{
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return ;
|
||||
|
||||
m_node = new SGFACESET( nullptr );
|
||||
m_node = new SGFACESET( NULL );
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_FACESET::IFSG_FACESET( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGFACESET( nullptr );
|
||||
m_node = new SGFACESET( NULL );
|
||||
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,28 +83,39 @@ IFSG_FACESET::IFSG_FACESET( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* pp = aParent.GetRawPtr();
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef DEBUG
|
||||
if( ! pp )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
BadParent );
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
m_node = new SGFACESET( nullptr );
|
||||
m_node = new SGFACESET( NULL );
|
||||
|
||||
if( !m_node->SetParent( pp ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +124,7 @@ bool IFSG_FACESET::Attach( SGNODE* aNode )
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
@@ -127,12 +150,17 @@ bool IFSG_FACESET::NewNode( SGNODE* aParent )
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] invalid SGNODE parent (%s) to SGFACESET" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeTypeName( aParent->GetNodeType() ) );
|
||||
#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 = nullptr;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -146,7 +174,17 @@ bool IFSG_FACESET::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
wxCHECK( np, false );
|
||||
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 );
|
||||
}
|
||||
@@ -155,7 +193,7 @@ bool IFSG_FACESET::NewNode( IFSG_NODE& aParent )
|
||||
bool IFSG_FACESET::CalcNormals( SGNODE** aPtr )
|
||||
{
|
||||
if( m_node )
|
||||
return ( (SGFACESET*) m_node )->CalcNormals( aPtr );
|
||||
return ((SGFACESET*)m_node)->CalcNormals( aPtr );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* 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) 2020 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
|
||||
@@ -31,24 +30,51 @@
|
||||
#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 )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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 ( (SGINDEX*) m_node )->GetIndices( nIndices, aIndexList );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGINDEX*)m_node)->GetIndices( nIndices, aIndexList );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_INDEX::SetIndices( size_t nIndices, int* aIndexList )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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
|
||||
|
||||
( (SGINDEX*) m_node )->SetIndices( nIndices, aIndexList );
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGINDEX*)m_node)->SetIndices( nIndices, aIndexList );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -56,9 +82,19 @@ bool IFSG_INDEX::SetIndices( size_t nIndices, int* aIndexList )
|
||||
|
||||
bool IFSG_INDEX::AddIndex( int aIndex )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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
|
||||
|
||||
( (SGINDEX*) m_node )->AddIndex( aIndex );
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGINDEX*)m_node)->AddIndex( aIndex );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* 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) 2020 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
|
||||
@@ -31,17 +30,15 @@
|
||||
#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 = nullptr;
|
||||
m_node = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +46,8 @@ IFSG_NODE::~IFSG_NODE()
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -58,11 +57,13 @@ void IFSG_NODE::Destroy( void )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGNODE* IFSG_NODE::GetRawPtr( void ) noexcept
|
||||
SGNODE* IFSG_NODE::GetRawPtr( void )
|
||||
{
|
||||
return m_node;
|
||||
}
|
||||
@@ -70,7 +71,17 @@ SGNODE* IFSG_NODE::GetRawPtr( void ) noexcept
|
||||
|
||||
S3D::SGTYPES IFSG_NODE::GetNodeType( void ) const
|
||||
{
|
||||
wxCHECK( m_node, S3D::SGTYPE_END );
|
||||
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();
|
||||
}
|
||||
@@ -78,7 +89,17 @@ S3D::SGTYPES IFSG_NODE::GetNodeType( void ) const
|
||||
|
||||
SGNODE* IFSG_NODE::GetParent( void ) const
|
||||
{
|
||||
wxCHECK( m_node, nullptr );
|
||||
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();
|
||||
}
|
||||
@@ -86,7 +107,17 @@ SGNODE* IFSG_NODE::GetParent( void ) const
|
||||
|
||||
bool IFSG_NODE::SetParent( SGNODE* aParent )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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 );
|
||||
}
|
||||
@@ -94,40 +125,90 @@ bool IFSG_NODE::SetParent( SGNODE* aParent )
|
||||
|
||||
const char* IFSG_NODE::GetName( void )
|
||||
{
|
||||
wxCHECK( m_node, nullptr );
|
||||
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 )
|
||||
bool IFSG_NODE::SetName( const char *aName )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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
|
||||
const char * IFSG_NODE::GetNodeTypeName( S3D::SGTYPES aNodeType ) const
|
||||
{
|
||||
wxCHECK( m_node, nullptr );
|
||||
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 )
|
||||
SGNODE* IFSG_NODE::FindNode( const char *aNodeName )
|
||||
{
|
||||
wxCHECK( m_node, nullptr );
|
||||
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 m_node->FindNode( aNodeName, nullptr );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m_node->FindNode( aNodeName, NULL );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NODE::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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 );
|
||||
}
|
||||
@@ -135,11 +216,31 @@ bool IFSG_NODE::AddRefNode( SGNODE* aNode )
|
||||
|
||||
bool IFSG_NODE::AddRefNode( IFSG_NODE& aNode )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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();
|
||||
|
||||
wxCHECK( np, false );
|
||||
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 );
|
||||
}
|
||||
@@ -147,7 +248,17 @@ bool IFSG_NODE::AddRefNode( IFSG_NODE& aNode )
|
||||
|
||||
bool IFSG_NODE::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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 );
|
||||
}
|
||||
@@ -155,11 +266,31 @@ bool IFSG_NODE::AddChildNode( SGNODE* aNode )
|
||||
|
||||
bool IFSG_NODE::AddChildNode( IFSG_NODE& aNode )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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();
|
||||
|
||||
wxCHECK( np, false );
|
||||
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 );
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* 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) 2020 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
|
||||
@@ -31,39 +30,53 @@
|
||||
#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 = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return;
|
||||
|
||||
m_node = new SGNORMALS( nullptr );
|
||||
m_node = new SGNORMALS( NULL );
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_NORMALS::IFSG_NORMALS( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGNORMALS( nullptr );
|
||||
m_node = new SGNORMALS( NULL );
|
||||
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,28 +84,39 @@ IFSG_NORMALS::IFSG_NORMALS( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* pp = aParent.GetRawPtr();
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef DEBUG
|
||||
if( ! pp )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
BadParent );
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
m_node = new SGNORMALS( nullptr );
|
||||
m_node = new SGNORMALS( NULL );
|
||||
|
||||
if( !m_node->SetParent( pp ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +125,7 @@ bool IFSG_NORMALS::Attach( SGNODE* aNode )
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
@@ -127,12 +151,17 @@ bool IFSG_NORMALS::NewNode( SGNODE* aParent )
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] invalid SGNODE parent (%s) to SGNORMALS" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeTypeName( aParent->GetNodeType() ) );
|
||||
#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 = nullptr;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -146,7 +175,17 @@ bool IFSG_NORMALS::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
wxCHECK( np, false );
|
||||
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 );
|
||||
}
|
||||
@@ -154,34 +193,74 @@ bool IFSG_NORMALS::NewNode( IFSG_NODE& aParent )
|
||||
|
||||
bool IFSG_NORMALS::GetNormalList( size_t& aListSize, SGVECTOR*& aNormalList )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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 ( (SGNORMALS*) m_node )->GetNormalList( aListSize, aNormalList );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGNORMALS*)m_node)->GetNormalList( aListSize, aNormalList );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NORMALS::SetNormalList( size_t aListSize, const SGVECTOR* aNormalList )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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
|
||||
|
||||
( (SGNORMALS*) m_node )->SetNormalList( aListSize, aNormalList );
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGNORMALS*)m_node)->SetNormalList( aListSize, aNormalList );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NORMALS::AddNormal( double aXValue, double aYValue, double aZValue )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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
|
||||
|
||||
( (SGNORMALS*) m_node )->AddNormal( aXValue, aYValue, aZValue );
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGNORMALS*)m_node)->AddNormal( aXValue, aYValue, aZValue );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NORMALS::AddNormal( const SGVECTOR& aNormal )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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
|
||||
|
||||
( (SGNORMALS*) m_node )->AddNormal( aNormal );
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGNORMALS*)m_node)->AddNormal( aNormal );
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* 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) 2020 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
|
||||
@@ -31,39 +30,53 @@
|
||||
#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 = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return ;
|
||||
|
||||
m_node = new SGSHAPE( nullptr );
|
||||
m_node = new SGSHAPE( NULL );
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_SHAPE::IFSG_SHAPE( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGSHAPE( nullptr );
|
||||
m_node = new SGSHAPE( NULL );
|
||||
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,28 +84,39 @@ IFSG_SHAPE::IFSG_SHAPE( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* pp = aParent.GetRawPtr();
|
||||
|
||||
#ifdef DEBUG
|
||||
if( !pp )
|
||||
#ifdef DEBUG
|
||||
if( ! pp )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
BadParent );
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
m_node = new SGSHAPE( nullptr );
|
||||
m_node = new SGSHAPE( NULL );
|
||||
|
||||
if( !m_node->SetParent( pp ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +125,7 @@ bool IFSG_SHAPE::Attach( SGNODE* aNode )
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
@@ -127,12 +151,17 @@ bool IFSG_SHAPE::NewNode( SGNODE* aParent )
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] invalid SGNODE parent (%s) to SGSHAPE" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeTypeName( aParent->GetNodeType() ) );
|
||||
#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 = nullptr;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -146,7 +175,17 @@ bool IFSG_SHAPE::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
wxCHECK( np, false );
|
||||
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 );
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* 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) 2020 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
|
||||
@@ -31,38 +30,52 @@
|
||||
#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 = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return;
|
||||
|
||||
m_node = new SCENEGRAPH( nullptr );
|
||||
m_node = new SCENEGRAPH( NULL );
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_TRANSFORM::IFSG_TRANSFORM( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SCENEGRAPH( nullptr );
|
||||
m_node = new SCENEGRAPH( NULL );
|
||||
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +84,7 @@ bool IFSG_TRANSFORM::Attach( SGNODE* aNode )
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
@@ -97,12 +110,17 @@ bool IFSG_TRANSFORM::NewNode( SGNODE* aParent )
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] invalid SGNODE parent (%s) to SCENEGRAPH" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeTypeName( aParent->GetNodeType() ) );
|
||||
#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 = nullptr;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -116,7 +134,17 @@ bool IFSG_TRANSFORM::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
wxCHECK( np, false );
|
||||
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 );
|
||||
}
|
||||
@@ -124,20 +152,40 @@ bool IFSG_TRANSFORM::NewNode( IFSG_NODE& aParent )
|
||||
|
||||
bool IFSG_TRANSFORM::SetRotation( const SGVECTOR& aRotationAxis, double aAngle )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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
|
||||
|
||||
( (SCENEGRAPH*) m_node )->rotation_axis = aRotationAxis;
|
||||
( (SCENEGRAPH*) m_node )->rotation_angle = aAngle;
|
||||
return false;
|
||||
}
|
||||
|
||||
((SCENEGRAPH*)m_node)->rotation_axis = aRotationAxis;
|
||||
((SCENEGRAPH*)m_node)->rotation_angle = aAngle;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_TRANSFORM::SetScale( const SGPOINT& aScale ) noexcept
|
||||
bool IFSG_TRANSFORM::SetScale( const SGPOINT& aScale )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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
|
||||
|
||||
( (SCENEGRAPH*) m_node )->scale = aScale;
|
||||
return false;
|
||||
}
|
||||
|
||||
((SCENEGRAPH*)m_node)->scale = aScale;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -145,27 +193,51 @@ bool IFSG_TRANSFORM::SetScale( const SGPOINT& aScale ) noexcept
|
||||
|
||||
bool IFSG_TRANSFORM::SetScale( double aScale )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
|
||||
if( aScale < 1e-8 && aScale > -1e-8 )
|
||||
if( NULL == m_node )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] |scale| is < 1e-8 - this seems strange" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#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 = SGPOINT( aScale, aScale, aScale );
|
||||
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 ) noexcept
|
||||
bool IFSG_TRANSFORM::SetTranslation( const SGPOINT& aTranslation )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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
|
||||
|
||||
( (SCENEGRAPH*) m_node )->translation = aTranslation;
|
||||
return false;
|
||||
}
|
||||
|
||||
((SCENEGRAPH*)m_node)->translation = aTranslation;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -173,20 +245,40 @@ bool IFSG_TRANSFORM::SetTranslation( const SGPOINT& aTranslation ) noexcept
|
||||
|
||||
bool IFSG_TRANSFORM::SetScaleOrientation( const SGVECTOR& aScaleAxis, double aAngle )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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
|
||||
|
||||
( (SCENEGRAPH*) m_node )->scale_axis = aScaleAxis;
|
||||
( (SCENEGRAPH*) m_node )->scale_angle = aAngle;
|
||||
return false;
|
||||
}
|
||||
|
||||
((SCENEGRAPH*)m_node)->scale_axis = aScaleAxis;
|
||||
((SCENEGRAPH*)m_node)->scale_angle = aAngle;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_TRANSFORM::SetCenter( const SGPOINT& aCenter ) noexcept
|
||||
bool IFSG_TRANSFORM::SetCenter( const SGPOINT& aCenter )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
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
|
||||
|
||||
( (SCENEGRAPH*) m_node )->center = aCenter;
|
||||
return false;
|
||||
}
|
||||
|
||||
((SCENEGRAPH*)m_node)->center = aCenter;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* 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) 2020 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
|
||||
@@ -45,19 +44,24 @@ SCENEGRAPH::SCENEGRAPH( SGNODE* aParent ) : SGNODE( aParent )
|
||||
scale.y = 1.0;
|
||||
scale.z = 1.0;
|
||||
|
||||
if( nullptr != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [BUG] inappropriate parent to SCENEGRAPH (type %d)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeType() );
|
||||
#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( nullptr != aParent && S3D::SGTYPE_TRANSFORM == aParent->GetNodeType() )
|
||||
else if( NULL != aParent && S3D::SGTYPE_TRANSFORM == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -70,12 +74,14 @@ SCENEGRAPH::~SCENEGRAPH()
|
||||
// delete owned objects
|
||||
DEL_OBJS( SCENEGRAPH, m_Transforms );
|
||||
DEL_OBJS( SGSHAPE, m_Shape );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SCENEGRAPH::SetParent( SGNODE* aParent, bool notify )
|
||||
{
|
||||
if( nullptr != m_Parent )
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
@@ -84,14 +90,14 @@ bool SCENEGRAPH::SetParent( SGNODE* aParent, bool notify )
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
if( nullptr == aParent )
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a transform may be parent to a transform
|
||||
if( nullptr != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
@@ -105,8 +111,8 @@ bool SCENEGRAPH::SetParent( SGNODE* aParent, bool notify )
|
||||
|
||||
SGNODE* SCENEGRAPH::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( nullptr == aNodeName || 0 == aNodeName[0] )
|
||||
return nullptr;
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
@@ -115,8 +121,8 @@ SGNODE* SCENEGRAPH::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
FIND_NODE( SGSHAPE, aNodeName, m_Shape, aCaller );
|
||||
|
||||
// query the parent if appropriate
|
||||
if( aCaller == m_Parent || nullptr == m_Parent )
|
||||
return nullptr;
|
||||
if( aCaller == m_Parent || NULL == m_Parent )
|
||||
return NULL;
|
||||
|
||||
return m_Parent->FindNode( aNodeName, this );
|
||||
}
|
||||
@@ -124,26 +130,33 @@ SGNODE* SCENEGRAPH::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
|
||||
void SCENEGRAPH::unlinkNode( const SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( nullptr == aNode )
|
||||
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_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;
|
||||
case S3D::SGTYPE_SHAPE:
|
||||
UNLINK_NODE( S3D::SGTYPE_SHAPE, SGSHAPE, aNode, m_Shape, m_RShape, isChild );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] unlinkNode() did not find its target" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
@@ -163,16 +176,30 @@ void SCENEGRAPH::unlinkRefNode( const SGNODE* aNode )
|
||||
|
||||
bool SCENEGRAPH::addNode( SGNODE* aNode, bool isChild )
|
||||
{
|
||||
wxCHECK( aNode, false );
|
||||
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 );
|
||||
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [BUG] object '%s' is not a valid type for this object (%d)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aNode->GetName(),
|
||||
aNode->GetNodeType() );
|
||||
#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;
|
||||
}
|
||||
@@ -210,7 +237,7 @@ void SCENEGRAPH::ReNameNodes( void )
|
||||
++sL;
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
} while(0);
|
||||
|
||||
// rename all transforms
|
||||
do
|
||||
@@ -224,13 +251,16 @@ void SCENEGRAPH::ReNameNodes( void )
|
||||
++sL;
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
} while(0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SCENEGRAPH::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
{
|
||||
if( m_Transforms.empty() && m_RTransforms.empty() && m_Shape.empty() && m_RShape.empty() )
|
||||
if( m_Transforms.empty() && m_RTransforms.empty()
|
||||
&& m_Shape.empty() && m_RShape.empty() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -336,14 +366,14 @@ bool SCENEGRAPH::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
|
||||
bool SCENEGRAPH::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( nullptr == parentNode && nullptr != m_Parent )
|
||||
if( NULL == parentNode && NULL != m_Parent )
|
||||
{
|
||||
SGNODE* np = m_Parent;
|
||||
|
||||
while( nullptr != np->GetParent() )
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, nullptr ) )
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
@@ -352,9 +382,19 @@ bool SCENEGRAPH::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
return false;
|
||||
}
|
||||
|
||||
wxCHECK( parentNode == m_Parent, 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
|
||||
|
||||
if( nullptr == m_Parent )
|
||||
return false;
|
||||
}
|
||||
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
// ensure unique node names
|
||||
ResetNodeIndex();
|
||||
@@ -363,8 +403,12 @@ bool SCENEGRAPH::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( aFile.fail() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad stream" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#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;
|
||||
}
|
||||
@@ -420,9 +464,12 @@ bool SCENEGRAPH::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( !m_Transforms[i]->WriteCache( aFile, this ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [INFO] bad stream while writing child transforms" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#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;
|
||||
}
|
||||
@@ -430,20 +477,21 @@ bool SCENEGRAPH::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
|
||||
// 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 ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [INFO] bad stream while writing child shapes" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#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;
|
||||
}
|
||||
@@ -451,7 +499,6 @@ bool SCENEGRAPH::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
|
||||
// write referenced transform names
|
||||
asize = m_RShape.size();
|
||||
|
||||
for( i = 0; i < asize; ++i )
|
||||
aFile << "[" << m_RShape[i]->GetName() << "]";
|
||||
|
||||
@@ -465,20 +512,33 @@ bool SCENEGRAPH::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
|
||||
bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
wxCHECK( m_Transforms.empty() && m_RTransforms.empty() && m_Shape.empty() && m_RShape.empty(),
|
||||
false );
|
||||
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( nullptr == parentNode )
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
// we need to read the tag and verify its type
|
||||
if( S3D::SGTYPE_TRANSFORM != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; tag mismatch at position "
|
||||
"%ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#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;
|
||||
}
|
||||
@@ -512,10 +572,13 @@ bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_TRANSFORM != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad child transform tag "
|
||||
"at position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#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;
|
||||
}
|
||||
@@ -525,10 +588,13 @@ bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !sp->ReadCache( aFile, this ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data while reading transform "
|
||||
"%ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#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;
|
||||
}
|
||||
@@ -539,10 +605,13 @@ bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_TRANSFORM != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad ref transform tag at "
|
||||
"position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#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;
|
||||
}
|
||||
@@ -551,20 +620,26 @@ bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !sp )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: cannot find ref "
|
||||
"transform at position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#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() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: type is not TRANSFORM "
|
||||
"at position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#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;
|
||||
}
|
||||
@@ -577,10 +652,13 @@ bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_SHAPE != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad child shape tag at "
|
||||
"position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#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;
|
||||
}
|
||||
@@ -590,10 +668,13 @@ bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !sp->ReadCache( aFile, this ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; corrupt data while "
|
||||
"reading shape at position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#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;
|
||||
}
|
||||
@@ -604,10 +685,13 @@ bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_SHAPE != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad ref shape tag at "
|
||||
"position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#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;
|
||||
}
|
||||
@@ -616,20 +700,26 @@ bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !sp )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: cannot find ref shape "
|
||||
"at position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#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() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: type is not SGSHAPE at "
|
||||
"position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#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;
|
||||
}
|
||||
@@ -644,27 +734,21 @@ bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
}
|
||||
|
||||
|
||||
bool SCENEGRAPH::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
std::vector< SMESH >& meshes )
|
||||
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 ) );
|
||||
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 ) );
|
||||
|
||||
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 ) );
|
||||
@@ -676,7 +760,7 @@ bool SCENEGRAPH::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
// tx0 = tM * cM * rM * srM * sM * nsrM * ncM
|
||||
glm::dmat4 tx0;
|
||||
|
||||
if( nullptr != aTransform )
|
||||
if( NULL != aTransform )
|
||||
tx0 = (*aTransform) * tM * cM * rM * srM * sM * nsrM * ncM;
|
||||
else
|
||||
tx0 = tM * cM * rM * srM * sM * nsrM * ncM;
|
||||
@@ -704,7 +788,7 @@ bool SCENEGRAPH::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
++sL;
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
} while(0);
|
||||
|
||||
// prepare all transforms
|
||||
do
|
||||
@@ -727,7 +811,7 @@ bool SCENEGRAPH::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
++sL;
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
} while(0);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* 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) 2020 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
|
||||
@@ -24,6 +23,10 @@
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -35,18 +38,38 @@
|
||||
|
||||
class SGSHAPE;
|
||||
|
||||
/**
|
||||
* Define 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.
|
||||
*/
|
||||
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();
|
||||
|
||||
@@ -61,35 +84,8 @@ public:
|
||||
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 );
|
||||
|
||||
private:
|
||||
void unlinkNode( const SGNODE* aNode, bool isChild );
|
||||
bool addNode( SGNODE* aNode, bool isChild );
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
bool Prepare( const glm::dmat4* aTransform,
|
||||
S3D::MATLIST& materials, std::vector< SMESH >& meshes );
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2020 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
|
||||
@@ -30,40 +29,46 @@
|
||||
#include "3d_cache/sg/sg_appearance.h"
|
||||
#include "3d_cache/sg/sg_helpers.h"
|
||||
|
||||
|
||||
SGAPPEARANCE::SGAPPEARANCE( SGNODE* aParent ) : SGNODE( aParent )
|
||||
SGAPPEARANCE::SGAPPEARANCE( SGNODE* aParent ) : SGNODE( aParent)
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_APPEARANCE;
|
||||
|
||||
// defaults in accord with VRML2.0 spec
|
||||
ambient.SetColor( 0.05317f, 0.17879f, 0.01804f );
|
||||
shininess = 0.2f;
|
||||
transparency = 0.0f;
|
||||
diffuse.SetColor( 0.8f, 0.8f, 0.8f );
|
||||
ambient.SetColor( 0.05317, 0.17879, 0.01804 );
|
||||
shininess = 0.2;
|
||||
transparency = 0.0;
|
||||
diffuse.SetColor( 0.8, 0.8, 0.8 );
|
||||
|
||||
if( nullptr != aParent && S3D::SGTYPE_SHAPE != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_SHAPE != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [BUG] inappropriate parent to SGAPPEARANCE (type %s )" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aParent->GetNodeType() );
|
||||
#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( nullptr != aParent && S3D::SGTYPE_SHAPE == aParent->GetNodeType() )
|
||||
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( nullptr != m_Parent )
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
@@ -72,14 +77,14 @@ bool SGAPPEARANCE::SetParent( SGNODE* aParent, bool notify )
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
if( nullptr == aParent )
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a SGSHAPE may be parent to a SGAPPEARANCE
|
||||
if( nullptr != aParent && S3D::SGTYPE_SHAPE != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_SHAPE != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
@@ -99,7 +104,17 @@ bool SGAPPEARANCE::SetEmissive( float aRVal, float aGVal, float aBVal )
|
||||
|
||||
bool SGAPPEARANCE::SetEmissive( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
wxCHECK_MSG( aRGBColor, false, wxT( "NULL pointer passed for 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 );
|
||||
}
|
||||
@@ -119,7 +134,17 @@ bool SGAPPEARANCE::SetDiffuse( float aRVal, float aGVal, float aBVal )
|
||||
|
||||
bool SGAPPEARANCE::SetDiffuse( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
wxCHECK_MSG( aRGBColor, false, wxT( "NULL pointer passed for 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 );
|
||||
}
|
||||
@@ -139,7 +164,17 @@ bool SGAPPEARANCE::SetSpecular( float aRVal, float aGVal, float aBVal )
|
||||
|
||||
bool SGAPPEARANCE::SetSpecular( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
wxCHECK_MSG( aRGBColor, false, wxT( "NULL pointer passed for 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 );
|
||||
}
|
||||
@@ -158,7 +193,17 @@ bool SGAPPEARANCE::SetAmbient( float aRVal, float aGVal, float aBVal )
|
||||
|
||||
bool SGAPPEARANCE::SetAmbient( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
wxCHECK_MSG( aRGBColor, false, wxT( "NULL pointer passed for 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 );
|
||||
}
|
||||
@@ -170,46 +215,66 @@ bool SGAPPEARANCE::SetAmbient( const SGCOLOR& aRGBColor )
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGAPPEARANCE::FindNode( const char* aNodeName, const SGNODE* aCaller) noexcept
|
||||
SGNODE* SGAPPEARANCE::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( nullptr == aNodeName || 0 == aNodeName[0] )
|
||||
return nullptr;
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void SGAPPEARANCE::unlinkChildNode( const SGNODE* aCaller ) noexcept
|
||||
void SGAPPEARANCE::unlinkChildNode( const SGNODE* aCaller )
|
||||
{
|
||||
wxCHECK_MSG( aCaller, /* void */,
|
||||
wxT( "unexpected code branch; node should have no children or refs" ) );
|
||||
#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 ) noexcept
|
||||
void SGAPPEARANCE::unlinkRefNode( const SGNODE* aCaller )
|
||||
{
|
||||
wxCHECK_MSG( aCaller, /* void */,
|
||||
wxT( "unexpected code branch; node should have no children or refs" ) );
|
||||
#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 ) noexcept
|
||||
bool SGAPPEARANCE::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK_MSG( aNode, false, wxT( "this node does not accept children or refs" ) );
|
||||
#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
|
||||
|
||||
// This is redundant but it keeps gcc from generating a warning on debug builds.
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::AddChildNode( SGNODE* aNode ) noexcept
|
||||
bool SGAPPEARANCE::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK_MSG( aNode, false, wxT( "this node does not accept children or refs" ) );
|
||||
#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
|
||||
|
||||
// This is redundant but it keeps gcc from generating a warning on debug builds.
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -253,13 +318,13 @@ bool SGAPPEARANCE::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
diffuse.GetColor( ambr, ambg, ambb );
|
||||
float den = ( 0.212671 * ambr + 0.71516 * ambg + 0.072169 * ambb );
|
||||
|
||||
if( den < 0.004f )
|
||||
den = 0.004f;
|
||||
if( den < 0.004 )
|
||||
den = 0.004;
|
||||
|
||||
amb /= den;
|
||||
|
||||
if( amb > 1.0f )
|
||||
amb = 1.0f;
|
||||
if( amb > 1.0 )
|
||||
amb = 1.0;
|
||||
|
||||
S3D::FormatFloat( tmp, amb );
|
||||
aFile << " ambientIntensity " << tmp << "\n";
|
||||
@@ -303,16 +368,26 @@ bool SGAPPEARANCE::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
|
||||
bool SGAPPEARANCE::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( nullptr == parentNode )
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
wxCHECK_MSG( m_Parent, false, wxT( "corrupt data; m_aParent is NULL" ) );
|
||||
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( nullptr != np->GetParent() )
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, nullptr ) )
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
@@ -321,20 +396,34 @@ bool SGAPPEARANCE::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
return false;
|
||||
}
|
||||
|
||||
wxCHECK_MSG( parentNode == m_Parent, false, wxT( "corrupt data; parentNode != m_aParent" ) );
|
||||
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() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad stream" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#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 ) );
|
||||
aFile.write( (char*)&shininess, sizeof(shininess) );
|
||||
aFile.write( (char*)&transparency, sizeof(transparency) );
|
||||
S3D::WriteColor( aFile, diffuse );
|
||||
S3D::WriteColor( aFile, emissive );
|
||||
S3D::WriteColor( aFile, specular );
|
||||
@@ -350,8 +439,8 @@ bool SGAPPEARANCE::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
bool SGAPPEARANCE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
S3D::ReadColor( aFile, ambient );
|
||||
aFile.read( (char*) &shininess, sizeof( shininess ) );
|
||||
aFile.read( (char*) &transparency, sizeof( transparency ) );
|
||||
aFile.read( (char*)&shininess, sizeof(shininess) );
|
||||
aFile.read( (char*)&transparency, sizeof(transparency) );
|
||||
S3D::ReadColor( aFile, diffuse );
|
||||
S3D::ReadColor( aFile, emissive );
|
||||
S3D::ReadColor( aFile, specular );
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2020 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
|
||||
@@ -24,6 +23,7 @@
|
||||
|
||||
/**
|
||||
* @file sg_appearance.h
|
||||
* defines the generic material appearance of a scenegraph object
|
||||
*/
|
||||
|
||||
#ifndef SG_APPEARANCE_H
|
||||
@@ -31,15 +31,20 @@
|
||||
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
|
||||
/**
|
||||
* Defines the generic material appearance of a scenegraph object.
|
||||
*/
|
||||
class SGAPPEARANCE : public SGNODE
|
||||
{
|
||||
public:
|
||||
void unlinkChildNode( const SGNODE* aNode ) noexcept override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) noexcept override;
|
||||
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();
|
||||
|
||||
@@ -61,23 +66,15 @@ public:
|
||||
bool SetAmbient( const SGCOLOR* aRGBColor );
|
||||
bool SetAmbient( const SGCOLOR& aRGBColor );
|
||||
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) noexcept override;
|
||||
bool AddRefNode( SGNODE* aNode ) noexcept override;
|
||||
bool AddChildNode( SGNODE* aNode ) noexcept 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;
|
||||
|
||||
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
|
||||
|
||||
};
|
||||
|
||||
#endif // SG_APPEARANCE_H
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* 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) 2020 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
|
||||
@@ -36,14 +35,20 @@ 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 ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] invalid value passed to constructor" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#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;
|
||||
@@ -53,32 +58,46 @@ SGCOLOR::SGCOLOR( float aRVal, float aGVal, float aBVal )
|
||||
red = aRVal;
|
||||
green = aGVal;
|
||||
blue = aBVal;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOLOR::GetColor( float& aRedVal, float& aGreenVal, float& aBlueVal ) const noexcept
|
||||
void SGCOLOR::GetColor( float& aRedVal, float& aGreenVal, float& aBlueVal ) const
|
||||
{
|
||||
aRedVal = red;
|
||||
aGreenVal = green;
|
||||
aBlueVal = blue;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOLOR::GetColor( SGCOLOR& aColor ) const noexcept
|
||||
void SGCOLOR::GetColor( SGCOLOR& aColor ) const
|
||||
{
|
||||
aColor.red = red;
|
||||
aColor.green = green;
|
||||
aColor.blue = blue;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOLOR::GetColor( SGCOLOR* aColor ) const noexcept
|
||||
void SGCOLOR::GetColor( SGCOLOR* aColor ) const
|
||||
{
|
||||
wxCHECK_MSG( aColor, /* void */, wxT( "NULL pointer passed for aRGBColor" ) );
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -95,7 +114,7 @@ bool SGCOLOR::SetColor( float aRedVal, float aGreenVal, float aBlueVal )
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLOR::SetColor( const SGCOLOR& aColor ) noexcept
|
||||
bool SGCOLOR::SetColor( const SGCOLOR& aColor )
|
||||
{
|
||||
red = aColor.red;
|
||||
green = aColor.green;
|
||||
@@ -104,9 +123,19 @@ bool SGCOLOR::SetColor( const SGCOLOR& aColor ) noexcept
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLOR::SetColor( const SGCOLOR* aColor ) noexcept
|
||||
bool SGCOLOR::SetColor( const SGCOLOR* aColor )
|
||||
{
|
||||
wxCHECK_MSG( aColor, false, wxT( "NULL pointer passed for aRGBColor" ) );
|
||||
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;
|
||||
@@ -115,31 +144,42 @@ bool SGCOLOR::SetColor( const SGCOLOR* aColor ) noexcept
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLOR::checkRange( float aRedVal, float aGreenVal, float aBlueVal ) const noexcept
|
||||
bool SGCOLOR::checkRange( float aRedVal, float aGreenVal, float aBlueVal ) const
|
||||
{
|
||||
bool ok = true;
|
||||
|
||||
if( aRedVal < 0.0 || aRedVal > 1.0 )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] invalid RED value: %g" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aRedVal );
|
||||
|
||||
#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 )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] invalid GREEN value: %g" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aGreenVal );
|
||||
|
||||
#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 )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] invalid BLUE value: %g" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aBlueVal );
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
@@ -152,10 +192,11 @@ SGPOINT::SGPOINT()
|
||||
x = 0.0;
|
||||
y = 0.0;
|
||||
z = 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGPOINT::SGPOINT( double aXVal, double aYVal, double aZVal ) noexcept
|
||||
SGPOINT::SGPOINT( double aXVal, double aYVal, double aZVal )
|
||||
{
|
||||
x = aXVal;
|
||||
y = aYVal;
|
||||
@@ -163,45 +204,60 @@ SGPOINT::SGPOINT( double aXVal, double aYVal, double aZVal ) noexcept
|
||||
}
|
||||
|
||||
|
||||
void SGPOINT::GetPoint( const double& aXVal, const double& aYVal, const double& aZVal ) noexcept
|
||||
void SGPOINT::GetPoint( double& aXVal, double& aYVal, double& aZVal )
|
||||
{
|
||||
x = aXVal;
|
||||
y = aYVal;
|
||||
z = aZVal;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGPOINT::GetPoint( const SGPOINT& aPoint ) noexcept
|
||||
void SGPOINT::GetPoint( SGPOINT& aPoint )
|
||||
{
|
||||
x = aPoint.x;
|
||||
y = aPoint.y;
|
||||
z = aPoint.z;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGPOINT::GetPoint( const SGPOINT* aPoint ) noexcept
|
||||
void SGPOINT::GetPoint( SGPOINT* aPoint )
|
||||
{
|
||||
wxCHECK_MSG( aPoint, /* void */, wxT( "NULL pointer passed for 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 ) noexcept
|
||||
void SGPOINT::SetPoint( double aXVal, double aYVal, double aZVal )
|
||||
{
|
||||
x = aXVal;
|
||||
y = aYVal;
|
||||
z = aZVal;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGPOINT::SetPoint( const SGPOINT& aPoint ) noexcept
|
||||
void SGPOINT::SetPoint( const SGPOINT& aPoint )
|
||||
{
|
||||
x = aPoint.x;
|
||||
y = aPoint.y;
|
||||
z = aPoint.z;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -210,6 +266,7 @@ SGVECTOR::SGVECTOR()
|
||||
vx = 0.0;
|
||||
vy = 0.0;
|
||||
vz = 1.0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -219,14 +276,16 @@ SGVECTOR::SGVECTOR( double aXVal, double aYVal, double aZVal )
|
||||
vy = aYVal;
|
||||
vz = aZVal;
|
||||
normalize();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGVECTOR::GetVector( double& aXVal, double& aYVal, double& aZVal ) const noexcept
|
||||
void SGVECTOR::GetVector( double& aXVal, double& aYVal, double& aZVal ) const
|
||||
{
|
||||
aXVal = vx;
|
||||
aYVal = vy;
|
||||
aZVal = vz;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -236,25 +295,28 @@ void SGVECTOR::SetVector( double aXVal, double aYVal, double aZVal )
|
||||
vy = aYVal;
|
||||
vz = aZVal;
|
||||
normalize();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGVECTOR::SetVector( const SGVECTOR& aVector )
|
||||
{
|
||||
aVector.GetVector( vx, vy, vz );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGVECTOR::normalize( void ) noexcept
|
||||
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 )
|
||||
if( (dx + dy + dz) < 1e-8 )
|
||||
{
|
||||
// use the default; the numbers are too small to be believable
|
||||
// use the default; the numbers are too small
|
||||
// to be believable
|
||||
vx = 0.0;
|
||||
vy = 0.0;
|
||||
vz = 1.0;
|
||||
@@ -264,10 +326,12 @@ void SGVECTOR::normalize( void ) noexcept
|
||||
vx /= dv2;
|
||||
vy /= dv2;
|
||||
vz /= dv2;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGVECTOR& SGVECTOR::operator=( const SGVECTOR& source ) noexcept
|
||||
SGVECTOR& SGVECTOR::operator=( const SGVECTOR& source )
|
||||
{
|
||||
vx = source.vx;
|
||||
vy = source.vy;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2020 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
|
||||
@@ -29,35 +28,41 @@
|
||||
#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( nullptr != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [BUG] inappropriate parent to SGCOLORS (type %s)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aParent->GetNodeType() );
|
||||
#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( nullptr != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||
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( nullptr != m_Parent )
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
@@ -66,14 +71,14 @@ bool SGCOLORS::SetParent( SGNODE* aParent, bool notify )
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
if( nullptr == aParent )
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a SGFACESET may be parent to a SGCOLORS
|
||||
if( nullptr != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
@@ -85,41 +90,65 @@ bool SGCOLORS::SetParent( SGNODE* aParent, bool notify )
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGCOLORS::FindNode(const char* aNodeName, const SGNODE *aCaller) noexcept
|
||||
SGNODE* SGCOLORS::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( nullptr == aNodeName || 0 == aNodeName[0] )
|
||||
return nullptr;
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void SGCOLORS::unlinkChildNode( const SGNODE* aCaller ) noexcept
|
||||
void SGCOLORS::unlinkChildNode( const SGNODE* aCaller )
|
||||
{
|
||||
wxCHECK( aCaller, /* void */ );
|
||||
#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 ) noexcept
|
||||
void SGCOLORS::unlinkRefNode( const SGNODE* aCaller )
|
||||
{
|
||||
wxCHECK( aCaller, /* void */ );
|
||||
#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 ) noexcept
|
||||
bool SGCOLORS::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK( aNode, false );
|
||||
#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 ) noexcept
|
||||
bool SGCOLORS::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK( aNode, false );
|
||||
#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;
|
||||
}
|
||||
@@ -130,7 +159,7 @@ bool SGCOLORS::GetColorList( size_t& aListSize, SGCOLOR*& aColorList )
|
||||
if( colors.empty() )
|
||||
{
|
||||
aListSize = 0;
|
||||
aColorList = nullptr;
|
||||
aColorList = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -144,7 +173,7 @@ void SGCOLORS::SetColorList( size_t aListSize, const SGCOLOR* aColorList )
|
||||
{
|
||||
colors.clear();
|
||||
|
||||
if( 0 == aListSize || nullptr == aColorList )
|
||||
if( 0 == aListSize || NULL == aColorList )
|
||||
return;
|
||||
|
||||
for( size_t i = 0; i < aListSize; ++i )
|
||||
@@ -156,7 +185,7 @@ void SGCOLORS::SetColorList( size_t aListSize, const SGCOLOR* aColorList )
|
||||
|
||||
void SGCOLORS::AddColor( double aRedValue, double aGreenValue, double aBlueValue )
|
||||
{
|
||||
colors.emplace_back( aRedValue, aGreenValue, aBlueValue );
|
||||
colors.push_back( SGCOLOR( aRedValue, aGreenValue, aBlueValue ) );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -238,16 +267,26 @@ bool SGCOLORS::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
|
||||
bool SGCOLORS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( nullptr == parentNode )
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
wxCHECK( m_Parent, false );
|
||||
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( nullptr != np->GetParent() )
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, nullptr ) )
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
@@ -256,12 +295,26 @@ bool SGCOLORS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
return false;
|
||||
}
|
||||
|
||||
wxCHECK( parentNode == m_Parent, 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() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad stream" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#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;
|
||||
}
|
||||
@@ -283,10 +336,20 @@ bool SGCOLORS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
|
||||
bool SGCOLORS::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
wxCHECK( colors.empty(), false );
|
||||
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 ) );
|
||||
aFile.read( (char*)&ncolors, sizeof(size_t) );
|
||||
SGCOLOR tmp;
|
||||
|
||||
if( aFile.fail() )
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2020 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
|
||||
@@ -24,6 +23,7 @@
|
||||
|
||||
/**
|
||||
* @file sg_colors.h
|
||||
* defines an RGB color set for a scenegraph object
|
||||
*/
|
||||
|
||||
#ifndef SG_COLORS_H
|
||||
@@ -32,23 +32,23 @@
|
||||
#include <vector>
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
|
||||
/**
|
||||
* Define an RGB color set for a scenegraph object.
|
||||
*/
|
||||
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;
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) noexcept override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) noexcept override;
|
||||
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) noexcept override;
|
||||
bool AddRefNode( SGNODE* aNode ) noexcept override;
|
||||
bool AddChildNode( SGNODE* aNode ) noexcept 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 );
|
||||
@@ -60,8 +60,6 @@ public:
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
|
||||
std::vector< SGCOLOR > colors;
|
||||
};
|
||||
|
||||
#endif // SG_COLORS_H
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* 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) 2020-2021 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
|
||||
@@ -29,15 +28,18 @@ SGCOORDINDEX::SGCOORDINDEX( SGNODE* aParent ) : SGINDEX( aParent )
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_COORDINDEX;
|
||||
|
||||
if( nullptr != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGCOORDINDEX::~SGCOORDINDEX()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,4 +49,6 @@ void SGCOORDINDEX::GatherCoordIndices( std::vector< int >& aIndexList )
|
||||
return;
|
||||
|
||||
aIndexList.insert( aIndexList.end(), index.begin(), index.end() );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* 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) 2020 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
|
||||
@@ -24,6 +23,7 @@
|
||||
|
||||
/**
|
||||
* @file sg_coordindex.h
|
||||
* defines an coordinate index set for a scenegraph object
|
||||
*/
|
||||
|
||||
#ifndef SG_COORDINDEX_H
|
||||
@@ -32,12 +32,14 @@
|
||||
#include "3d_cache/sg/sg_index.h"
|
||||
|
||||
/**
|
||||
* An object to maintain 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
|
||||
* 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
|
||||
{
|
||||
@@ -46,7 +48,9 @@ public:
|
||||
virtual ~SGCOORDINDEX();
|
||||
|
||||
/**
|
||||
* Add all coordinate indices to the given list in preparation for a normals calculation.
|
||||
* Function GatherCoordIndices
|
||||
* adds all coordinate indices to the given list
|
||||
* in preparation for a normals calculation
|
||||
*/
|
||||
void GatherCoordIndices( std::vector< int >& aIndexList );
|
||||
};
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2020 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
|
||||
@@ -36,30 +35,37 @@ SGCOORDS::SGCOORDS( SGNODE* aParent ) : SGNODE( aParent )
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_COORDS;
|
||||
|
||||
if( nullptr != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [BUG] inappropriate parent to SGCOORDS (type %s)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aParent->GetNodeType() );
|
||||
#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( nullptr != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||
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( nullptr != m_Parent )
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
@@ -68,14 +74,14 @@ bool SGCOORDS::SetParent( SGNODE* aParent, bool notify )
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
if( nullptr == aParent )
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a SGFACESET may be parent to a SGCOORDS
|
||||
if( nullptr != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
@@ -87,41 +93,65 @@ bool SGCOORDS::SetParent( SGNODE* aParent, bool notify )
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGCOORDS::FindNode(const char *aNodeName, const SGNODE *aCaller) noexcept
|
||||
SGNODE* SGCOORDS::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( nullptr == aNodeName || 0 == aNodeName[0] )
|
||||
return nullptr;
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void SGCOORDS::unlinkChildNode( const SGNODE* aCaller ) noexcept
|
||||
void SGCOORDS::unlinkChildNode( const SGNODE* aCaller )
|
||||
{
|
||||
wxCHECK( aCaller, /* void */ );
|
||||
#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 ) noexcept
|
||||
void SGCOORDS::unlinkRefNode( const SGNODE* aCaller )
|
||||
{
|
||||
wxCHECK( aCaller, /* void */ );
|
||||
#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 ) noexcept
|
||||
bool SGCOORDS::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK( aNode, false );
|
||||
#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 ) noexcept
|
||||
bool SGCOORDS::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK( aNode, false );
|
||||
#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;
|
||||
}
|
||||
@@ -132,7 +162,7 @@ bool SGCOORDS::GetCoordsList( size_t& aListSize, SGPOINT*& aCoordsList )
|
||||
if( coords.empty() )
|
||||
{
|
||||
aListSize = 0;
|
||||
aCoordsList = nullptr;
|
||||
aCoordsList = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -146,23 +176,27 @@ void SGCOORDS::SetCoordsList( size_t aListSize, const SGPOINT* aCoordsList )
|
||||
{
|
||||
coords.clear();
|
||||
|
||||
if( 0 == aListSize || nullptr == aCoordsList )
|
||||
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.emplace_back( aXValue, aYValue, aZValue );
|
||||
coords.push_back( SGPOINT( aXValue, aYValue, aZValue ) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOORDS::AddCoord( const SGPOINT& aPoint )
|
||||
{
|
||||
coords.push_back( aPoint );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -240,16 +274,26 @@ bool SGCOORDS::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
|
||||
bool SGCOORDS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( nullptr == parentNode )
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
wxCHECK( m_Parent, false );
|
||||
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( nullptr != np->GetParent() )
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, nullptr ) )
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
@@ -258,12 +302,26 @@ bool SGCOORDS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
return false;
|
||||
}
|
||||
|
||||
wxCHECK( parentNode == m_Parent, 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() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad stream" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#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;
|
||||
}
|
||||
@@ -285,10 +343,20 @@ bool SGCOORDS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
|
||||
bool SGCOORDS::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
wxCHECK( coords.empty(), false );
|
||||
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 ) );
|
||||
aFile.read( (char*)&npts, sizeof(size_t) );
|
||||
SGPOINT tmp;
|
||||
|
||||
if( aFile.fail() )
|
||||
@@ -309,15 +377,15 @@ bool SGCOORDS::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
bool SGCOORDS::CalcNormals( SGFACESET* callingNode, SGNODE** aPtr )
|
||||
{
|
||||
if( aPtr )
|
||||
*aPtr = nullptr;
|
||||
*aPtr = NULL;
|
||||
|
||||
if( nullptr == m_Parent || nullptr == callingNode )
|
||||
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 = nullptr;
|
||||
SGNORMALS* np = NULL;
|
||||
|
||||
if( callingNode == m_Parent )
|
||||
{
|
||||
@@ -333,7 +401,7 @@ bool SGCOORDS::CalcNormals( SGFACESET* callingNode, SGNODE** aPtr )
|
||||
++sB;
|
||||
}
|
||||
|
||||
np = ( (SGFACESET*) m_Parent )->m_Normals;
|
||||
np = ((SGFACESET*)m_Parent)->m_Normals;
|
||||
|
||||
if( !np )
|
||||
np = new SGNORMALS( m_Parent );
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2020 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
|
||||
@@ -24,6 +23,7 @@
|
||||
|
||||
/**
|
||||
* @file sg_coords.h
|
||||
* defines a vertex coordinate set for a scenegraph object
|
||||
*/
|
||||
|
||||
#ifndef SG_COORDS_H
|
||||
@@ -34,23 +34,23 @@
|
||||
|
||||
class SGFACESET;
|
||||
|
||||
/**
|
||||
* Define a vertex coordinate set for a scenegraph object.
|
||||
*/
|
||||
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();
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) noexcept override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) noexcept override;
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) noexcept override;
|
||||
bool AddRefNode( SGNODE* aNode ) noexcept override;
|
||||
bool AddChildNode( SGNODE* aNode ) noexcept 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 );
|
||||
@@ -58,18 +58,17 @@ public:
|
||||
void AddCoord( const SGPOINT& aPoint );
|
||||
|
||||
/**
|
||||
* Calculate normals for this coordinate list and sets the normals list in the
|
||||
* parent #SGFACESET.
|
||||
* Function CalcNormals
|
||||
* calculates normals for this coordinate list and sets the
|
||||
* normals list in the parent SGFACESET
|
||||
*/
|
||||
bool CalcNormals( SGFACESET* callingNode, SGNODE** aPtr = nullptr );
|
||||
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;
|
||||
|
||||
std::vector< SGPOINT > coords;
|
||||
};
|
||||
|
||||
#endif // SG_COORDS_H
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2020 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
|
||||
@@ -34,33 +33,37 @@
|
||||
#include "3d_cache/sg/sg_coordindex.h"
|
||||
#include "3d_cache/sg/sg_helpers.h"
|
||||
|
||||
|
||||
SGFACESET::SGFACESET( SGNODE* aParent ) : SGNODE( aParent )
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_FACESET;
|
||||
m_Colors = nullptr;
|
||||
m_Coords = nullptr;
|
||||
m_CoordIndices = nullptr;
|
||||
m_Normals = nullptr;
|
||||
m_RColors = nullptr;
|
||||
m_RCoords = nullptr;
|
||||
m_RNormals = nullptr;
|
||||
m_Colors = NULL;
|
||||
m_Coords = NULL;
|
||||
m_CoordIndices = NULL;
|
||||
m_Normals = NULL;
|
||||
m_RColors = NULL;
|
||||
m_RCoords = NULL;
|
||||
m_RNormals = NULL;
|
||||
valid = false;
|
||||
validated = false;
|
||||
|
||||
if( nullptr != aParent && S3D::SGTYPE_SHAPE != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_SHAPE != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [BUG] inappropriate parent to SGFACESET (type %s)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeType() );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] inappropriate parent to SGFACESET (type ";
|
||||
ostr << aParent->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
else if( nullptr != aParent && S3D::SGTYPE_SHAPE == aParent->GetNodeType() )
|
||||
else if( NULL != aParent && S3D::SGTYPE_SHAPE == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -70,55 +73,57 @@ SGFACESET::~SGFACESET()
|
||||
if( m_RColors )
|
||||
{
|
||||
m_RColors->delNodeRef( this );
|
||||
m_RColors = nullptr;
|
||||
m_RColors = NULL;
|
||||
}
|
||||
|
||||
if( m_RCoords )
|
||||
{
|
||||
m_RCoords->delNodeRef( this );
|
||||
m_RCoords = nullptr;
|
||||
m_RCoords = NULL;
|
||||
}
|
||||
|
||||
if( m_RNormals )
|
||||
{
|
||||
m_RNormals->delNodeRef( this );
|
||||
m_RNormals = nullptr;
|
||||
m_RNormals = NULL;
|
||||
}
|
||||
|
||||
// delete owned objects
|
||||
if( m_Colors )
|
||||
{
|
||||
m_Colors->SetParent( nullptr, false );
|
||||
m_Colors->SetParent( NULL, false );
|
||||
delete m_Colors;
|
||||
m_Colors = nullptr;
|
||||
m_Colors = NULL;
|
||||
}
|
||||
|
||||
if( m_Coords )
|
||||
{
|
||||
m_Coords->SetParent( nullptr, false );
|
||||
m_Coords->SetParent( NULL, false );
|
||||
delete m_Coords;
|
||||
m_Coords = nullptr;
|
||||
m_Coords = NULL;
|
||||
}
|
||||
|
||||
if( m_Normals )
|
||||
{
|
||||
m_Normals->SetParent( nullptr, false );
|
||||
m_Normals->SetParent( NULL, false );
|
||||
delete m_Normals;
|
||||
m_Normals = nullptr;
|
||||
m_Normals = NULL;
|
||||
}
|
||||
|
||||
if( m_CoordIndices )
|
||||
{
|
||||
m_CoordIndices->SetParent( nullptr, false );
|
||||
m_CoordIndices->SetParent( NULL, false );
|
||||
delete m_CoordIndices;
|
||||
m_CoordIndices = nullptr;
|
||||
m_CoordIndices = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGFACESET::SetParent( SGNODE* aParent, bool notify )
|
||||
{
|
||||
if( nullptr != m_Parent )
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
@@ -127,14 +132,14 @@ bool SGFACESET::SetParent( SGNODE* aParent, bool notify )
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
if( nullptr == aParent )
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a SGSHAPE may be parent to a SGFACESET
|
||||
if( nullptr != aParent && S3D::SGTYPE_SHAPE != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_SHAPE != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
@@ -148,13 +153,13 @@ bool SGFACESET::SetParent( SGNODE* aParent, bool notify )
|
||||
|
||||
SGNODE* SGFACESET::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( nullptr == aNodeName || 0 == aNodeName[0] )
|
||||
return nullptr;
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
SGNODE* np = nullptr;
|
||||
SGNODE* np = NULL;
|
||||
|
||||
if( m_Colors )
|
||||
{
|
||||
@@ -189,8 +194,8 @@ SGNODE* SGFACESET::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
}
|
||||
|
||||
// query the parent if appropriate
|
||||
if( aCaller == m_Parent || nullptr == m_Parent )
|
||||
return nullptr;
|
||||
if( aCaller == m_Parent || NULL == m_Parent )
|
||||
return NULL;
|
||||
|
||||
return m_Parent->FindNode( aNodeName, this );
|
||||
}
|
||||
@@ -198,7 +203,7 @@ SGNODE* SGFACESET::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
|
||||
void SGFACESET::unlinkNode( const SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( nullptr == aNode )
|
||||
if( NULL == aNode )
|
||||
return;
|
||||
|
||||
valid = false;
|
||||
@@ -208,25 +213,25 @@ void SGFACESET::unlinkNode( const SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( aNode == m_Colors )
|
||||
{
|
||||
m_Colors = nullptr;
|
||||
m_Colors = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if( aNode == m_Coords )
|
||||
{
|
||||
m_Coords = nullptr;
|
||||
m_Coords = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if( aNode == m_Normals )
|
||||
{
|
||||
m_Normals = nullptr;
|
||||
m_Normals = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if( aNode == m_CoordIndices )
|
||||
{
|
||||
m_CoordIndices = nullptr;
|
||||
m_CoordIndices = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -235,46 +240,66 @@ void SGFACESET::unlinkNode( const SGNODE* aNode, bool isChild )
|
||||
if( aNode == m_RColors )
|
||||
{
|
||||
delNodeRef( this );
|
||||
m_RColors = nullptr;
|
||||
m_RColors = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if( aNode == m_RCoords )
|
||||
{
|
||||
delNodeRef( this );
|
||||
m_RCoords = nullptr;
|
||||
m_RCoords = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if( aNode == m_RNormals )
|
||||
{
|
||||
delNodeRef( this );
|
||||
m_RNormals = nullptr;
|
||||
m_RNormals = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] unlinkNode() did not find its target" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#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 SGFACESET::unlinkChildNode( const SGNODE* aNode )
|
||||
{
|
||||
unlinkNode( aNode, true );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGFACESET::unlinkRefNode( const SGNODE* aNode )
|
||||
{
|
||||
unlinkNode( aNode, false );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool SGFACESET::addNode( SGNODE* aNode, bool isChild )
|
||||
{
|
||||
wxCHECK( aNode, false );
|
||||
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;
|
||||
}
|
||||
|
||||
valid = false;
|
||||
validated = false;
|
||||
@@ -285,8 +310,12 @@ bool SGFACESET::addNode( SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( aNode != m_Colors && aNode != m_RColors )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] assigning multiple Colors nodes" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] assigning multiple Colors nodes";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -314,8 +343,12 @@ bool SGFACESET::addNode( SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( aNode != m_Coords && aNode != m_RCoords )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] assigning multiple Colors nodes" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] assigning multiple Coords nodes";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -343,8 +376,12 @@ bool SGFACESET::addNode( SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( aNode != m_Normals && aNode != m_RNormals )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] assigning multiple Normals nodes" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] assigning multiple Normals nodes";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -372,9 +409,12 @@ bool SGFACESET::addNode( SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( aNode != m_CoordIndices )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [BUG] assigning multiple CoordIndex nodes" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] assigning multiple CoordIndex nodes";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -388,11 +428,16 @@ bool SGFACESET::addNode( SGNODE* aNode, bool isChild )
|
||||
return true;
|
||||
}
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] object type '%s' is not a valid type for "
|
||||
"this object '%d'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aNode->GetName(),
|
||||
aNode->GetNodeType() );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] object '" << aNode->GetName();
|
||||
ostr << "' (type " << aNode->GetNodeType();
|
||||
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;
|
||||
}
|
||||
@@ -432,12 +477,15 @@ void SGFACESET::ReNameNodes( void )
|
||||
// rename all Normals and Indices
|
||||
if( m_Normals )
|
||||
m_Normals->ReNameNodes();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGFACESET::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
{
|
||||
if( ( nullptr == m_Coords && nullptr == m_RCoords ) || ( nullptr == m_CoordIndices ) )
|
||||
if( ( NULL == m_Coords && NULL == m_RCoords )
|
||||
|| ( NULL == m_CoordIndices ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -492,16 +540,26 @@ bool SGFACESET::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
|
||||
bool SGFACESET::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( nullptr == parentNode )
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
wxCHECK( m_Parent, false );
|
||||
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( nullptr != np->GetParent() )
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, nullptr ) )
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
@@ -510,24 +568,38 @@ bool SGFACESET::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
return false;
|
||||
}
|
||||
|
||||
wxCHECK( parentNode == m_Parent, 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() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad stream" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#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( nullptr != m_RCoords && !m_RCoords->isWritten() )
|
||||
if( NULL != m_RCoords && !m_RCoords->isWritten() )
|
||||
m_RCoords->SwapParent( this );
|
||||
|
||||
if( nullptr != m_RNormals && !m_RNormals->isWritten() )
|
||||
if( NULL != m_RNormals && !m_RNormals->isWritten() )
|
||||
m_RNormals->SwapParent( this );
|
||||
|
||||
if( nullptr != m_RColors && !m_RColors->isWritten() )
|
||||
if( NULL != m_RColors && !m_RColors->isWritten() )
|
||||
m_RColors->SwapParent( this );
|
||||
|
||||
aFile << "[" << GetName() << "]";
|
||||
@@ -539,35 +611,35 @@ bool SGFACESET::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
items[i] = 0;
|
||||
|
||||
i = 0;
|
||||
if( nullptr != m_Coords )
|
||||
if( NULL != m_Coords )
|
||||
items[i] = true;
|
||||
|
||||
++i;
|
||||
if( nullptr != m_RCoords )
|
||||
if( NULL != m_RCoords )
|
||||
items[i] = true;
|
||||
|
||||
++i;
|
||||
if( nullptr != m_CoordIndices )
|
||||
if( NULL != m_CoordIndices )
|
||||
items[i] = true;
|
||||
|
||||
++i;
|
||||
if( nullptr != m_Normals )
|
||||
if( NULL != m_Normals )
|
||||
items[i] = true;
|
||||
|
||||
++i;
|
||||
if( nullptr != m_RNormals )
|
||||
if( NULL != m_RNormals )
|
||||
items[i] = true;
|
||||
|
||||
++i;
|
||||
if( nullptr != m_Colors )
|
||||
if( NULL != m_Colors )
|
||||
items[i] = true;
|
||||
|
||||
++i;
|
||||
if( nullptr != m_RColors )
|
||||
if( NULL != m_RColors )
|
||||
items[i] = true;
|
||||
|
||||
for( int jj = 0; jj < NITEMS; ++jj )
|
||||
aFile.write( (char*) &items[jj], sizeof( bool ) );
|
||||
aFile.write( (char*)&items[jj], sizeof(bool) );
|
||||
|
||||
if( items[0] )
|
||||
m_Coords->WriteCache( aFile, this );
|
||||
@@ -600,11 +672,16 @@ bool SGFACESET::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
|
||||
bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( m_Coords || m_RCoords || m_CoordIndices || m_Colors || m_RColors || m_Normals
|
||||
|| m_RNormals )
|
||||
if( m_Coords || m_RCoords || m_CoordIndices
|
||||
|| m_Colors || m_RColors
|
||||
|| m_Normals || m_RNormals )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] non-empty node" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#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;
|
||||
}
|
||||
@@ -613,14 +690,18 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
bool items[NITEMS];
|
||||
|
||||
for( int i = 0; i < NITEMS; ++i )
|
||||
aFile.read( (char*) &items[i], sizeof( bool ) );
|
||||
aFile.read( (char*)&items[i], sizeof(bool) );
|
||||
|
||||
if( ( items[0] && items[1] ) || ( items[3] && items[4] ) || ( items[5] && items[6] ) )
|
||||
if( ( items[0] && items[1] ) || ( items[3] && items[4] )
|
||||
|| ( items[5] && items[6] ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; multiple item definitions "
|
||||
"at position %d" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<int>( aFile.tellg() ) );
|
||||
#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;
|
||||
}
|
||||
@@ -631,10 +712,13 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_COORDS != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad child coords tag at "
|
||||
"position %d" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<int>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad child coords tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -644,10 +728,13 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !m_Coords->ReadCache( aFile, this ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; corrupt data while "
|
||||
"reading coords '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data while reading coords '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -657,10 +744,13 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_COORDS != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad ref coords tag at "
|
||||
"position %d" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<int>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad ref coords tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -669,20 +759,26 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !np )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; cannot find ref "
|
||||
"coords '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: cannot find ref coords '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_COORDS != np->GetNodeType() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; type is not SGCOORDS "
|
||||
"'%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: type is not SGCOORDS '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -695,10 +791,13 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_COORDINDEX != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad coord index tag at "
|
||||
"position %d" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<int>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad coord index tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -708,10 +807,13 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !m_CoordIndices->ReadCache( aFile, this ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data while reading coord "
|
||||
"index '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data while reading coord index '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -721,10 +823,13 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_NORMALS != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad child normals tag "
|
||||
"at position %d" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<int>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad child normals tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -734,10 +839,13 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !m_Normals->ReadCache( aFile, this ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data while reading normals "
|
||||
"'%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data while reading normals '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -747,10 +855,13 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_NORMALS != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad ref normals tag at "
|
||||
"position %d" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<int>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad ref normals tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -759,19 +870,26 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !np )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt: cannot find ref normals "
|
||||
"'%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: cannot find ref normals '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_NORMALS != np->GetNodeType() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt: type is not SGNORMALS '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: type is not SGNORMALS '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -784,10 +902,13 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_COLORS != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad child colors tag "
|
||||
"at position %d" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<int>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad child colors tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -797,10 +918,13 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !m_Colors->ReadCache( aFile, this ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data while reading colors "
|
||||
"'%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data while reading colors '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -810,10 +934,13 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_COLORS != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad ref colors tag at "
|
||||
"position %d" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<int>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad ref colors tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -822,20 +949,26 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !np )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: cannot find ref colors "
|
||||
"'%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: cannot find ref colors '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_COLORS != np->GetNodeType() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: type is not SGCOLORS "
|
||||
"'%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: type is not SGCOLORS '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -858,14 +991,16 @@ bool SGFACESET::validate( void )
|
||||
return valid;
|
||||
|
||||
// ensure we have at least coordinates and their normals
|
||||
if( ( nullptr == m_Coords && nullptr == m_RCoords )
|
||||
|| ( nullptr == m_Normals && nullptr == m_RNormals )
|
||||
|| ( nullptr == m_CoordIndices ) )
|
||||
if( (NULL == m_Coords && NULL == m_RCoords)
|
||||
|| (NULL == m_Normals && NULL == m_RNormals)
|
||||
|| (NULL == m_CoordIndices) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad model; no vertices, vertex indices, "
|
||||
"or normals" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad model; no vertices, vertex indices, or normals";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
validated = true;
|
||||
valid = false;
|
||||
return false;
|
||||
@@ -874,18 +1009,21 @@ bool SGFACESET::validate( void )
|
||||
// check that there are >3 vertices
|
||||
SGCOORDS* coords = m_Coords;
|
||||
|
||||
if( nullptr == coords )
|
||||
if( NULL == coords )
|
||||
coords = m_RCoords;
|
||||
|
||||
size_t nCoords = 0;
|
||||
SGPOINT* lCoords = nullptr;
|
||||
SGPOINT* lCoords = NULL;
|
||||
coords->GetCoordsList( nCoords, lCoords );
|
||||
|
||||
if( nCoords < 3 )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad model; fewer than 3 vertices" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad model; fewer than 3 vertices";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
validated = true;
|
||||
valid = false;
|
||||
return false;
|
||||
@@ -893,15 +1031,17 @@ bool SGFACESET::validate( void )
|
||||
|
||||
// check that nVertices is divisible by 3 (facets are triangles)
|
||||
size_t nCIdx = 0;
|
||||
int* lCIdx = nullptr;
|
||||
int* lCIdx = NULL;
|
||||
m_CoordIndices->GetIndices( nCIdx, lCIdx );
|
||||
|
||||
if( nCIdx < 3 || ( nCIdx % 3 > 0 ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad model; no vertex indices or not "
|
||||
"multiple of 3" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad model; no vertex indices or not multiple of 3";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
validated = true;
|
||||
valid = false;
|
||||
return false;
|
||||
@@ -912,10 +1052,12 @@ bool SGFACESET::validate( void )
|
||||
{
|
||||
if( lCIdx[i] < 0 || lCIdx[i] >= (int)nCoords )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad model; vertex index out of "
|
||||
"bounds" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad model; vertex index out of bounds";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
validated = true;
|
||||
valid = false;
|
||||
return false;
|
||||
@@ -924,22 +1066,23 @@ bool SGFACESET::validate( void )
|
||||
|
||||
// check that there are as many normals as vertices
|
||||
size_t nNorms = 0;
|
||||
SGVECTOR* lNorms = nullptr;
|
||||
SGVECTOR* lNorms = NULL;
|
||||
SGNORMALS* pNorms = m_Normals;
|
||||
|
||||
if( nullptr == pNorms )
|
||||
if( NULL == pNorms )
|
||||
pNorms = m_RNormals;
|
||||
|
||||
pNorms->GetNormalList( nNorms, lNorms );
|
||||
|
||||
if( nNorms != nCoords )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad model; number of normals (%ul) does "
|
||||
"not match number of vertices (%ul)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( nNorms ),
|
||||
static_cast<unsigned long>( nCoords ) );
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad model; number of normals (" << nNorms;
|
||||
ostr << ") does not match number of vertices (" << nCoords << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
validated = true;
|
||||
valid = false;
|
||||
return false;
|
||||
@@ -948,14 +1091,14 @@ bool SGFACESET::validate( void )
|
||||
// if there are colors then ensure there are as many colors as vertices
|
||||
SGCOLORS* pColors = m_Colors;
|
||||
|
||||
if( nullptr == pColors )
|
||||
if( NULL == pColors )
|
||||
pColors = m_RColors;
|
||||
|
||||
if( nullptr != pColors )
|
||||
if( NULL != pColors )
|
||||
{
|
||||
// we must have at least as many colors as vertices
|
||||
size_t nColor = 0;
|
||||
SGCOLOR* pColor = nullptr;
|
||||
SGCOLOR* pColor = NULL;
|
||||
pColors->GetColorList( nColor, pColor );
|
||||
}
|
||||
|
||||
@@ -969,6 +1112,8 @@ void SGFACESET::GatherCoordIndices( std::vector< int >& aIndexList )
|
||||
{
|
||||
if( m_CoordIndices )
|
||||
m_CoordIndices->GatherCoordIndices( aIndexList );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -979,7 +1124,7 @@ bool SGFACESET::CalcNormals( SGNODE** aPtr )
|
||||
if( m_RCoords )
|
||||
coords = m_RCoords;
|
||||
|
||||
if( nullptr == coords || coords->coords.empty() )
|
||||
if( NULL == coords || coords->coords.empty() )
|
||||
return false;
|
||||
|
||||
if( m_Normals && !m_Normals->norms.empty( ) )
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2020 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
|
||||
@@ -24,6 +23,7 @@
|
||||
|
||||
/**
|
||||
* @file sg_faceset.h
|
||||
* defines an indexed face set for a scenegraph
|
||||
*/
|
||||
|
||||
|
||||
@@ -40,18 +40,38 @@ class SGNORMALS;
|
||||
class SGCOLORINDEX;
|
||||
class SGCOORDINDEX;
|
||||
|
||||
/**
|
||||
* Define an indexed face set for a scenegraph.
|
||||
*/
|
||||
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;
|
||||
SGNODE* FindNode( const char *aNodeName, const SGNODE *aCaller ) override;
|
||||
bool AddRefNode( SGNODE* aNode ) override;
|
||||
bool AddChildNode( SGNODE* aNode ) override;
|
||||
|
||||
@@ -64,34 +84,11 @@ public:
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
|
||||
/**
|
||||
* Add all internal coordinate indices to the given list in preparation for a normals
|
||||
* calculation.
|
||||
* Function GatherCoordIndices
|
||||
* adds all internal coordinate indices to the given list
|
||||
* in preparation for a normals calculation
|
||||
*/
|
||||
void GatherCoordIndices( std::vector< int >& aIndexList );
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
|
||||
// validate the data held by this face set
|
||||
bool validate( void );
|
||||
|
||||
// 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;
|
||||
|
||||
private:
|
||||
bool valid;
|
||||
bool validated;
|
||||
void unlinkNode( const SGNODE* aNode, bool isChild );
|
||||
bool addNode( SGNODE* aNode, bool isChild );
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2020 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
|
||||
@@ -34,6 +33,7 @@
|
||||
#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 )
|
||||
@@ -49,9 +49,10 @@ void S3D::FormatFloat( std::string& result, double value )
|
||||
|
||||
result = out.str();
|
||||
|
||||
size_t p = result.find( '.' );
|
||||
size_t p = result.find( "." );
|
||||
|
||||
// trim trailing 0 if appropriate
|
||||
|
||||
if( std::string::npos == p )
|
||||
return;
|
||||
|
||||
@@ -59,26 +60,28 @@ void S3D::FormatFloat( std::string& result, double value )
|
||||
|
||||
if( std::string::npos == p )
|
||||
{
|
||||
while( '0' == *( result.rbegin() ) )
|
||||
while( '0' == *(result.rbegin()) )
|
||||
result.erase( result.size() - 1 );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if( '0' != result.at( p - 1 ) )
|
||||
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() ) )
|
||||
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;
|
||||
@@ -97,9 +100,11 @@ void S3D::FormatOrientation( std::string& result, const SGVECTOR& axis, double r
|
||||
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 );
|
||||
@@ -112,9 +117,12 @@ void S3D::FormatPoint( std::string& result, const SGPOINT& point )
|
||||
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;
|
||||
@@ -129,9 +137,12 @@ void S3D::FormatVector( std::string& result, const SGVECTOR& aVector )
|
||||
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;
|
||||
@@ -146,14 +157,16 @@ void S3D::FormatColor( std::string& result, const SGCOLOR& aColor )
|
||||
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 ) );
|
||||
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;
|
||||
@@ -166,9 +179,9 @@ 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 ) );
|
||||
aFile.write( (char*)&x, sizeof(double) );
|
||||
aFile.write( (char*)&y, sizeof(double) );
|
||||
aFile.write( (char*)&z, sizeof(double) );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
@@ -181,9 +194,9 @@ 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 ) );
|
||||
aFile.write( (char*)&r, sizeof(float) );
|
||||
aFile.write( (char*)&g, sizeof(float) );
|
||||
aFile.write( (char*)&b, sizeof(float) );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
@@ -199,10 +212,13 @@ S3D::SGTYPES S3D::ReadTag( std::istream& aFile, std::string& aName )
|
||||
|
||||
if( '[' != schar )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; missing left bracket at "
|
||||
"position %d" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<int>( aFile.tellg() ) );
|
||||
#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;
|
||||
}
|
||||
@@ -218,9 +234,12 @@ S3D::SGTYPES S3D::ReadTag( std::istream& aFile, std::string& aName )
|
||||
|
||||
if( schar != ']' )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; could not find right "
|
||||
"bracket" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#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;
|
||||
}
|
||||
@@ -230,9 +249,13 @@ S3D::SGTYPES S3D::ReadTag( std::istream& aFile, std::string& aName )
|
||||
|
||||
if( std::string::npos == upos )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; no underscore in name '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#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;
|
||||
}
|
||||
@@ -256,9 +279,15 @@ S3D::SGTYPES S3D::ReadTag( std::istream& aFile, std::string& aName )
|
||||
return types[i];
|
||||
}
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; no node type matching '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#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;
|
||||
}
|
||||
@@ -266,9 +295,9 @@ S3D::SGTYPES S3D::ReadTag( std::istream& aFile, std::string& aName )
|
||||
|
||||
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 ) );
|
||||
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;
|
||||
@@ -280,9 +309,9 @@ bool S3D::ReadPoint( std::istream& aFile, SGPOINT& aPoint )
|
||||
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 ) );
|
||||
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() )
|
||||
@@ -295,9 +324,9 @@ bool S3D::ReadVector( std::istream& aFile, SGVECTOR& aVector )
|
||||
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 ) );
|
||||
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() )
|
||||
@@ -307,7 +336,7 @@ bool S3D::ReadColor( std::istream& aFile, SGCOLOR& aColor )
|
||||
}
|
||||
|
||||
|
||||
bool S3D::degenerate( glm::dvec3* pts ) noexcept
|
||||
bool S3D::degenerate( glm::dvec3* pts )
|
||||
{
|
||||
double dx, dy, dz;
|
||||
|
||||
@@ -347,19 +376,24 @@ static void calcTriad( glm::dvec3* pts, glm::dvec3& tri )
|
||||
|
||||
// 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 )
|
||||
bool S3D::CalcTriangleNormals( std::vector< SGPOINT > coords,
|
||||
std::vector< int >& index, std::vector< SGVECTOR >& norms )
|
||||
{
|
||||
size_t vsize = coords.size();
|
||||
|
||||
if( vsize < 3 )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] invalid vertex set (fewer than 3 "
|
||||
"vertices)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#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;
|
||||
}
|
||||
@@ -368,16 +402,24 @@ bool S3D::CalcTriangleNormals( std::vector< SGPOINT > coords, std::vector< int >
|
||||
|
||||
if( 0 != isize % 3 || index.empty() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] invalid index set (not multiple of 3)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#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() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] normals set is not empty" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#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;
|
||||
}
|
||||
@@ -393,14 +435,15 @@ bool S3D::CalcTriangleNormals( std::vector< SGPOINT > coords, std::vector< int >
|
||||
p2 = index[i++];
|
||||
p3 = index[i++];
|
||||
|
||||
if( p1 < 0 || p1 >= (int)vsize || p2 < 0 || p2 >= (int)vsize || p3 < 0 || p3 >= (int)vsize )
|
||||
if( p1 < 0 || p1 >= (int)vsize || p2 < 0 || p2 >= (int)vsize ||
|
||||
p3 < 0 || p3 >= (int)vsize )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] invalid index set; index out of bounds";
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s\n" ), ostr.str().c_str() );
|
||||
#endif
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -460,7 +503,7 @@ bool S3D::CalcTriangleNormals( std::vector< SGPOINT > coords, std::vector< int >
|
||||
// assign any skipped coordinates a normal of (0,0,1)
|
||||
while( item > idx )
|
||||
{
|
||||
norms.emplace_back( 0, 0, 1 );
|
||||
norms.push_back( SGVECTOR( 0, 0, 1 ) );
|
||||
++idx;
|
||||
}
|
||||
|
||||
@@ -474,7 +517,7 @@ bool S3D::CalcTriangleNormals( std::vector< SGPOINT > coords, std::vector< int >
|
||||
++sT;
|
||||
}
|
||||
|
||||
norms.emplace_back( norm.x, norm.y, norm.z );
|
||||
norms.push_back( SGVECTOR( norm.x, norm.y, norm.z ) );
|
||||
|
||||
++idx;
|
||||
++sM;
|
||||
@@ -482,9 +525,12 @@ bool S3D::CalcTriangleNormals( std::vector< SGPOINT > coords, std::vector< int >
|
||||
|
||||
if( norms.size() != coords.size() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] number of normals does not equal number "
|
||||
"of vertices" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#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;
|
||||
}
|
||||
|
||||
+121
-147
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2020 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
|
||||
@@ -24,10 +23,10 @@
|
||||
|
||||
/**
|
||||
* @file sg_helpers.h
|
||||
*
|
||||
* Define a number of macros 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.
|
||||
* 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
|
||||
@@ -45,182 +44,151 @@ 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(); \
|
||||
#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( nullptr, false ); \
|
||||
delete *sL; \
|
||||
++sL; \
|
||||
} \
|
||||
aList.clear(); \
|
||||
#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 )
|
||||
#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( nullptr != 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( nullptr == aNode->GetParent() ) { \
|
||||
#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 )
|
||||
} */ \
|
||||
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 = nullptr; \
|
||||
while( sLA != eLA ) \
|
||||
{ \
|
||||
if( (SGNODE*) *sLA != aCallingNode ) \
|
||||
{ \
|
||||
psg = (SGNODE*) ( *sLA )->FindNode( aName, this ); \
|
||||
if( nullptr != psg ) \
|
||||
return psg; \
|
||||
} \
|
||||
++sLA; \
|
||||
} \
|
||||
} while( 0 )
|
||||
|
||||
#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 ) noexcept;
|
||||
bool degenerate( glm::dvec3* pts );
|
||||
|
||||
//
|
||||
// Normals calculations from triangles
|
||||
//
|
||||
|
||||
/*
|
||||
* Take an array of 3D coordinates and its corresponding index set and calculates
|
||||
* the normals assuming that indices are given in CCW order.
|
||||
* 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.
|
||||
*
|
||||
* Care must be taken in using this function to ensure that:
|
||||
* -# 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.
|
||||
* -# 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.
|
||||
* @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 );
|
||||
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 );
|
||||
@@ -250,13 +218,19 @@ namespace S3D
|
||||
// write out an RGB color
|
||||
bool WriteColor( std::ostream& aFile, const SGCOLOR& aColor );
|
||||
|
||||
//
|
||||
// Cache related READ functions
|
||||
//
|
||||
|
||||
/**
|
||||
* Read the text tag of a binary cache file which is the NodeTag and unique ID number combined.
|
||||
* 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.
|
||||
* @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 );
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2020 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
|
||||
@@ -31,27 +30,33 @@
|
||||
|
||||
SGINDEX::SGINDEX( SGNODE* aParent ) : SGNODE( aParent )
|
||||
{
|
||||
if( nullptr != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] inappropriate parent to SGINDEX (type "
|
||||
"'%d')" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeType() );
|
||||
#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( nullptr != m_Parent )
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
@@ -60,14 +65,14 @@ bool SGINDEX::SetParent( SGNODE* aParent, bool notify )
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
if( nullptr == aParent )
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a SGFACESET may be parent to a SGINDEX and derived types
|
||||
if( nullptr != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
@@ -79,45 +84,65 @@ bool SGINDEX::SetParent( SGNODE* aParent, bool notify )
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGINDEX::FindNode(const char *aNodeName, const SGNODE *aCaller) noexcept
|
||||
SGNODE* SGINDEX::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( nullptr == aNodeName || 0 == aNodeName[0] )
|
||||
return nullptr;
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void SGINDEX::unlinkChildNode( const SGNODE* aCaller ) noexcept
|
||||
void SGINDEX::unlinkChildNode( const SGNODE* aCaller )
|
||||
{
|
||||
// Node should have no children or refs.
|
||||
wxCHECK( false, /* void */ );
|
||||
#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 ) noexcept
|
||||
void SGINDEX::unlinkRefNode( const SGNODE* aCaller )
|
||||
{
|
||||
// Node should have no children or refs.
|
||||
wxCHECK( false, /* void */ );
|
||||
#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 ) noexcept
|
||||
bool SGINDEX::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
// Node should have no children or refs.
|
||||
wxCHECK( false, false );
|
||||
#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 ) noexcept
|
||||
bool SGINDEX::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
// Node should have no children or refs.
|
||||
wxCHECK( false, false );
|
||||
#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;
|
||||
}
|
||||
@@ -128,7 +153,7 @@ bool SGINDEX::GetIndices( size_t& nIndices, int*& aIndexList )
|
||||
if( index.empty() )
|
||||
{
|
||||
nIndices = 0;
|
||||
aIndexList = nullptr;
|
||||
aIndexList = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -142,7 +167,7 @@ void SGINDEX::SetIndices( size_t nIndices, int* aIndexList )
|
||||
{
|
||||
index.clear();
|
||||
|
||||
if( 0 == nIndices || nullptr == aIndexList )
|
||||
if( 0 == nIndices || NULL == aIndexList )
|
||||
return;
|
||||
|
||||
for( size_t i = 0; i < nIndices; ++i )
|
||||
@@ -155,6 +180,7 @@ void SGINDEX::SetIndices( size_t nIndices, int* aIndexList )
|
||||
void SGINDEX::AddIndex( int aIndex )
|
||||
{
|
||||
index.push_back( aIndex );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -184,8 +210,17 @@ bool SGINDEX::writeCoordIndex( std::ostream& aFile )
|
||||
{
|
||||
size_t n = index.size();
|
||||
|
||||
wxCHECK_MSG( n % 3 == 0, false, wxT( "Coordinate index is not divisible by three (violates "
|
||||
"triangle constraint)" ) );
|
||||
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 ";
|
||||
|
||||
@@ -261,16 +296,26 @@ bool SGINDEX::writeIndexList( std::ostream& aFile )
|
||||
|
||||
bool SGINDEX::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( nullptr == parentNode )
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
wxCHECK( m_Parent, false );
|
||||
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( nullptr != np->GetParent() )
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, nullptr ) )
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
@@ -279,12 +324,26 @@ bool SGINDEX::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
return false;
|
||||
}
|
||||
|
||||
wxCHECK( parentNode == m_Parent, 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() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad stream" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#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;
|
||||
}
|
||||
@@ -306,7 +365,17 @@ bool SGINDEX::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
|
||||
bool SGINDEX::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
wxCHECK( index.empty(), false );
|
||||
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) );
|
||||
@@ -317,7 +386,7 @@ bool SGINDEX::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
for( size_t i = 0; i < npts; ++i )
|
||||
{
|
||||
aFile.read( (char*) &tmp, sizeof( int ) );
|
||||
aFile.read( (char*)&tmp, sizeof(int) );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2020 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
|
||||
@@ -24,6 +23,7 @@
|
||||
|
||||
/**
|
||||
* @file sg_index.h
|
||||
* defines a generic Index interface for a scenegraph object
|
||||
*/
|
||||
|
||||
#ifndef SG_INDEX_H
|
||||
@@ -32,59 +32,8 @@
|
||||
#include <vector>
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
|
||||
/**
|
||||
* Define a generic index interface for a scenegraph object.
|
||||
*/
|
||||
class SGINDEX : public SGNODE
|
||||
{
|
||||
public:
|
||||
SGINDEX( SGNODE* aParent );
|
||||
virtual ~SGINDEX();
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
|
||||
SGNODE* FindNode(const char* aNodeName, const SGNODE* aCaller) noexcept override;
|
||||
bool AddRefNode( SGNODE* aNode ) noexcept override;
|
||||
bool AddChildNode( SGNODE* aNode ) noexcept override;
|
||||
|
||||
void unlinkChildNode( const SGNODE* aCaller ) noexcept override;
|
||||
void unlinkRefNode( const SGNODE* aCaller ) noexcept override;
|
||||
|
||||
/**
|
||||
* Retrieve 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 will hold the number of indices in the list.
|
||||
* @param aIndexList 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 );
|
||||
|
||||
/**
|
||||
* Set the number of indices and creates a copy of the given index data.
|
||||
*
|
||||
* @param nIndices the number of indices to be stored.
|
||||
* @param aIndexList the index data.
|
||||
*/
|
||||
void SetIndices( size_t nIndices, int* aIndexList );
|
||||
|
||||
|
||||
/**
|
||||
* Add 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;
|
||||
|
||||
protected:
|
||||
bool writeCoordIndex( std::ostream& aFile );
|
||||
bool writeColorIndex( std::ostream& aFile );
|
||||
@@ -93,6 +42,56 @@ protected:
|
||||
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
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* 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) 2020 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
|
||||
@@ -32,7 +31,6 @@
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
#include "plugins/3dapi/c3dmodel.h"
|
||||
|
||||
|
||||
static const std::string node_names[S3D::SGTYPE_END + 1] = {
|
||||
"TXFM",
|
||||
"APP",
|
||||
@@ -50,7 +48,7 @@ static const std::string node_names[S3D::SGTYPE_END + 1] = {
|
||||
static unsigned int node_counts[S3D::SGTYPE_END] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 };
|
||||
|
||||
|
||||
char const* S3D::GetNodeTypeName( S3D::SGTYPES aType ) noexcept
|
||||
char const* S3D::GetNodeTypeName( S3D::SGTYPES aType )
|
||||
{
|
||||
return node_names[aType].c_str();
|
||||
}
|
||||
@@ -70,15 +68,19 @@ static void getNodeName( S3D::SGTYPES nodeType, std::string& aName )
|
||||
std::ostringstream ostr;
|
||||
ostr << node_names[nodeType] << "_" << seqNum;
|
||||
aName = ostr.str();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGNODE::SGNODE( SGNODE* aParent )
|
||||
{
|
||||
m_Parent = aParent;
|
||||
m_Association = nullptr;
|
||||
m_Association = NULL;
|
||||
m_written = false;
|
||||
m_SGtype = S3D::SGTYPE_END;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +90,7 @@ SGNODE::~SGNODE()
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
if( m_Association )
|
||||
*m_Association = nullptr;
|
||||
*m_Association = NULL;
|
||||
|
||||
std::list< SGNODE* >::iterator sBP = m_BackPointers.begin();
|
||||
std::list< SGNODE* >::iterator eBP = m_BackPointers.end();
|
||||
@@ -98,16 +100,18 @@ SGNODE::~SGNODE()
|
||||
(*sBP)->unlinkRefNode( this );
|
||||
++sBP;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
S3D::SGTYPES SGNODE::GetNodeType( void ) const noexcept
|
||||
S3D::SGTYPES SGNODE::GetNodeType( void ) const
|
||||
{
|
||||
return m_SGtype;
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGNODE::GetParent( void ) const noexcept
|
||||
SGNODE* SGNODE::GetParent( void ) const
|
||||
{
|
||||
return m_Parent;
|
||||
}
|
||||
@@ -118,10 +122,10 @@ bool SGNODE::SwapParent( SGNODE* aNewParent )
|
||||
if( aNewParent == m_Parent )
|
||||
return true;
|
||||
|
||||
if( nullptr == aNewParent )
|
||||
if( NULL == aNewParent )
|
||||
return false;
|
||||
|
||||
if( nullptr == m_Parent )
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
if( aNewParent->AddChildNode( this ) )
|
||||
return true;
|
||||
@@ -134,7 +138,7 @@ bool SGNODE::SwapParent( SGNODE* aNewParent )
|
||||
|
||||
SGNODE* oldParent = m_Parent;
|
||||
m_Parent->unlinkChildNode( this );
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
aNewParent->unlinkRefNode( this );
|
||||
aNewParent->AddChildNode( this );
|
||||
oldParent->AddRefNode( this );
|
||||
@@ -152,16 +156,18 @@ const char* SGNODE::GetName( void )
|
||||
}
|
||||
|
||||
|
||||
void SGNODE::SetName( const char* aName )
|
||||
void SGNODE::SetName( const char *aName )
|
||||
{
|
||||
if( nullptr == aName || 0 == aName[0] )
|
||||
if( NULL == aName || 0 == aName[0] )
|
||||
getNodeName( m_SGtype, m_Name );
|
||||
else
|
||||
m_Name = aName;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const char* SGNODE::GetNodeTypeName( S3D::SGTYPES aNodeType ) const noexcept
|
||||
const char * SGNODE::GetNodeTypeName( S3D::SGTYPES aNodeType ) const
|
||||
{
|
||||
return node_names[aNodeType].c_str();
|
||||
}
|
||||
@@ -169,7 +175,7 @@ const char* SGNODE::GetNodeTypeName( S3D::SGTYPES aNodeType ) const noexcept
|
||||
|
||||
void SGNODE::addNodeRef( SGNODE* aNode )
|
||||
{
|
||||
if( nullptr == aNode )
|
||||
if( NULL == aNode )
|
||||
return;
|
||||
|
||||
std::list< SGNODE* >::iterator np =
|
||||
@@ -179,12 +185,13 @@ void SGNODE::addNodeRef( SGNODE* aNode )
|
||||
return;
|
||||
|
||||
m_BackPointers.push_back( aNode );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGNODE::delNodeRef( const SGNODE* aNode )
|
||||
{
|
||||
if( nullptr == aNode )
|
||||
if( NULL == aNode )
|
||||
return;
|
||||
|
||||
std::list< SGNODE* >::iterator np =
|
||||
@@ -196,49 +203,110 @@ void SGNODE::delNodeRef( const SGNODE* aNode )
|
||||
return;
|
||||
}
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] delNodeRef() did not find its target, this "
|
||||
"node type %d, referenced node type %d" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
m_SGtype,
|
||||
aNode->GetNodeType() );
|
||||
#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 ) noexcept
|
||||
void SGNODE::AssociateWrapper( SGNODE** aWrapperRef )
|
||||
{
|
||||
wxCHECK( aWrapperRef && *aWrapperRef == this, /* void */ );
|
||||
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 = nullptr;
|
||||
*m_Association = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [WARNING] association being broken with "
|
||||
"previous wrapper" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#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 ) noexcept
|
||||
void SGNODE::DisassociateWrapper( SGNODE** aWrapperRef )
|
||||
{
|
||||
if( !m_Association )
|
||||
return;
|
||||
|
||||
wxCHECK( aWrapperRef, /* void */ );
|
||||
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
|
||||
|
||||
wxCHECK( *aWrapperRef == *m_Association && aWrapperRef == m_Association, /* void */ );
|
||||
return;
|
||||
}
|
||||
|
||||
m_Association = nullptr;
|
||||
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 ) noexcept
|
||||
void SGNODE::ResetNodeIndex( void )
|
||||
{
|
||||
for( int i = 0; i < (int)S3D::SGTYPE_END; ++i )
|
||||
node_counts[i] = 1;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -246,7 +314,28 @@ bool S3D::GetMatIndex( MATLIST& aList, SGNODE* aNode, int& aIndex )
|
||||
{
|
||||
aIndex = 0;
|
||||
|
||||
wxCHECK( aNode && S3D::SGTYPE_APPEARANCE == aNode->GetNodeType(), false );
|
||||
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;
|
||||
|
||||
@@ -273,74 +362,78 @@ void S3D::INIT_SMATERIAL( SMATERIAL& aMaterial )
|
||||
}
|
||||
|
||||
|
||||
void S3D::INIT_SMESH( SMESH& aMesh ) noexcept
|
||||
void S3D::INIT_SMESH( SMESH& aMesh )
|
||||
{
|
||||
aMesh = {};
|
||||
}
|
||||
|
||||
|
||||
void S3D::INIT_S3DMODEL( S3DMODEL& aModel ) noexcept
|
||||
void S3D::INIT_S3DMODEL( S3DMODEL& aModel )
|
||||
{
|
||||
aModel = {};
|
||||
}
|
||||
|
||||
|
||||
void S3D::FREE_SMESH( SMESH& aMesh ) noexcept
|
||||
void S3D::FREE_SMESH( SMESH& aMesh)
|
||||
{
|
||||
if( nullptr != aMesh.m_Positions )
|
||||
if( NULL != aMesh.m_Positions )
|
||||
{
|
||||
delete [] aMesh.m_Positions;
|
||||
aMesh.m_Positions = nullptr;
|
||||
aMesh.m_Positions = NULL;
|
||||
}
|
||||
|
||||
if( nullptr != aMesh.m_Normals )
|
||||
if( NULL != aMesh.m_Normals )
|
||||
{
|
||||
delete [] aMesh.m_Normals;
|
||||
aMesh.m_Normals = nullptr;
|
||||
aMesh.m_Normals = NULL;
|
||||
}
|
||||
|
||||
if( nullptr != aMesh.m_Texcoords )
|
||||
if( NULL != aMesh.m_Texcoords )
|
||||
{
|
||||
delete [] aMesh.m_Texcoords;
|
||||
aMesh.m_Texcoords = nullptr;
|
||||
aMesh.m_Texcoords = NULL;
|
||||
}
|
||||
|
||||
if( nullptr != aMesh.m_Color )
|
||||
if( NULL != aMesh.m_Color )
|
||||
{
|
||||
delete [] aMesh.m_Color;
|
||||
aMesh.m_Color = nullptr;
|
||||
aMesh.m_Color = NULL;
|
||||
}
|
||||
|
||||
if( nullptr != aMesh.m_FaceIdx )
|
||||
if( NULL != aMesh.m_FaceIdx )
|
||||
{
|
||||
delete [] aMesh.m_FaceIdx;
|
||||
aMesh.m_FaceIdx = nullptr;
|
||||
aMesh.m_FaceIdx = NULL;
|
||||
}
|
||||
|
||||
aMesh.m_VertexSize = 0;
|
||||
aMesh.m_FaceIdxSize = 0;
|
||||
aMesh.m_MaterialIdx = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D::FREE_S3DMODEL( S3DMODEL& aModel )
|
||||
{
|
||||
if( nullptr != aModel.m_Materials )
|
||||
if( NULL != aModel.m_Materials )
|
||||
{
|
||||
delete [] aModel.m_Materials;
|
||||
aModel.m_Materials = nullptr;
|
||||
aModel.m_Materials = NULL;
|
||||
}
|
||||
|
||||
aModel.m_MaterialsSize = 0;
|
||||
|
||||
if( nullptr != aModel.m_Meshes )
|
||||
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 = nullptr;
|
||||
aModel.m_Meshes = NULL;
|
||||
}
|
||||
|
||||
aModel.m_MeshesSize = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
+121
-107
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2020 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
|
||||
@@ -24,6 +23,7 @@
|
||||
|
||||
/**
|
||||
* @file sg_node.h
|
||||
* defines the base class of the intermediate scene graph NODE
|
||||
*/
|
||||
|
||||
|
||||
@@ -47,9 +47,10 @@ class SGAPPEARANCE;
|
||||
namespace S3D
|
||||
{
|
||||
/**
|
||||
* Return the name of the given type of node
|
||||
* Function GetNodeTypeName
|
||||
* returns the name of the given type of node
|
||||
*/
|
||||
char const* GetNodeTypeName( S3D::SGTYPES aType ) noexcept;
|
||||
char const* GetNodeTypeName( S3D::SGTYPES aType );
|
||||
|
||||
struct MATLIST
|
||||
{
|
||||
@@ -60,67 +61,129 @@ namespace S3D
|
||||
bool GetMatIndex( MATLIST& aList, SGNODE* aNode, int& aIndex );
|
||||
|
||||
void INIT_SMATERIAL( SMATERIAL& aMaterial );
|
||||
void INIT_SMESH( SMESH& aMesh ) noexcept;
|
||||
void INIT_S3DMODEL( S3DMODEL& aModel ) noexcept;
|
||||
void INIT_SMESH( SMESH& aMesh );
|
||||
void INIT_S3DMODEL( S3DMODEL& aModel );
|
||||
|
||||
void FREE_SMESH( SMESH& aMesh) noexcept;
|
||||
void FREE_SMESH( SMESH& aMesh);
|
||||
void FREE_S3DMODEL( S3DMODEL& aModel );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The base class of all Scene Graph nodes.
|
||||
* 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();
|
||||
|
||||
/**
|
||||
* Return the type of this node instance.
|
||||
* Function GetNodeType
|
||||
* returns the type of this node instance
|
||||
*/
|
||||
S3D::SGTYPES GetNodeType( void ) const noexcept;
|
||||
S3D::SGTYPES GetNodeType( void ) const;
|
||||
|
||||
/**
|
||||
* Returns a pointer to the parent SGNODE of this object or NULL if the object has
|
||||
* no parent (ie. top level transform).
|
||||
* 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 noexcept;
|
||||
SGNODE* GetParent( void ) const;
|
||||
|
||||
/**
|
||||
* Set the parent #SGNODE of this object.
|
||||
* 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.
|
||||
* @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;
|
||||
|
||||
/**
|
||||
* Swap the ownership with the given parent.
|
||||
* Function SwapParent
|
||||
* swaps the ownership with the given parent. This operation
|
||||
* may be required when reordering nodes for optimization.
|
||||
*
|
||||
* This operation may be required when reordering nodes for optimization.
|
||||
*
|
||||
* @param aNewParent will become the new parent to the object; it must be the same type
|
||||
* as the parent of this instance.
|
||||
* @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 noexcept;
|
||||
const char * GetNodeTypeName( S3D::SGTYPES aNodeType ) const;
|
||||
|
||||
/**
|
||||
* Search the tree of linked nodes and return a reference to the first node found with
|
||||
* the given name.
|
||||
* 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().
|
||||
*
|
||||
* 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.
|
||||
* @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;
|
||||
|
||||
@@ -129,108 +192,59 @@ public:
|
||||
virtual bool AddChildNode( SGNODE* aNode ) = 0;
|
||||
|
||||
/**
|
||||
* Associate this object with a handle to itself.
|
||||
*
|
||||
* The 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.
|
||||
* 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 ) noexcept;
|
||||
void AssociateWrapper( SGNODE** aWrapperRef );
|
||||
|
||||
/**
|
||||
* Remove the association between an IFSG* wrapper object and this object.
|
||||
* Function DisassociateWrapper
|
||||
* removes the association between an IFSG* wrapper
|
||||
* object and this object.
|
||||
*/
|
||||
void DisassociateWrapper( SGNODE** aWrapperRef ) noexcept;
|
||||
void DisassociateWrapper( SGNODE** aWrapperRef );
|
||||
|
||||
/**
|
||||
* Reset the global SG* node indices in preparation for write operations.
|
||||
* Function ResetNodeIndex
|
||||
* resets the global SG* node indices in preparation for
|
||||
* Write() operations
|
||||
*/
|
||||
void ResetNodeIndex( void ) noexcept;
|
||||
void ResetNodeIndex( void );
|
||||
|
||||
/**
|
||||
* Rename a node and all its child nodes in preparation for write operations.
|
||||
* Function ReNameNodes
|
||||
* renames a node and all its child nodes in preparation for
|
||||
* Write() operations
|
||||
*/
|
||||
virtual void ReNameNodes( void ) = 0;
|
||||
|
||||
/**
|
||||
* Writes this node's data to a VRML file.
|
||||
*
|
||||
* This includes all data of child and referenced nodes.
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Write 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.
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Remove references to an owned child.
|
||||
*
|
||||
* This 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;
|
||||
|
||||
/**
|
||||
* Remove pointers to a referenced node.
|
||||
*
|
||||
* This 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;
|
||||
|
||||
/**
|
||||
* Add a pointer to a node which references this node, but does not own.
|
||||
*
|
||||
* 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 );
|
||||
|
||||
/**
|
||||
* Remove a pointer to a node which references this node, but does not own.
|
||||
*
|
||||
* @param aNode is the node holding a reference to this object.
|
||||
*/
|
||||
void delNodeRef( const SGNODE* aNode );
|
||||
|
||||
/**
|
||||
* Return true if the object had already been written to a cache file or VRML file
|
||||
*
|
||||
* For internal use only.
|
||||
*/
|
||||
bool isWritten( void ) noexcept
|
||||
{
|
||||
return m_written;
|
||||
}
|
||||
|
||||
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 Scene Graph node.
|
||||
std::string m_Name; ///< name to use for referencing the entity by name.
|
||||
bool m_written; ///< Set to true when the object has been written after a ReNameNodes().
|
||||
|
||||
private:
|
||||
SGNODE** m_Association; ///< Handle to the instance held by a wrapper.
|
||||
};
|
||||
|
||||
#endif // SG_NODE_H
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2020 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
|
||||
@@ -34,31 +33,37 @@ SGNORMALS::SGNORMALS( SGNODE* aParent ) : SGNODE( aParent )
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_NORMALS;
|
||||
|
||||
if( nullptr != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] inappropriate parent to SGNORMALS "
|
||||
"(type %d)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeType() );
|
||||
#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( nullptr != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||
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( nullptr != m_Parent )
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
@@ -67,14 +72,14 @@ bool SGNORMALS::SetParent( SGNODE* aParent, bool notify )
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
if( nullptr == aParent )
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a SGFACESET may be parent to a SGNORMALS
|
||||
if( nullptr != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
@@ -86,41 +91,65 @@ bool SGNORMALS::SetParent( SGNODE* aParent, bool notify )
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGNORMALS::FindNode( const char* aNodeName, const SGNODE* aCaller ) noexcept
|
||||
SGNODE* SGNORMALS::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( nullptr == aNodeName || 0 == aNodeName[0] )
|
||||
return nullptr;
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void SGNORMALS::unlinkChildNode( const SGNODE* aCaller ) noexcept
|
||||
void SGNORMALS::unlinkChildNode( const SGNODE* aCaller )
|
||||
{
|
||||
wxCHECK( false, /* void */ );
|
||||
#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 ) noexcept
|
||||
void SGNORMALS::unlinkRefNode( const SGNODE* aCaller )
|
||||
{
|
||||
wxCHECK( false, /* void */ );
|
||||
#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 ) noexcept
|
||||
bool SGNORMALS::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK( false, false );
|
||||
#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 ) noexcept
|
||||
bool SGNORMALS::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK( false, false );
|
||||
#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;
|
||||
}
|
||||
@@ -131,7 +160,7 @@ bool SGNORMALS::GetNormalList( size_t& aListSize, SGVECTOR*& aNormalList )
|
||||
if( norms.empty() )
|
||||
{
|
||||
aListSize = 0;
|
||||
aNormalList = nullptr;
|
||||
aNormalList = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -145,23 +174,27 @@ void SGNORMALS::SetNormalList( size_t aListSize, const SGVECTOR* aNormalList )
|
||||
{
|
||||
norms.clear();
|
||||
|
||||
if( 0 == aListSize || nullptr == aNormalList )
|
||||
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.emplace_back( aXValue, aYValue, aZValue );
|
||||
norms.push_back( SGVECTOR( aXValue, aYValue, aZValue ) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGNORMALS::AddNormal( const SGVECTOR& aNormal )
|
||||
{
|
||||
norms.push_back( aNormal );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -233,16 +266,26 @@ bool SGNORMALS::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
|
||||
bool SGNORMALS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( nullptr == parentNode )
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
wxCHECK( m_Parent, false );
|
||||
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( nullptr != np->GetParent() )
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, nullptr ) )
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
@@ -251,12 +294,26 @@ bool SGNORMALS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
return false;
|
||||
}
|
||||
|
||||
wxCHECK( parentNode == m_Parent, 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() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad stream" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#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;
|
||||
}
|
||||
@@ -278,10 +335,20 @@ bool SGNORMALS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
|
||||
bool SGNORMALS::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
wxCHECK( norms.empty(), false );
|
||||
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 ) );
|
||||
aFile.read( (char*)&npts, sizeof(size_t) );
|
||||
SGVECTOR tmp;
|
||||
|
||||
if( aFile.fail() )
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2020 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
|
||||
@@ -24,6 +23,7 @@
|
||||
|
||||
/**
|
||||
* @file sg_normals.h
|
||||
* defines a set of vertex normals for a scene graph object
|
||||
*/
|
||||
|
||||
#ifndef SG_NORMALS_H
|
||||
@@ -32,20 +32,23 @@
|
||||
#include <vector>
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
|
||||
/**
|
||||
* Define a set of vertex normals for a scene graph object
|
||||
*/
|
||||
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 ) noexcept override;
|
||||
bool AddRefNode( SGNODE* aNode ) noexcept override;
|
||||
bool AddChildNode( SGNODE* aNode ) noexcept 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 );
|
||||
@@ -57,11 +60,6 @@ public:
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) noexcept override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) noexcept override;
|
||||
|
||||
std::vector< SGVECTOR > norms;
|
||||
};
|
||||
|
||||
#endif // SG_NORMALS_H
|
||||
|
||||
+248
-131
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2020 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
|
||||
@@ -40,22 +39,29 @@
|
||||
SGSHAPE::SGSHAPE( SGNODE* aParent ) : SGNODE( aParent )
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_SHAPE;
|
||||
m_Appearance = nullptr;
|
||||
m_RAppearance = nullptr;
|
||||
m_FaceSet = nullptr;
|
||||
m_RFaceSet = nullptr;
|
||||
m_Appearance = NULL;
|
||||
m_RAppearance = NULL;
|
||||
m_FaceSet = NULL;
|
||||
m_RFaceSet = NULL;
|
||||
|
||||
if( nullptr != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] inappropriate parent to SGSHAPE (type %d)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aParent->GetNodeType() );
|
||||
#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( nullptr != aParent && S3D::SGTYPE_TRANSFORM == aParent->GetNodeType() )
|
||||
else if( NULL != aParent && S3D::SGTYPE_TRANSFORM == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -65,35 +71,37 @@ SGSHAPE::~SGSHAPE()
|
||||
if( m_RAppearance )
|
||||
{
|
||||
m_RAppearance->delNodeRef( this );
|
||||
m_RAppearance = nullptr;
|
||||
m_RAppearance = NULL;
|
||||
}
|
||||
|
||||
if( m_RFaceSet )
|
||||
{
|
||||
m_RFaceSet->delNodeRef( this );
|
||||
m_RFaceSet = nullptr;
|
||||
m_RFaceSet = NULL;
|
||||
}
|
||||
|
||||
// delete objects
|
||||
if( m_Appearance )
|
||||
{
|
||||
m_Appearance->SetParent( nullptr, false );
|
||||
m_Appearance->SetParent( NULL, false );
|
||||
delete m_Appearance;
|
||||
m_Appearance = nullptr;
|
||||
m_Appearance = NULL;
|
||||
}
|
||||
|
||||
if( m_FaceSet )
|
||||
{
|
||||
m_FaceSet->SetParent( nullptr, false );
|
||||
m_FaceSet->SetParent( NULL, false );
|
||||
delete m_FaceSet;
|
||||
m_FaceSet = nullptr;
|
||||
m_FaceSet = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGSHAPE::SetParent( SGNODE* aParent, bool notify )
|
||||
{
|
||||
if( nullptr != m_Parent )
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
@@ -102,14 +110,14 @@ bool SGSHAPE::SetParent( SGNODE* aParent, bool notify )
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
if( nullptr == aParent )
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a SGTRANSFORM may be parent to a SGSHAPE
|
||||
if( nullptr != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
@@ -121,17 +129,17 @@ bool SGSHAPE::SetParent( SGNODE* aParent, bool notify )
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGSHAPE::FindNode( const char* aNodeName, const SGNODE* aCaller )
|
||||
SGNODE* SGSHAPE::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( nullptr == aNodeName || 0 == aNodeName[0] )
|
||||
return nullptr;
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
SGNODE* tmp = nullptr;
|
||||
SGNODE* tmp = NULL;
|
||||
|
||||
if( nullptr != m_Appearance )
|
||||
if( NULL != m_Appearance )
|
||||
{
|
||||
tmp = m_Appearance->FindNode( aNodeName, this );
|
||||
|
||||
@@ -141,7 +149,7 @@ SGNODE* SGSHAPE::FindNode( const char* aNodeName, const SGNODE* aCaller )
|
||||
}
|
||||
}
|
||||
|
||||
if( nullptr != m_FaceSet )
|
||||
if( NULL != m_FaceSet )
|
||||
{
|
||||
tmp = m_FaceSet->FindNode( aNodeName, this );
|
||||
|
||||
@@ -152,8 +160,8 @@ SGNODE* SGSHAPE::FindNode( const char* aNodeName, const SGNODE* aCaller )
|
||||
}
|
||||
|
||||
// query the parent if appropriate
|
||||
if( aCaller == m_Parent || nullptr == m_Parent )
|
||||
return nullptr;
|
||||
if( aCaller == m_Parent || NULL == m_Parent )
|
||||
return NULL;
|
||||
|
||||
return m_Parent->FindNode( aNodeName, this );
|
||||
}
|
||||
@@ -161,20 +169,20 @@ SGNODE* SGSHAPE::FindNode( const char* aNodeName, const SGNODE* aCaller )
|
||||
|
||||
void SGSHAPE::unlinkNode( const SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( nullptr == aNode )
|
||||
if( NULL == aNode )
|
||||
return;
|
||||
|
||||
if( isChild )
|
||||
{
|
||||
if( aNode == m_Appearance )
|
||||
{
|
||||
m_Appearance = nullptr;
|
||||
m_Appearance = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if( aNode == m_FaceSet )
|
||||
{
|
||||
m_FaceSet = nullptr;
|
||||
m_FaceSet = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -183,38 +191,58 @@ void SGSHAPE::unlinkNode( const SGNODE* aNode, bool isChild )
|
||||
if( aNode == m_RAppearance )
|
||||
{
|
||||
delNodeRef( this );
|
||||
m_RAppearance = nullptr;
|
||||
m_RAppearance = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if( aNode == m_RFaceSet )
|
||||
{
|
||||
delNodeRef( this );
|
||||
m_RFaceSet = nullptr;
|
||||
m_RFaceSet = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] unlinkNode() did not find its target" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#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 )
|
||||
{
|
||||
wxCHECK( aNode, false );
|
||||
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() )
|
||||
{
|
||||
@@ -222,9 +250,12 @@ bool SGSHAPE::addNode( SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( aNode != m_Appearance && aNode != m_RAppearance )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] assigning multiple Appearance "
|
||||
"nodes" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#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;
|
||||
}
|
||||
@@ -252,8 +283,12 @@ bool SGSHAPE::addNode( SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( aNode != m_FaceSet && aNode != m_RFaceSet )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] assigning multiple FaceSet nodes" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#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;
|
||||
}
|
||||
@@ -275,9 +310,15 @@ bool SGSHAPE::addNode( SGNODE* aNode, bool isChild )
|
||||
return true;
|
||||
}
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] object %s is not a valid type for this "
|
||||
"object (%d)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aNode->GetName(), aNode->GetNodeType() );
|
||||
#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;
|
||||
}
|
||||
@@ -310,12 +351,15 @@ void SGSHAPE::ReNameNodes( void )
|
||||
// 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 )
|
||||
if( !m_Appearance && !m_RAppearance
|
||||
&& !m_FaceSet && !m_RFaceSet )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -358,16 +402,26 @@ bool SGSHAPE::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
|
||||
bool SGSHAPE::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( nullptr == parentNode )
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
wxCHECK( m_Parent, false );
|
||||
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( nullptr != np->GetParent() )
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, nullptr ) )
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
@@ -376,21 +430,35 @@ bool SGSHAPE::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
return false;
|
||||
}
|
||||
|
||||
wxCHECK( parentNode == m_Parent, 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() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] bad stream" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#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( nullptr != m_RAppearance && !m_RAppearance->isWritten() )
|
||||
if( NULL != m_RAppearance && !m_RAppearance->isWritten() )
|
||||
m_RAppearance->SwapParent(this);
|
||||
|
||||
if( nullptr != m_RFaceSet && !m_RFaceSet->isWritten() )
|
||||
if( NULL != m_RFaceSet && !m_RFaceSet->isWritten() )
|
||||
m_RFaceSet->SwapParent( this );
|
||||
|
||||
aFile << "[" << GetName() << "]";
|
||||
@@ -402,23 +470,19 @@ bool SGSHAPE::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
items[i] = 0;
|
||||
|
||||
i = 0;
|
||||
|
||||
if( nullptr != m_Appearance )
|
||||
if( NULL != m_Appearance )
|
||||
items[i] = true;
|
||||
|
||||
++i;
|
||||
|
||||
if( nullptr != m_RAppearance )
|
||||
if( NULL != m_RAppearance )
|
||||
items[i] = true;
|
||||
|
||||
++i;
|
||||
|
||||
if( nullptr != m_FaceSet )
|
||||
if( NULL != m_FaceSet )
|
||||
items[i] = true;
|
||||
|
||||
++i;
|
||||
|
||||
if( nullptr != m_RFaceSet )
|
||||
if( NULL != m_RFaceSet )
|
||||
items[i] = true;
|
||||
|
||||
for( int jj = 0; jj < NITEMS; ++jj )
|
||||
@@ -446,8 +510,17 @@ bool SGSHAPE::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
|
||||
bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
wxCHECK( m_Appearance == nullptr && m_RAppearance == nullptr && m_FaceSet == nullptr &&
|
||||
m_RFaceSet == nullptr, false );
|
||||
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];
|
||||
@@ -457,10 +530,13 @@ bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( ( items[0] && items[1] ) || ( items[2] && items[3] ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; multiple item definitions "
|
||||
"at position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#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;
|
||||
}
|
||||
@@ -471,10 +547,13 @@ bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_APPEARANCE != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad child appearance "
|
||||
"tag at position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#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;
|
||||
}
|
||||
@@ -484,9 +563,13 @@ bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !m_Appearance->ReadCache( aFile, this ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data while reading appearance "
|
||||
"'%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, name );
|
||||
#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;
|
||||
}
|
||||
@@ -496,10 +579,13 @@ bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_APPEARANCE != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad ref appearance tag "
|
||||
"at position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#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;
|
||||
}
|
||||
@@ -508,20 +594,26 @@ bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !np )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: cannot find ref "
|
||||
"appearance '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#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() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: type is not "
|
||||
"SGAPPEARANCE '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#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;
|
||||
}
|
||||
@@ -534,10 +626,13 @@ bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_FACESET != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad child face set tag "
|
||||
"at position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#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;
|
||||
}
|
||||
@@ -547,9 +642,13 @@ bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !m_FaceSet->ReadCache( aFile, this ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data while reading face set "
|
||||
"'%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, name );
|
||||
#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;
|
||||
}
|
||||
@@ -559,10 +658,13 @@ bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_FACESET != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad ref face set tag at "
|
||||
"position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#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;
|
||||
}
|
||||
@@ -571,20 +673,26 @@ bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !np )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: cannot find ref face "
|
||||
"set '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#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() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: type is not SGFACESET "
|
||||
"'%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#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;
|
||||
}
|
||||
@@ -600,8 +708,8 @@ bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
}
|
||||
|
||||
|
||||
bool SGSHAPE::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
std::vector< SMESH >& meshes )
|
||||
bool SGSHAPE::Prepare( const glm::dmat4* aTransform,
|
||||
S3D::MATLIST& materials, std::vector< SMESH >& meshes )
|
||||
{
|
||||
SMESH m;
|
||||
S3D::INIT_SMESH( m );
|
||||
@@ -609,25 +717,28 @@ bool SGSHAPE::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
SGAPPEARANCE* pa = m_Appearance;
|
||||
SGFACESET* pf = m_FaceSet;
|
||||
|
||||
if( nullptr == pa )
|
||||
if( NULL == pa )
|
||||
pa = m_RAppearance;
|
||||
|
||||
if( nullptr == pf )
|
||||
if( NULL == pf )
|
||||
pf = m_RFaceSet;
|
||||
|
||||
// no face sets = nothing to render, which is valid though pointless
|
||||
if( nullptr == pf )
|
||||
if( NULL == pf )
|
||||
return true;
|
||||
|
||||
if( !pf->validate() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad model; inconsistent data" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
#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( nullptr == pa )
|
||||
if( NULL == pa )
|
||||
{
|
||||
m.m_MaterialIdx = 0;
|
||||
}
|
||||
@@ -650,22 +761,22 @@ bool SGSHAPE::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
SGCOORDINDEX* vidx = pf->m_CoordIndices;
|
||||
SGNORMALS* pn = pf->m_Normals;
|
||||
|
||||
if( nullptr == pc )
|
||||
if( NULL == pc )
|
||||
pc = pf->m_RColors;
|
||||
|
||||
if( nullptr == pv )
|
||||
if( NULL == pv )
|
||||
pv = pf->m_RCoords;
|
||||
|
||||
if( nullptr == pn )
|
||||
if( NULL == pn )
|
||||
pn = pf->m_RNormals;
|
||||
|
||||
// set the vertex points and indices
|
||||
size_t nCoords = 0;
|
||||
SGPOINT* pCoords = nullptr;
|
||||
SGPOINT* pCoords = NULL;
|
||||
pv->GetCoordsList( nCoords, pCoords );
|
||||
|
||||
size_t nColors = 0;
|
||||
SGCOLOR* pColors = nullptr;
|
||||
SGCOLOR* pColors = NULL;
|
||||
|
||||
if( pc )
|
||||
{
|
||||
@@ -674,18 +785,20 @@ bool SGSHAPE::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
|
||||
if( nColors < nCoords )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad model; not enough colors per "
|
||||
"vertex (%ul vs %ul)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, static_cast<unsigned long>( nColors ),
|
||||
static_cast<unsigned long>( 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 = nullptr;
|
||||
int* lv = NULL;
|
||||
vidx->GetIndices( nvidx, lv );
|
||||
|
||||
// note: reduce the vertex set to include only the referenced vertices
|
||||
@@ -706,14 +819,17 @@ bool SGSHAPE::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
|
||||
if( vertices.size() < 3 )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad model; not enough vertices" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
#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 = nullptr;
|
||||
SFVEC3F* lColors = NULL;
|
||||
SFVEC3F* lCoords = new SFVEC3F[ vertices.size() ];
|
||||
int ti;
|
||||
|
||||
@@ -723,6 +839,7 @@ bool SGSHAPE::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
m.m_Color = lColors;
|
||||
}
|
||||
|
||||
|
||||
if( pc )
|
||||
{
|
||||
for( size_t i = 0; i < vertices.size(); ++i )
|
||||
@@ -760,7 +877,7 @@ bool SGSHAPE::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
|
||||
// set the per-vertex normals
|
||||
size_t nNorms = 0;
|
||||
SGVECTOR* pNorms = nullptr;
|
||||
SGVECTOR* pNorms = NULL;
|
||||
double x, y, z;
|
||||
|
||||
pn->GetNormalList( nNorms, pNorms );
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2020 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
|
||||
@@ -24,6 +23,7 @@
|
||||
|
||||
/**
|
||||
* @file sg_shape.h
|
||||
* defines a complex 3D shape for a scenegraph object
|
||||
*/
|
||||
|
||||
|
||||
@@ -36,33 +36,8 @@
|
||||
class SGAPPEARANCE;
|
||||
class SGFACESET;
|
||||
|
||||
/**
|
||||
* Define a complex 3D shape for a scenegraph object.
|
||||
*/
|
||||
class SGSHAPE : public SGNODE
|
||||
{
|
||||
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 );
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
|
||||
private:
|
||||
void unlinkNode( const SGNODE* aNode, bool isChild );
|
||||
bool addNode( SGNODE* aNode, bool isChild );
|
||||
@@ -75,6 +50,28 @@ public:
|
||||
// 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 );
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,782 +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-2021 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 "../3d_rendering/camera.h"
|
||||
#include "board_adapter.h"
|
||||
#include <board_design_settings.h>
|
||||
#include <board_stackup_manager/board_stackup.h>
|
||||
#include <board_stackup_manager/stackup_predefined_prms.h>
|
||||
#include <3d_rendering/raytracing/shapes2D/polygon_2d.h>
|
||||
#include <board.h>
|
||||
#include <dialogs/dialog_color_picker.h>
|
||||
#include <3d_math.h>
|
||||
#include "3d_fastmath.h"
|
||||
#include <geometry/geometry_utils.h>
|
||||
#include <convert_to_biu.h>
|
||||
#include <pgm_base.h>
|
||||
#include <settings/settings_manager.h>
|
||||
#include <wx/log.h>
|
||||
|
||||
|
||||
CUSTOM_COLORS_LIST BOARD_ADAPTER::g_SilkscreenColors;
|
||||
CUSTOM_COLORS_LIST BOARD_ADAPTER::g_MaskColors;
|
||||
CUSTOM_COLORS_LIST BOARD_ADAPTER::g_PasteColors;
|
||||
CUSTOM_COLORS_LIST BOARD_ADAPTER::g_FinishColors;
|
||||
CUSTOM_COLORS_LIST BOARD_ADAPTER::g_BoardColors;
|
||||
|
||||
KIGFX::COLOR4D BOARD_ADAPTER::g_DefaultBackgroundTop;
|
||||
KIGFX::COLOR4D BOARD_ADAPTER::g_DefaultBackgroundBot;
|
||||
KIGFX::COLOR4D BOARD_ADAPTER::g_DefaultSilkscreen;
|
||||
KIGFX::COLOR4D BOARD_ADAPTER::g_DefaultSolderMask;
|
||||
KIGFX::COLOR4D BOARD_ADAPTER::g_DefaultSolderPaste;
|
||||
KIGFX::COLOR4D BOARD_ADAPTER::g_DefaultSurfaceFinish;
|
||||
KIGFX::COLOR4D BOARD_ADAPTER::g_DefaultBoardBody;
|
||||
|
||||
static bool g_ColorsLoaded = false;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @ingroup trace_env_vars
|
||||
*/
|
||||
const wxChar *BOARD_ADAPTER::m_logTrace = wxT( "KI_TRACE_EDA_CINFO3D_VISU" );
|
||||
|
||||
|
||||
BOARD_ADAPTER::BOARD_ADAPTER() :
|
||||
m_board( nullptr ),
|
||||
m_3dModelManager( nullptr ),
|
||||
m_colors( nullptr ),
|
||||
m_layerZcoordTop(),
|
||||
m_layerZcoordBottom()
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "BOARD_ADAPTER::BOARD_ADAPTER" ) );
|
||||
|
||||
m_gridType = GRID3D_TYPE::NONE;
|
||||
m_antiAliasingMode = ANTIALIASING_MODE::AA_8X;
|
||||
m_drawFlags.resize( FL_LAST, false );
|
||||
|
||||
if( PgmOrNull() )
|
||||
m_colors = Pgm().GetSettingsManager().GetColorSettings();
|
||||
|
||||
m_renderEngine = RENDER_ENGINE::OPENGL;
|
||||
m_materialMode = MATERIAL_MODE::NORMAL;
|
||||
|
||||
m_boardPos = wxPoint();
|
||||
m_boardSize = wxSize();
|
||||
m_boardCenter = SFVEC3F( 0.0f );
|
||||
|
||||
m_boardBoundingBox.Reset();
|
||||
|
||||
m_throughHoleIds.Clear();
|
||||
m_throughHoleOds.Clear();
|
||||
m_throughHoleAnnularRings.Clear();
|
||||
|
||||
m_copperLayersCount = -1;
|
||||
m_epoxyThickness3DU = 0.0f;
|
||||
m_copperThickness3DU = 0.0f;
|
||||
m_nonCopperLayerThickness3DU = 0.0f;
|
||||
m_solderPasteLayerThickness3DU = 0.0f;
|
||||
m_biuTo3Dunits = 1.0;
|
||||
|
||||
m_trackCount = 0;
|
||||
m_viaCount = 0;
|
||||
m_averageViaHoleDiameter = 0.0f;
|
||||
m_holeCount = 0;
|
||||
m_averageHoleDiameter = 0.0f;
|
||||
m_averageTrackWidth = 0.0f;
|
||||
|
||||
SetFlag( FL_USE_REALISTIC_MODE, true );
|
||||
SetFlag( FL_FP_ATTRIBUTES_NORMAL, true );
|
||||
SetFlag( FL_SHOW_BOARD_BODY, true );
|
||||
SetFlag( FL_CLIP_SILK_ON_VIA_ANNULUS, false );
|
||||
SetFlag( FL_FP_ATTRIBUTES_NORMAL, true );
|
||||
SetFlag( FL_FP_ATTRIBUTES_NORMAL_INSERT, true );
|
||||
SetFlag( FL_FP_ATTRIBUTES_VIRTUAL, true );
|
||||
SetFlag( FL_ZONE, true );
|
||||
SetFlag( FL_SILKSCREEN, true );
|
||||
SetFlag( FL_SOLDERMASK, true );
|
||||
SetFlag( FL_SUBTRACT_MASK_FROM_SILK, false );
|
||||
|
||||
SetFlag( FL_RENDER_OPENGL_COPPER_THICKNESS, true );
|
||||
SetFlag( FL_RENDER_OPENGL_AA_DISABLE_ON_MOVE, false );
|
||||
SetFlag( FL_RENDER_OPENGL_THICKNESS_DISABLE_ON_MOVE, false );
|
||||
SetFlag( FL_RENDER_OPENGL_VIAS_DISABLE_ON_MOVE, false );
|
||||
SetFlag( FL_RENDER_OPENGL_HOLES_DISABLE_ON_MOVE, false );
|
||||
|
||||
SetFlag( FL_USE_SELECTION, true );
|
||||
SetFlag( FL_HIGHLIGHT_ROLLOVER_ITEM, true );
|
||||
|
||||
m_BgColorBot = SFVEC4F( 0.4, 0.4, 0.5, 1.0 );
|
||||
m_BgColorTop = SFVEC4F( 0.8, 0.8, 0.9, 1.0 );
|
||||
m_BoardBodyColor = SFVEC4F( 0.4, 0.4, 0.5, 0.9 );
|
||||
m_SolderMaskColorTop = SFVEC4F( 0.1, 0.2, 0.1, 0.83 );
|
||||
m_SolderMaskColorBot = SFVEC4F( 0.1, 0.2, 0.1, 0.83 );
|
||||
m_SolderPasteColor = SFVEC4F( 0.4, 0.4, 0.4, 1.0 );
|
||||
m_SilkScreenColorTop = SFVEC4F( 0.9, 0.9, 0.9, 1.0 );
|
||||
m_SilkScreenColorBot = SFVEC4F( 0.9, 0.9, 0.9, 1.0 );
|
||||
m_CopperColor = SFVEC4F( 0.75, 0.61, 0.23, 1.0 );
|
||||
|
||||
m_platedPadsFront = nullptr;
|
||||
m_platedPadsBack = nullptr;
|
||||
|
||||
m_frontPlatedPadPolys = nullptr;
|
||||
m_backPlatedPadPolys = nullptr;
|
||||
|
||||
// Avoid raytracing options not initialized:
|
||||
m_RtShadowSampleCount = 0;
|
||||
m_RtReflectionSampleCount = 0;
|
||||
m_RtRefractionSampleCount = 0;
|
||||
|
||||
m_RtSpreadShadows = 0.0;
|
||||
m_RtSpreadReflections = 0.0;
|
||||
m_RtSpreadRefractions = 0.0;
|
||||
|
||||
m_RtRecursiveReflectionCount = 0;
|
||||
m_RtRecursiveRefractionCount = 0;
|
||||
|
||||
if( !g_ColorsLoaded )
|
||||
{
|
||||
#define ADD_COLOR( list, r, g, b, a, name ) \
|
||||
list.push_back( CUSTOM_COLOR_ITEM( r/255.0, g/255.0, b/255.0, a, name ) )
|
||||
|
||||
ADD_COLOR( g_SilkscreenColors, 245, 245, 245, 1.0, NotSpecifiedPrm() ); // White
|
||||
ADD_COLOR( g_SilkscreenColors, 20, 51, 36, 1.0, wxT( "Green" ) );
|
||||
ADD_COLOR( g_SilkscreenColors, 181, 19, 21, 1.0, wxT( "Red" ) );
|
||||
ADD_COLOR( g_SilkscreenColors, 2, 59, 162, 1.0, wxT( "Blue" ) );
|
||||
ADD_COLOR( g_SilkscreenColors, 11, 11, 11, 1.0, wxT( "Black" ) );
|
||||
ADD_COLOR( g_SilkscreenColors, 245, 245, 245, 1.0, wxT( "White" ) );
|
||||
ADD_COLOR( g_SilkscreenColors, 32, 2, 53, 1.0, wxT( "Purple" ) );
|
||||
ADD_COLOR( g_SilkscreenColors, 194, 195, 0, 1.0, wxT( "Yellow" ) );
|
||||
|
||||
ADD_COLOR( g_MaskColors, 20, 51, 36, 0.83, NotSpecifiedPrm() ); // Green
|
||||
ADD_COLOR( g_MaskColors, 20, 51, 36, 0.83, wxT( "Green" ) );
|
||||
ADD_COLOR( g_MaskColors, 91, 168, 12, 0.83, wxT( "Light Green" ) );
|
||||
ADD_COLOR( g_MaskColors, 13, 104, 11, 0.83, wxT( "Saturated Green" ) );
|
||||
ADD_COLOR( g_MaskColors, 181, 19, 21, 0.83, wxT( "Red" ) );
|
||||
ADD_COLOR( g_MaskColors, 210, 40, 14, 0.83, wxT( "Light Red" ) );
|
||||
ADD_COLOR( g_MaskColors, 239, 53, 41, 0.83, wxT( "Red/Orange" ) );
|
||||
ADD_COLOR( g_MaskColors, 2, 59, 162, 0.83, wxT( "Blue" ) );
|
||||
ADD_COLOR( g_MaskColors, 54, 79, 116, 0.83, wxT( "Light Blue 1" ) );
|
||||
ADD_COLOR( g_MaskColors, 61, 85, 130, 0.83, wxT( "Light Blue 2" ) );
|
||||
ADD_COLOR( g_MaskColors, 21, 70, 80, 0.83, wxT( "Green/Blue" ) );
|
||||
ADD_COLOR( g_MaskColors, 11, 11, 11, 0.83, wxT( "Black" ) );
|
||||
ADD_COLOR( g_MaskColors, 245, 245, 245, 0.83, wxT( "White" ) );
|
||||
ADD_COLOR( g_MaskColors, 32, 2, 53, 0.83, wxT( "Purple" ) );
|
||||
ADD_COLOR( g_MaskColors, 119, 31, 91, 0.83, wxT( "Light Purple" ) );
|
||||
ADD_COLOR( g_MaskColors, 194, 195, 0, 0.83, wxT( "Yellow" ) );
|
||||
|
||||
ADD_COLOR( g_PasteColors, 128, 128, 128, 1.0, wxT( "Grey" ) );
|
||||
ADD_COLOR( g_PasteColors, 90, 90, 90, 1.0, wxT( "Dark Grey" ) );
|
||||
ADD_COLOR( g_PasteColors, 213, 213, 213, 1.0, wxT( "Silver" ) );
|
||||
|
||||
ADD_COLOR( g_FinishColors, 184, 115, 50, 1.0, wxT( "Copper" ) );
|
||||
ADD_COLOR( g_FinishColors, 178, 156, 0, 1.0, wxT( "Gold" ) );
|
||||
ADD_COLOR( g_FinishColors, 213, 213, 213, 1.0, wxT( "Silver" ) );
|
||||
ADD_COLOR( g_FinishColors, 160, 160, 160, 1.0, wxT( "Tin" ) );
|
||||
|
||||
ADD_COLOR( g_BoardColors, 51, 43, 22, 0.83, wxT( "FR4 natural, dark" ) );
|
||||
ADD_COLOR( g_BoardColors, 109, 116, 75, 0.83, wxT( "FR4 natural" ) );
|
||||
ADD_COLOR( g_BoardColors, 252, 252, 250, 0.90, wxT( "PTFE natural" ) );
|
||||
ADD_COLOR( g_BoardColors, 205, 130, 0, 0.68, wxT( "Polyimide" ) );
|
||||
ADD_COLOR( g_BoardColors, 92, 17, 6, 0.90, wxT( "Phenolic natural" ) );
|
||||
ADD_COLOR( g_BoardColors, 146, 99, 47, 0.83, wxT( "Brown 1" ) );
|
||||
ADD_COLOR( g_BoardColors, 160, 123, 54, 0.83, wxT( "Brown 2" ) );
|
||||
ADD_COLOR( g_BoardColors, 146, 99, 47, 0.83, wxT( "Brown 3" ) );
|
||||
ADD_COLOR( g_BoardColors, 213, 213, 213, 1.0, wxT( "Aluminum" ) );
|
||||
|
||||
g_DefaultBackgroundTop = COLOR4D( 0.80, 0.80, 0.90, 1.0 );
|
||||
g_DefaultBackgroundBot = COLOR4D( 0.40, 0.40, 0.50, 1.0 );
|
||||
|
||||
g_DefaultSilkscreen = COLOR4D( 0.94, 0.94, 0.94, 1.0 );
|
||||
g_DefaultSolderMask = COLOR4D( 0.08, 0.20, 0.14, 0.83 );
|
||||
g_DefaultSolderPaste = COLOR4D( 0.50, 0.50, 0.50, 1.0 );
|
||||
g_DefaultSurfaceFinish = COLOR4D( 0.75, 0.61, 0.23, 1.0 );
|
||||
g_DefaultBoardBody = COLOR4D( 0.43, 0.45, 0.30, 0.90 );
|
||||
|
||||
g_ColorsLoaded = true;
|
||||
}
|
||||
#undef ADD_COLOR
|
||||
}
|
||||
|
||||
|
||||
BOARD_ADAPTER::~BOARD_ADAPTER()
|
||||
{
|
||||
destroyLayers();
|
||||
}
|
||||
|
||||
|
||||
bool BOARD_ADAPTER::Is3dLayerEnabled( PCB_LAYER_ID aLayer ) const
|
||||
{
|
||||
wxASSERT( aLayer < PCB_LAYER_ID_COUNT );
|
||||
|
||||
if( m_board && !m_board->IsLayerEnabled( aLayer ) )
|
||||
return false;
|
||||
|
||||
// see if layer needs to be shown
|
||||
// check the flags
|
||||
switch( aLayer )
|
||||
{
|
||||
case B_Adhes:
|
||||
case F_Adhes:
|
||||
return GetFlag( FL_ADHESIVE );
|
||||
|
||||
case B_Paste:
|
||||
case F_Paste:
|
||||
return GetFlag( FL_SOLDERPASTE );
|
||||
|
||||
case B_SilkS:
|
||||
case F_SilkS:
|
||||
return GetFlag( FL_SILKSCREEN );
|
||||
|
||||
case B_Mask:
|
||||
case F_Mask:
|
||||
return GetFlag( FL_SOLDERMASK );
|
||||
|
||||
case Dwgs_User:
|
||||
case Cmts_User:
|
||||
if( GetFlag( FL_USE_REALISTIC_MODE ) )
|
||||
return false;
|
||||
|
||||
return GetFlag( FL_COMMENTS );
|
||||
|
||||
case Eco1_User:
|
||||
case Eco2_User:
|
||||
if( GetFlag( FL_USE_REALISTIC_MODE ) )
|
||||
return false;
|
||||
|
||||
return GetFlag( FL_ECO );
|
||||
|
||||
case Edge_Cuts:
|
||||
if( GetFlag( FL_SHOW_BOARD_BODY ) || GetFlag( FL_USE_REALISTIC_MODE ) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
||||
case Margin:
|
||||
if( GetFlag( FL_USE_REALISTIC_MODE ) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
||||
case B_Cu:
|
||||
case F_Cu:
|
||||
return m_board ? m_board->IsLayerVisible( aLayer ) || GetFlag( FL_USE_REALISTIC_MODE )
|
||||
: true;
|
||||
|
||||
default:
|
||||
// the layer is an internal copper layer, used the visibility
|
||||
return m_board && m_board->IsLayerVisible( aLayer );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool BOARD_ADAPTER::GetFlag( DISPLAY3D_FLG aFlag ) const
|
||||
{
|
||||
wxASSERT( aFlag < FL_LAST );
|
||||
|
||||
return m_drawFlags[aFlag];
|
||||
}
|
||||
|
||||
|
||||
void BOARD_ADAPTER::SetFlag( DISPLAY3D_FLG aFlag, bool aState )
|
||||
{
|
||||
wxASSERT( aFlag < FL_LAST );
|
||||
|
||||
m_drawFlags[aFlag] = aState;
|
||||
}
|
||||
|
||||
|
||||
bool BOARD_ADAPTER::IsFootprintShown( FOOTPRINT_ATTR_T aFPAttributes ) const
|
||||
{
|
||||
if( aFPAttributes & FP_SMD )
|
||||
return GetFlag( FL_FP_ATTRIBUTES_NORMAL_INSERT );
|
||||
else if( aFPAttributes & FP_THROUGH_HOLE )
|
||||
return GetFlag( FL_FP_ATTRIBUTES_NORMAL );
|
||||
else
|
||||
return GetFlag( FL_FP_ATTRIBUTES_VIRTUAL );
|
||||
}
|
||||
|
||||
|
||||
// !TODO: define the actual copper thickness by user from board stackup
|
||||
#define COPPER_THICKNESS Millimeter2iu( 0.035 ) // for 35 um
|
||||
// The solder mask layer (and silkscreen) thickness
|
||||
#define TECH_LAYER_THICKNESS Millimeter2iu( 0.025 )
|
||||
// The solder paste thickness is chosen bigger than the solder mask layer
|
||||
// to be sure is covers the mask when overlapping.
|
||||
#define SOLDERPASTE_LAYER_THICKNESS Millimeter2iu( 0.04 )
|
||||
|
||||
int BOARD_ADAPTER::GetHolePlatingThickness() const noexcept
|
||||
{
|
||||
return m_board ? m_board->GetDesignSettings().GetHolePlatingThickness()
|
||||
: 0.035 * PCB_IU_PER_MM;
|
||||
}
|
||||
|
||||
|
||||
unsigned int BOARD_ADAPTER::GetCircleSegmentCount( float aDiameter3DU ) const
|
||||
{
|
||||
wxASSERT( aDiameter3DU > 0.0f );
|
||||
|
||||
return GetCircleSegmentCount( (int)( aDiameter3DU / m_biuTo3Dunits ) );
|
||||
}
|
||||
|
||||
|
||||
unsigned int BOARD_ADAPTER::GetCircleSegmentCount( int aDiameterBIU ) const
|
||||
{
|
||||
wxASSERT( aDiameterBIU > 0 );
|
||||
|
||||
return GetArcToSegmentCount( aDiameterBIU / 2, ARC_HIGH_DEF, 360.0 );
|
||||
}
|
||||
|
||||
|
||||
void BOARD_ADAPTER::InitSettings( REPORTER* aStatusReporter, REPORTER* aWarningReporter )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "BOARD_ADAPTER::InitSettings" ) );
|
||||
|
||||
if( aStatusReporter )
|
||||
aStatusReporter->Report( _( "Build board outline" ) );
|
||||
|
||||
wxString msg;
|
||||
|
||||
const bool succeedToGetBoardPolygon = createBoardPolygon( &msg );
|
||||
|
||||
if( aWarningReporter )
|
||||
{
|
||||
if( !succeedToGetBoardPolygon )
|
||||
aWarningReporter->Report( msg, RPT_SEVERITY_WARNING );
|
||||
else
|
||||
aWarningReporter->Report( wxEmptyString );
|
||||
}
|
||||
|
||||
// Calculates the board bounding box (board outlines + items)
|
||||
// to ensure any item, even outside the board outlines can be seen
|
||||
bool boardEdgesOnly = true;
|
||||
|
||||
if( ( m_board && m_board->IsFootprintHolder() ) || !GetFlag( FL_USE_REALISTIC_MODE )
|
||||
|| !succeedToGetBoardPolygon )
|
||||
{
|
||||
boardEdgesOnly = false;
|
||||
}
|
||||
|
||||
EDA_RECT bbbox;
|
||||
|
||||
if( m_board )
|
||||
bbbox = m_board->ComputeBoundingBox( boardEdgesOnly );
|
||||
|
||||
// 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 ? m_board->GetCopperLayerCount() : 2;
|
||||
|
||||
// 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 conversion to apply to all positions.
|
||||
m_biuTo3Dunits = RANGE_SCALE_3D / std::max( m_boardSize.x, m_boardSize.y );
|
||||
|
||||
m_epoxyThickness3DU = m_board
|
||||
? m_board->GetDesignSettings().GetBoardThickness() * m_biuTo3Dunits
|
||||
: 1.6 * PCB_IU_PER_MM * 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;
|
||||
m_solderPasteLayerThickness3DU = SOLDERPASTE_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:
|
||||
zposBottom = zpos_copperTop_back;
|
||||
zposTop = zpos_copperTop_back - m_nonCopperLayerThickness3DU;
|
||||
break;
|
||||
|
||||
case B_Paste:
|
||||
zposBottom = zpos_copperTop_back;
|
||||
zposTop = zpos_copperTop_back - m_solderPasteLayerThickness3DU;
|
||||
break;
|
||||
|
||||
case F_Mask:
|
||||
zposBottom = zpos_copperTop_front;
|
||||
zposTop = zpos_copperTop_front + m_nonCopperLayerThickness3DU;
|
||||
break;
|
||||
|
||||
case F_Paste:
|
||||
zposBottom = zpos_copperTop_front;
|
||||
zposTop = zpos_copperTop_front + m_solderPasteLayerThickness3DU;
|
||||
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_boardBoundingBox = BBOX_3D( boardMin, boardMax );
|
||||
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
unsigned stats_startCreateBoardPolyTime = GetRunningMicroSecs();
|
||||
#endif
|
||||
|
||||
if( aStatusReporter )
|
||||
aStatusReporter->Report( _( "Create layers" ) );
|
||||
|
||||
createLayers( aStatusReporter );
|
||||
|
||||
COLOR_SETTINGS* colors = Pgm().GetSettingsManager().GetColorSettings();
|
||||
|
||||
auto to_SFVEC4F =
|
||||
[]( const COLOR4D& src )
|
||||
{
|
||||
return SFVEC4F( src.r, src.g, src.b, src.a );
|
||||
};
|
||||
|
||||
m_BgColorTop = to_SFVEC4F( colors->GetColor( LAYER_3D_BACKGROUND_TOP ) );
|
||||
m_BgColorBot = to_SFVEC4F( colors->GetColor( LAYER_3D_BACKGROUND_BOTTOM ) );
|
||||
|
||||
m_SolderPasteColor = to_SFVEC4F( colors->GetColor( LAYER_3D_SOLDERPASTE ) );
|
||||
|
||||
if( m_board && colors->GetUseBoardStackupColors() )
|
||||
{
|
||||
const BOARD_STACKUP& stackup = m_board->GetDesignSettings().GetStackupDescriptor();
|
||||
|
||||
auto findColor =
|
||||
[]( const wxString& aColorName, const CUSTOM_COLORS_LIST& aColorSet )
|
||||
{
|
||||
if( aColorName.StartsWith( wxT( "#" ) ) )
|
||||
{
|
||||
return KIGFX::COLOR4D( aColorName );
|
||||
}
|
||||
else
|
||||
{
|
||||
for( const CUSTOM_COLOR_ITEM& color : aColorSet )
|
||||
{
|
||||
if( color.m_ColorName == aColorName )
|
||||
return color.m_Color;
|
||||
}
|
||||
}
|
||||
|
||||
return KIGFX::COLOR4D();
|
||||
};
|
||||
|
||||
m_SilkScreenColorTop = to_SFVEC4F( g_DefaultSilkscreen );
|
||||
m_SilkScreenColorBot = to_SFVEC4F( g_DefaultSilkscreen );
|
||||
m_SolderMaskColorTop = to_SFVEC4F( g_DefaultSolderMask );
|
||||
m_SolderMaskColorBot = to_SFVEC4F( g_DefaultSolderMask );
|
||||
|
||||
KIGFX::COLOR4D bodyColor( 0, 0, 0, 0 );
|
||||
|
||||
for( const BOARD_STACKUP_ITEM* stackupItem : stackup.GetList() )
|
||||
{
|
||||
wxString colorName = stackupItem->GetColor();
|
||||
|
||||
switch( stackupItem->GetType() )
|
||||
{
|
||||
case BS_ITEM_TYPE_SILKSCREEN:
|
||||
if( stackupItem->GetBrdLayerId() == F_SilkS )
|
||||
m_SilkScreenColorTop = to_SFVEC4F( findColor( colorName, g_SilkscreenColors ) );
|
||||
else
|
||||
m_SilkScreenColorBot = to_SFVEC4F( findColor( colorName, g_SilkscreenColors ) );
|
||||
break;
|
||||
|
||||
case BS_ITEM_TYPE_SOLDERMASK:
|
||||
if( stackupItem->GetBrdLayerId() == F_Mask )
|
||||
m_SolderMaskColorTop = to_SFVEC4F( findColor( colorName, g_MaskColors ) );
|
||||
else
|
||||
m_SolderMaskColorBot = to_SFVEC4F( findColor( colorName, g_MaskColors ) );
|
||||
|
||||
break;
|
||||
|
||||
case BS_ITEM_TYPE_DIELECTRIC:
|
||||
{
|
||||
KIGFX::COLOR4D layerColor = COLOR4D::UNSPECIFIED;
|
||||
const wxString& materialName = stackupItem->GetMaterial();
|
||||
|
||||
if( materialName.StartsWith( wxT( "FR4" ) ) )
|
||||
{
|
||||
layerColor = findColor( wxT( "FR4 natural" ), g_BoardColors );
|
||||
}
|
||||
else if( materialName.IsSameAs( wxT( "PTFE" ) )
|
||||
|| materialName.IsSameAs( wxT( "Teflon" ) ) )
|
||||
{
|
||||
layerColor = findColor( wxT( "PTFE natural" ), g_BoardColors );
|
||||
}
|
||||
else if( materialName.IsSameAs( wxT( "Polyimide" ) )
|
||||
|| materialName.IsSameAs( wxT( "Kapton" ) ) )
|
||||
{
|
||||
layerColor = findColor( wxT( "Polyimide" ), g_BoardColors );
|
||||
}
|
||||
else if( materialName.IsSameAs( wxT( "Al" ) ) )
|
||||
{
|
||||
layerColor = findColor( wxT( "Aluminum" ), g_BoardColors );
|
||||
}
|
||||
else // A default color value for unknown dielectric material
|
||||
// (i.e. an exotic name entered by hand)
|
||||
{
|
||||
layerColor = findColor( wxT( "FR4 natural" ), g_BoardColors );
|
||||
}
|
||||
|
||||
if( bodyColor == COLOR4D( 0, 0, 0, 0 ) )
|
||||
bodyColor = layerColor;
|
||||
else
|
||||
bodyColor = bodyColor.Mix( layerColor, 1.0 - layerColor.a );
|
||||
|
||||
bodyColor.a += ( 1.0 - bodyColor.a ) * layerColor.a / 2;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( bodyColor != COLOR4D( 0, 0, 0, 0 ) )
|
||||
m_BoardBodyColor = to_SFVEC4F( bodyColor );
|
||||
else
|
||||
m_BoardBodyColor = to_SFVEC4F( g_DefaultBoardBody );
|
||||
|
||||
const wxString& finishName = stackup.m_FinishType;
|
||||
|
||||
if( finishName.EndsWith( wxT( "OSP" ) ) )
|
||||
{
|
||||
m_CopperColor = to_SFVEC4F( findColor( wxT( "Copper" ), g_FinishColors ) );
|
||||
}
|
||||
else if( finishName.EndsWith( wxT( "IG" ) )
|
||||
|| finishName.EndsWith( wxT( "gold" ) ) )
|
||||
{
|
||||
m_CopperColor = to_SFVEC4F( findColor( wxT( "Gold" ), g_FinishColors ) );
|
||||
}
|
||||
else if( finishName.StartsWith( wxT( "HAL" ) )
|
||||
|| finishName.StartsWith( wxT( "HASL" ) )
|
||||
|| finishName.EndsWith( wxT( "tin" ) )
|
||||
|| finishName.EndsWith( wxT( "nickel" ) ) )
|
||||
{
|
||||
m_CopperColor = to_SFVEC4F( findColor( wxT( "Tin" ), g_FinishColors ) );
|
||||
}
|
||||
else if( finishName.EndsWith( wxT( "silver" ) ) )
|
||||
{
|
||||
m_CopperColor = to_SFVEC4F( findColor( wxT( "Silver" ), g_FinishColors ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_CopperColor = to_SFVEC4F( g_DefaultSurfaceFinish );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_SilkScreenColorBot = to_SFVEC4F( colors->GetColor( LAYER_3D_SILKSCREEN_BOTTOM ) );
|
||||
m_SilkScreenColorTop = to_SFVEC4F( colors->GetColor( LAYER_3D_SILKSCREEN_TOP ) );
|
||||
m_SolderMaskColorBot = to_SFVEC4F( colors->GetColor( LAYER_3D_SOLDERMASK_BOTTOM ) );
|
||||
m_SolderMaskColorTop = to_SFVEC4F( colors->GetColor( LAYER_3D_SOLDERMASK_TOP ) );
|
||||
m_CopperColor = to_SFVEC4F( colors->GetColor( LAYER_3D_COPPER ) );
|
||||
m_BoardBodyColor = to_SFVEC4F( colors->GetColor( LAYER_3D_BOARD ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern bool BuildFootprintPolygonOutlines( BOARD* aBoard, SHAPE_POLY_SET& aOutlines,
|
||||
int aErrorMax, int aChainingEpsilon,
|
||||
OUTLINE_ERROR_HANDLER* aErrorHandler = nullptr );
|
||||
|
||||
|
||||
bool BOARD_ADAPTER::createBoardPolygon( wxString* aErrorMsg )
|
||||
{
|
||||
m_board_poly.RemoveAllContours();
|
||||
|
||||
if( !m_board )
|
||||
return false;
|
||||
|
||||
bool success;
|
||||
|
||||
if( m_board->IsFootprintHolder() )
|
||||
{
|
||||
if( !m_board->GetFirstFootprint() )
|
||||
{
|
||||
if( aErrorMsg )
|
||||
*aErrorMsg = _( "No footprint loaded." );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int chainingEpsilon = Millimeter2iu( 0.02 ); // max dist from one endPt to next startPt
|
||||
|
||||
success = BuildFootprintPolygonOutlines( m_board, m_board_poly,
|
||||
m_board->GetDesignSettings().m_MaxError,
|
||||
chainingEpsilon );
|
||||
|
||||
// Make polygon strictly simple to avoid issues (especially in 3D viewer)
|
||||
m_board_poly.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
||||
|
||||
if( !success && aErrorMsg )
|
||||
{
|
||||
*aErrorMsg = _( "Footprint outline is missing or malformed. Run Footprint Checker for "
|
||||
"a full analysis." );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
success = m_board->GetBoardPolygonOutlines( m_board_poly );
|
||||
|
||||
if( !success && aErrorMsg )
|
||||
*aErrorMsg = _( "Board outline is missing or malformed. Run DRC for a full analysis." );
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
float BOARD_ADAPTER::GetFootprintZPos( 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];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SFVEC4F BOARD_ADAPTER::GetLayerColor( PCB_LAYER_ID aLayerId ) const
|
||||
{
|
||||
wxASSERT( aLayerId < PCB_LAYER_ID_COUNT );
|
||||
|
||||
const COLOR4D color = m_colors->GetColor( aLayerId );
|
||||
|
||||
return SFVEC4F( color.r, color.g, color.b, color.a );
|
||||
}
|
||||
|
||||
|
||||
SFVEC4F BOARD_ADAPTER::GetItemColor( int aItemId ) const
|
||||
{
|
||||
return GetColor( m_colors->GetColor( aItemId ) );
|
||||
}
|
||||
|
||||
|
||||
SFVEC4F BOARD_ADAPTER::GetColor( const COLOR4D& aColor ) const
|
||||
{
|
||||
return SFVEC4F( aColor.r, aColor.g, aColor.b, aColor.a );
|
||||
}
|
||||
@@ -1,788 +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-2021 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
|
||||
*/
|
||||
|
||||
#ifndef BOARD_ADAPTER_H
|
||||
#define BOARD_ADAPTER_H
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include "../3d_rendering/raytracing/accelerators/container_2d.h"
|
||||
#include "../3d_rendering/raytracing/accelerators/container_3d.h"
|
||||
#include "../3d_rendering/raytracing/shapes3D/bbox_3d.h"
|
||||
#include "../3d_rendering/camera.h"
|
||||
#include "../3d_enums.h"
|
||||
#include "../3d_cache/3d_cache.h"
|
||||
#include "../common_ogl/ogl_attr_list.h"
|
||||
|
||||
#include <layer_ids.h>
|
||||
#include <pad.h>
|
||||
#include <pcb_track.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <pcb_base_frame.h>
|
||||
#include <pcb_text.h>
|
||||
#include <pcb_shape.h>
|
||||
#include <pcb_dimension.h>
|
||||
#include <zone.h>
|
||||
#include <footprint.h>
|
||||
#include <reporter.h>
|
||||
#include <dialogs/dialog_color_picker.h>
|
||||
|
||||
class COLOR_SETTINGS;
|
||||
|
||||
/// A type that stores a container of 2d objects for each layer id
|
||||
typedef std::map< PCB_LAYER_ID, BVH_CONTAINER_2D *> MAP_CONTAINER_2D_BASE;
|
||||
|
||||
/// 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
|
||||
|
||||
|
||||
/**
|
||||
* Helper class to handle information needed to display 3D board.
|
||||
*/
|
||||
class BOARD_ADAPTER
|
||||
{
|
||||
public:
|
||||
BOARD_ADAPTER();
|
||||
|
||||
~BOARD_ADAPTER();
|
||||
|
||||
/**
|
||||
* Update the cache manager pointer.
|
||||
*
|
||||
* @param aCachePointer: the pointer to the 3D cache manager.
|
||||
*/
|
||||
void Set3dCacheManager( S3D_CACHE* aCachePointer ) noexcept
|
||||
{
|
||||
m_3dModelManager = aCachePointer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the 3D cache manager pointer.
|
||||
*/
|
||||
S3D_CACHE* Get3dCacheManager() const noexcept
|
||||
{
|
||||
return m_3dModelManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 ;
|
||||
|
||||
/**
|
||||
* Set the status of a flag.
|
||||
*
|
||||
* @param aFlag the flag to set the status
|
||||
* @param aState status to set.
|
||||
*/
|
||||
void SetFlag( DISPLAY3D_FLG aFlag, bool aState );
|
||||
|
||||
/**
|
||||
* Check if a layer is enabled.
|
||||
*
|
||||
* @param aLayer layer ID to get status.
|
||||
*/
|
||||
bool Is3dLayerEnabled( PCB_LAYER_ID aLayer ) const;
|
||||
|
||||
/**
|
||||
* Test if footprint should be displayed in relation to attributes and the flags.
|
||||
*/
|
||||
bool IsFootprintShown( FOOTPRINT_ATTR_T aFPAttributes ) const;
|
||||
|
||||
/**
|
||||
* Set current board to be rendered.
|
||||
*
|
||||
* @param aBoard board to process.
|
||||
*/
|
||||
void SetBoard( BOARD* aBoard ) noexcept
|
||||
{
|
||||
m_board = aBoard;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current board to be rendered.
|
||||
*
|
||||
* @return BOARD pointer
|
||||
*/
|
||||
const BOARD* GetBoard() const noexcept
|
||||
{
|
||||
return m_board;
|
||||
}
|
||||
|
||||
void SetColorSettings( COLOR_SETTINGS* aSettings ) noexcept
|
||||
{
|
||||
m_colors = aSettings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to be called by the render when it need to reload the settings for the board.
|
||||
*
|
||||
* @param aStatusReporter the pointer for the status reporter.
|
||||
* @param aWarningReporter pointer for the warning reporter.
|
||||
*/
|
||||
void InitSettings( REPORTER* aStatusReporter, REPORTER* aWarningReporter );
|
||||
|
||||
/**
|
||||
* Board integer units To 3D units.
|
||||
*
|
||||
* @return the conversion factor to transform a position from the board to 3D units.
|
||||
*/
|
||||
double BiuTo3dUnits() const noexcept
|
||||
{
|
||||
return m_biuTo3Dunits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the board outling bounding box.
|
||||
*
|
||||
* @return the board bounding box in 3D units.
|
||||
*/
|
||||
const BBOX_3D& GetBBox() const noexcept
|
||||
{
|
||||
return m_boardBoundingBox;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current epoxy thickness.
|
||||
*
|
||||
* @return epoxy thickness in 3D units.
|
||||
*/
|
||||
float GetEpoxyThickness() const noexcept
|
||||
{
|
||||
return m_epoxyThickness3DU;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current non copper layers thickness.
|
||||
*
|
||||
* @return thickness in 3D units of non copper layers.
|
||||
*/
|
||||
float GetNonCopperLayerThickness() const noexcept
|
||||
{
|
||||
return m_nonCopperLayerThickness3DU;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current copper layer thickness.
|
||||
*
|
||||
* @return thickness in 3D units of copper layers.
|
||||
*/
|
||||
float GetCopperThickness() const noexcept
|
||||
{
|
||||
return m_copperThickness3DU;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current copper layer thickness.
|
||||
*
|
||||
* @return thickness in board units.
|
||||
*/
|
||||
int GetHolePlatingThickness() const noexcept;
|
||||
|
||||
/**
|
||||
* Get the board size.
|
||||
*
|
||||
* @return size in BIU units.
|
||||
*/
|
||||
wxSize GetBoardSize() const noexcept
|
||||
{
|
||||
return m_boardSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the board center.
|
||||
*
|
||||
* @return position in BIU units.
|
||||
*/
|
||||
wxPoint GetBoardPos() const noexcept
|
||||
{
|
||||
return m_boardPos;
|
||||
}
|
||||
|
||||
/**
|
||||
* The board center position in 3D units.
|
||||
*
|
||||
* @return board center vector position in 3D units.
|
||||
*/
|
||||
const SFVEC3F& GetBoardCenter() const noexcept
|
||||
{
|
||||
return m_boardCenter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the position of the footprint in 3d integer units considering if it is flipped or not.
|
||||
*
|
||||
* @param aIsFlipped true for use in footprints on Front (top) layer, false
|
||||
* if footprint is on back (bottom) layer.
|
||||
* @return the Z position of 3D shapes, in 3D integer units.
|
||||
*/
|
||||
float GetFootprintZPos( bool aIsFlipped ) const ;
|
||||
|
||||
/**
|
||||
* Get the current grid.
|
||||
*
|
||||
* @return space type of the grid.
|
||||
*/
|
||||
GRID3D_TYPE GetGridType() const noexcept
|
||||
{
|
||||
return m_gridType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current grid.
|
||||
*
|
||||
* @param aGridType the type space of the grid.
|
||||
*/
|
||||
void SetGridType( GRID3D_TYPE aGridType ) noexcept
|
||||
{
|
||||
m_gridType = aGridType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current antialiasing mode value.
|
||||
*
|
||||
* @return antialiasing mode value
|
||||
*/
|
||||
ANTIALIASING_MODE GetAntiAliasingMode() const { return m_antiAliasingMode; }
|
||||
|
||||
/**
|
||||
* Set the current antialiasing mode value.
|
||||
*
|
||||
* @param aAAmode antialiasing mode value.
|
||||
*/
|
||||
void SetAntiAliasingMode( ANTIALIASING_MODE aAAmode ) { m_antiAliasingMode = aAAmode; }
|
||||
|
||||
/**
|
||||
* @param aRenderEngine the render engine mode selected.
|
||||
*/
|
||||
void SetRenderEngine( RENDER_ENGINE aRenderEngine ) noexcept
|
||||
{
|
||||
m_renderEngine = aRenderEngine;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return render engine on use.
|
||||
*/
|
||||
RENDER_ENGINE GetRenderEngine() const noexcept
|
||||
{
|
||||
return m_renderEngine;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param aMaterialMode the render material mode.
|
||||
*/
|
||||
void SetMaterialMode( MATERIAL_MODE aMaterialMode ) noexcept
|
||||
{
|
||||
m_materialMode = aMaterialMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return material rendering mode.
|
||||
*/
|
||||
MATERIAL_MODE GetMaterialMode() const noexcept
|
||||
{
|
||||
return m_materialMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current polygon of the epoxy board.
|
||||
*
|
||||
* @return the shape polygon
|
||||
*/
|
||||
const SHAPE_POLY_SET& GetBoardPoly() const noexcept
|
||||
{
|
||||
return m_board_poly;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the technical color of a layer.
|
||||
*
|
||||
* @param aLayerId the layer to get the color information.
|
||||
* @return the color in SFVEC3F format.
|
||||
*/
|
||||
SFVEC4F GetLayerColor( PCB_LAYER_ID aLayerId ) const;
|
||||
|
||||
/**
|
||||
* Get the technical color of a layer.
|
||||
*
|
||||
* @param aItemId the item id to get the color information.
|
||||
* @return the color in SFVEC3F format.
|
||||
*/
|
||||
SFVEC4F GetItemColor( int aItemId ) const;
|
||||
|
||||
/**
|
||||
* @param[in] aColor is the color mapped.
|
||||
* @return the color in SFVEC3F format
|
||||
*/
|
||||
SFVEC4F GetColor( const COLOR4D& aColor ) const;
|
||||
|
||||
/**
|
||||
* Get the top z position.
|
||||
*
|
||||
* @param aLayerId layer id.
|
||||
* @return position in 3D units.
|
||||
*/
|
||||
float GetLayerTopZPos( PCB_LAYER_ID aLayerId ) const noexcept
|
||||
{
|
||||
return m_layerZcoordTop[aLayerId];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bottom z position.
|
||||
*
|
||||
* @param aLayerId layer id.
|
||||
* @return position in 3D units.
|
||||
*/
|
||||
float GetLayerBottomZPos( PCB_LAYER_ID aLayerId ) const noexcept
|
||||
{
|
||||
return m_layerZcoordBottom[aLayerId];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the map of containers that have the objects per layer.
|
||||
*
|
||||
* @return the map containers of this board.
|
||||
*/
|
||||
const MAP_CONTAINER_2D_BASE& GetLayerMap() const noexcept
|
||||
{
|
||||
return m_layerMap;
|
||||
}
|
||||
|
||||
const BVH_CONTAINER_2D* GetPlatedPadsFront() const noexcept
|
||||
{
|
||||
return m_platedPadsFront;
|
||||
}
|
||||
|
||||
const BVH_CONTAINER_2D* GetPlatedPadsBack() const noexcept
|
||||
{
|
||||
return m_platedPadsBack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the map of container that have the holes per layer.
|
||||
*
|
||||
* @return the map containers of holes from this board.
|
||||
*/
|
||||
const MAP_CONTAINER_2D_BASE& GetLayerHoleMap() const noexcept
|
||||
{
|
||||
return m_layerHoleMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the inflated through hole outside diameters container.
|
||||
*
|
||||
* @return a container with holes.
|
||||
*/
|
||||
const BVH_CONTAINER_2D& GetThroughHoleOds() const noexcept
|
||||
{
|
||||
return m_throughHoleOds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the through hole annular rings container.
|
||||
*
|
||||
* @return a container with through hole annular rings.
|
||||
*/
|
||||
const BVH_CONTAINER_2D& GetThroughHoleAnnularRings() const noexcept
|
||||
{
|
||||
return m_throughHoleAnnularRings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get through hole outside diameter 2D polygons.
|
||||
*
|
||||
* The outside diameter 2D polygon is the hole diameter plus the plating thickness.
|
||||
*
|
||||
* @return a container with through hold outside diameter 2D polygons.
|
||||
*/
|
||||
const SHAPE_POLY_SET& GetThroughHoleOdPolys() const noexcept
|
||||
{
|
||||
return m_throughHoleOdPolys;
|
||||
}
|
||||
|
||||
const SHAPE_POLY_SET& GetThroughHoleAnnularRingPolys() const noexcept
|
||||
{
|
||||
return m_throughHoleAnnularRingPolys;
|
||||
}
|
||||
|
||||
const SHAPE_POLY_SET& GetOuterNonPlatedThroughHolePoly() const noexcept
|
||||
{
|
||||
return m_nonPlatedThroughHoleOdPolys;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a container with through hole via hole outside diameters.
|
||||
*/
|
||||
const BVH_CONTAINER_2D& GetThroughHoleViaOds() const noexcept
|
||||
{
|
||||
return m_throughHoleViaOds;
|
||||
}
|
||||
|
||||
const SHAPE_POLY_SET& GetThroughHoleViaOdPolys() const noexcept
|
||||
{
|
||||
return m_throughHoleViaOdPolys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the through hole inner diameter container.
|
||||
*
|
||||
* @return a container with holes inner diameters.
|
||||
*/
|
||||
const BVH_CONTAINER_2D& GetThroughHoleIds() const noexcept
|
||||
{
|
||||
return m_throughHoleIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of vias in this board.
|
||||
*
|
||||
* @return number of vias.
|
||||
*/
|
||||
unsigned int GetViaCount() const noexcept
|
||||
{
|
||||
return m_viaCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of holes in this board.
|
||||
*
|
||||
* @return number of holes.
|
||||
*/
|
||||
unsigned int GetHoleCount() const noexcept
|
||||
{
|
||||
return m_holeCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Thee average diameter of the via holes.
|
||||
*
|
||||
* @return via hole average diameter dimension in 3D units.
|
||||
*/
|
||||
float GetAverageViaHoleDiameter() const noexcept
|
||||
{
|
||||
return m_averageViaHoleDiameter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Average diameter of through holes.
|
||||
*
|
||||
* @return the average diameter of through holes in 3D units.
|
||||
*/
|
||||
float GetAverageHoleDiameter() const noexcept
|
||||
{
|
||||
return m_averageHoleDiameter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Average width of the tracks.
|
||||
*
|
||||
* @return average track width in 3D units.
|
||||
*/
|
||||
float GetAverageTrackWidth() const noexcept
|
||||
{
|
||||
return m_averageTrackWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param aDiameter3DU diameter in 3DU.
|
||||
* @return number of sides that should be used in a circle with \a aDiameter3DU.
|
||||
*/
|
||||
unsigned int GetCircleSegmentCount( float aDiameter3DU ) const;
|
||||
|
||||
/**
|
||||
* @param aDiameterBIU diameter in board internal units.
|
||||
* @return number of sides that should be used in circle with \a aDiameterBIU.
|
||||
*/
|
||||
unsigned int GetCircleSegmentCount( int aDiameterBIU ) const;
|
||||
|
||||
/**
|
||||
* Get map of polygon's layers.
|
||||
*
|
||||
* @return the map with polygon's layers.
|
||||
*/
|
||||
const MAP_POLY& GetPolyMap() const noexcept
|
||||
{
|
||||
return m_layers_poly;
|
||||
}
|
||||
|
||||
const SHAPE_POLY_SET* GetFrontPlatedPadPolys()
|
||||
{
|
||||
return m_frontPlatedPadPolys;
|
||||
}
|
||||
|
||||
const SHAPE_POLY_SET* GetBackPlatedPadPolys()
|
||||
{
|
||||
return m_backPlatedPadPolys;
|
||||
}
|
||||
|
||||
const MAP_POLY& GetHoleIdPolysMap() const noexcept
|
||||
{
|
||||
return m_layerHoleIdPolys;
|
||||
}
|
||||
|
||||
const MAP_POLY& GetHoleOdPolysMap() const noexcept
|
||||
{
|
||||
return m_layerHoleOdPolys;
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Create the board outline polygon.
|
||||
*
|
||||
* @return false if the outline could not be created
|
||||
*/
|
||||
bool createBoardPolygon( wxString* aErrorMsg );
|
||||
void createLayers( REPORTER* aStatusReporter );
|
||||
void destroyLayers();
|
||||
|
||||
// Helper functions to create the board
|
||||
void createTrack( const PCB_TRACK* aTrack, CONTAINER_2D_BASE* aDstContainer,
|
||||
int aClearanceValue );
|
||||
|
||||
void createPadWithClearance( const PAD *aPad, CONTAINER_2D_BASE* aDstContainer,
|
||||
PCB_LAYER_ID aLayer, const wxSize& aClearanceValue ) const;
|
||||
|
||||
OBJECT_2D* createPadWithDrill( const PAD* aPad, int aInflateValue );
|
||||
|
||||
void addPadsWithClearance( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aDstContainer,
|
||||
PCB_LAYER_ID aLayerId, int aInflateValue,
|
||||
bool aSkipNPTHPadsWihNoCopper, bool aSkipPlatedPads,
|
||||
bool aSkipNonPlatedPads );
|
||||
|
||||
void addFootprintShapesWithClearance( const FOOTPRINT* aFootprint,
|
||||
CONTAINER_2D_BASE* aDstContainer,
|
||||
PCB_LAYER_ID aLayerId, int aInflateValue );
|
||||
|
||||
void addShapeWithClearance( const PCB_TEXT* aText, CONTAINER_2D_BASE* aDstContainer,
|
||||
PCB_LAYER_ID aLayerId, int aClearanceValue );
|
||||
|
||||
void addShapeWithClearance( const PCB_SHAPE* aShape, CONTAINER_2D_BASE* aDstContainer,
|
||||
PCB_LAYER_ID aLayerId, int aClearanceValue );
|
||||
|
||||
void addShapeWithClearance( const PCB_DIMENSION_BASE* aDimension,
|
||||
CONTAINER_2D_BASE* aDstContainer, PCB_LAYER_ID aLayerId,
|
||||
int aClearanceValue );
|
||||
|
||||
void addSolidAreasShapes( const ZONE* aZoneContainer, CONTAINER_2D_BASE* aDstContainer,
|
||||
PCB_LAYER_ID aLayerId );
|
||||
|
||||
void transformArcToSegments( const wxPoint& aCentre, const wxPoint& aStart, double aArcAngle,
|
||||
int aCircleToSegmentsCount, int aWidth,
|
||||
CONTAINER_2D_BASE* aDstContainer, const BOARD_ITEM& aBoardItem );
|
||||
|
||||
void buildPadOutlineAsSegments( const PAD* aPad, CONTAINER_2D_BASE* aDstContainer, int aWidth );
|
||||
|
||||
// Helper functions to create poly contours
|
||||
void buildPadOutlineAsPolygon( const PAD* aPad, SHAPE_POLY_SET& aCornerBuffer,
|
||||
int aWidth) const;
|
||||
|
||||
void transformFPShapesToPolygon( const FOOTPRINT* aFootprint, PCB_LAYER_ID aLayer,
|
||||
SHAPE_POLY_SET& aCornerBuffer ) const;
|
||||
|
||||
public:
|
||||
static CUSTOM_COLORS_LIST g_SilkscreenColors;
|
||||
static CUSTOM_COLORS_LIST g_MaskColors;
|
||||
static CUSTOM_COLORS_LIST g_PasteColors;
|
||||
static CUSTOM_COLORS_LIST g_FinishColors;
|
||||
static CUSTOM_COLORS_LIST g_BoardColors;
|
||||
|
||||
static KIGFX::COLOR4D g_DefaultBackgroundTop;
|
||||
static KIGFX::COLOR4D g_DefaultBackgroundBot;
|
||||
static KIGFX::COLOR4D g_DefaultSilkscreen;
|
||||
static KIGFX::COLOR4D g_DefaultSolderMask;
|
||||
static KIGFX::COLOR4D g_DefaultSolderPaste;
|
||||
static KIGFX::COLOR4D g_DefaultSurfaceFinish;
|
||||
static KIGFX::COLOR4D g_DefaultBoardBody;
|
||||
|
||||
public:
|
||||
SFVEC4F m_BgColorBot; ///< background bottom color
|
||||
SFVEC4F m_BgColorTop; ///< background top color
|
||||
SFVEC4F m_BoardBodyColor; ///< in realistic mode: FR4 board color
|
||||
SFVEC4F m_SolderMaskColorBot; ///< in realistic mode: solder mask color ( bot )
|
||||
SFVEC4F m_SolderMaskColorTop; ///< in realistic mode: solder mask color ( top )
|
||||
SFVEC4F m_SolderPasteColor; ///< in realistic mode: solder paste color
|
||||
SFVEC4F m_SilkScreenColorBot; ///< in realistic mode: SilkScreen color ( bot )
|
||||
SFVEC4F m_SilkScreenColorTop; ///< in realistic mode: SilkScreen color ( top )
|
||||
SFVEC4F m_CopperColor; ///< in realistic mode: copper color
|
||||
|
||||
SFVEC3F m_OpenGlSelectionColor;
|
||||
|
||||
// Raytracing light colors
|
||||
SFVEC3F m_RtCameraLightColor;
|
||||
SFVEC3F m_RtLightColorTop;
|
||||
SFVEC3F m_RtLightColorBottom;
|
||||
|
||||
std::vector<SFVEC3F> m_RtLightColor;
|
||||
std::vector<SFVEC2F> m_RtLightSphericalCoords;
|
||||
|
||||
// Raytracing options
|
||||
int m_RtShadowSampleCount;
|
||||
int m_RtReflectionSampleCount;
|
||||
int m_RtRefractionSampleCount;
|
||||
int m_RtRecursiveReflectionCount;
|
||||
int m_RtRecursiveRefractionCount;
|
||||
|
||||
float m_RtSpreadShadows;
|
||||
float m_RtSpreadReflections;
|
||||
float m_RtSpreadRefractions;
|
||||
|
||||
private:
|
||||
BOARD* m_board;
|
||||
S3D_CACHE* m_3dModelManager;
|
||||
COLOR_SETTINGS* m_colors;
|
||||
|
||||
std::vector< bool > m_drawFlags;
|
||||
GRID3D_TYPE m_gridType;
|
||||
RENDER_ENGINE m_renderEngine;
|
||||
MATERIAL_MODE m_materialMode;
|
||||
ANTIALIASING_MODE m_antiAliasingMode;
|
||||
|
||||
|
||||
wxPoint m_boardPos; ///< Board center position in board internal units.
|
||||
wxSize m_boardSize; ///< Board size in board internal units.
|
||||
SFVEC3F m_boardCenter; ///< 3D center position of the board in 3D units.
|
||||
BBOX_3D m_boardBoundingBox; ///< 3D bounding box of the board in 3D units.
|
||||
|
||||
|
||||
///< Polygon contours for each layer.
|
||||
MAP_POLY m_layers_poly;
|
||||
|
||||
SHAPE_POLY_SET* m_frontPlatedPadPolys;
|
||||
SHAPE_POLY_SET* m_backPlatedPadPolys;
|
||||
|
||||
///< Polygon contours for hole outer diameters for each layer.
|
||||
MAP_POLY m_layerHoleOdPolys;
|
||||
|
||||
///< Polygon contours for hole inner diameters for each layer.
|
||||
MAP_POLY m_layerHoleIdPolys;
|
||||
|
||||
///< Polygon contours for non plated through hole outer diameters.
|
||||
SHAPE_POLY_SET m_nonPlatedThroughHoleOdPolys;
|
||||
|
||||
///< Polygon contours for through hole outer diameters.
|
||||
SHAPE_POLY_SET m_throughHoleOdPolys;
|
||||
|
||||
///< Polygon contours for through holes via outer diameters.
|
||||
SHAPE_POLY_SET m_throughHoleViaOdPolys;
|
||||
|
||||
///< Polygon contours for through hole via annular rings.
|
||||
SHAPE_POLY_SET m_throughHoleAnnularRingPolys;
|
||||
|
||||
SHAPE_POLY_SET m_board_poly; ///< Board outline polygon.
|
||||
|
||||
MAP_CONTAINER_2D_BASE m_layerMap; ///< 2D elements for each layer.
|
||||
|
||||
|
||||
BVH_CONTAINER_2D* m_platedPadsFront;
|
||||
BVH_CONTAINER_2D* m_platedPadsBack;
|
||||
|
||||
///< The holes per each layer.
|
||||
MAP_CONTAINER_2D_BASE m_layerHoleMap;
|
||||
|
||||
///< List of through holes with the radius of the hole inflated with the copper thickness.
|
||||
BVH_CONTAINER_2D m_throughHoleOds;
|
||||
|
||||
///< List of plated through hole annular rings.
|
||||
BVH_CONTAINER_2D m_throughHoleAnnularRings;
|
||||
|
||||
///< List of through hole inner diameters.
|
||||
BVH_CONTAINER_2D m_throughHoleIds;
|
||||
|
||||
///< List of through hole vias with the radius of the hole inflated with the copper thickness.
|
||||
BVH_CONTAINER_2D m_throughHoleViaOds;
|
||||
|
||||
///< List of through hole via inner diameters.
|
||||
BVH_CONTAINER_2D m_throughHoleViaIds;
|
||||
|
||||
///< Number of copper layers actually used by the board.
|
||||
unsigned int m_copperLayersCount;
|
||||
|
||||
///< Scale factor to convert board internal units to 3D units normalized between -1.0 and 1.0.
|
||||
double m_biuTo3Dunits;
|
||||
|
||||
///< Top (End) Z position of each layer in 3D units.
|
||||
std::array<float, PCB_LAYER_ID_COUNT> m_layerZcoordTop;
|
||||
|
||||
///< Bottom (Start) Z position of each layer in 3D units.
|
||||
std::array<float, PCB_LAYER_ID_COUNT> m_layerZcoordBottom;
|
||||
|
||||
///< Copper thickness in 3D units.
|
||||
float m_copperThickness3DU;
|
||||
|
||||
///< Epoxy thickness in 3D units.
|
||||
float m_epoxyThickness3DU;
|
||||
|
||||
///< Non copper layers thickness in 3D units.
|
||||
float m_nonCopperLayerThickness3DU;
|
||||
|
||||
///< solder paste layers thickness in 3D units.
|
||||
float m_solderPasteLayerThickness3DU;
|
||||
|
||||
///< Number of tracks in the board.
|
||||
unsigned int m_trackCount;
|
||||
|
||||
///< Track average width.
|
||||
float m_averageTrackWidth;
|
||||
|
||||
///< Number of through hole vias in the board.
|
||||
unsigned int m_viaCount;
|
||||
|
||||
///< Computed average diameter of the via holes in 3D units.
|
||||
float m_averageViaHoleDiameter;
|
||||
|
||||
///< Number of holes in the board.
|
||||
unsigned int m_holeCount;
|
||||
|
||||
///< Computed average diameter of the holes in 3D units.
|
||||
float m_averageHoleDiameter;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
};
|
||||
|
||||
|
||||
class EDA_3D_BOARD_HOLDER
|
||||
{
|
||||
public:
|
||||
virtual BOARD_ADAPTER& GetAdapter() = 0;
|
||||
virtual CAMERA& GetCurrentCamera() = 0;
|
||||
|
||||
virtual ~EDA_3D_BOARD_HOLDER() {};
|
||||
};
|
||||
|
||||
#endif // BOARD_ADAPTER_H
|
||||
@@ -0,0 +1,517 @@
|
||||
/*
|
||||
* 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_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 (board outlines + items)
|
||||
// to ensure any item, even outside the board outlines can be seen
|
||||
EDA_RECT 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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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 );
|
||||
}
|
||||
@@ -0,0 +1,677 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/// 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
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
||||
* 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-2020 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
@@ -25,54 +25,219 @@
|
||||
/**
|
||||
* @file create_layer_poly.cpp
|
||||
* @brief This file implements the creation of the pcb board items in the poly
|
||||
* contours format.
|
||||
* 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 "board_adapter.h"
|
||||
#include "cinfo3d_visu.h"
|
||||
#include <convert_basic_shapes_to_polygon.h>
|
||||
#include <fp_shape.h>
|
||||
#include <footprint.h>
|
||||
#include <class_edge_mod.h>
|
||||
#include <class_module.h>
|
||||
|
||||
|
||||
void BOARD_ADAPTER::buildPadOutlineAsPolygon( const PAD* aPad, SHAPE_POLY_SET& aCornerBuffer,
|
||||
int aWidth ) const
|
||||
// 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
|
||||
{
|
||||
if( aPad->GetShape() == PAD_SHAPE::CIRCLE ) // Draw a ring
|
||||
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() )
|
||||
{
|
||||
TransformRingToPolygon( aCornerBuffer, aPad->ShapePos(), aPad->GetSize().x / 2,
|
||||
aWidth, ARC_HIGH_DEF, ERROR_INSIDE );
|
||||
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, add outlines as thick segments in polygon buffer
|
||||
const std::shared_ptr<SHAPE_POLY_SET>& corners = aPad->GetEffectivePolygon();
|
||||
const SHAPE_LINE_CHAIN& path = corners->COutline( 0 );
|
||||
|
||||
// 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 );
|
||||
|
||||
TransformOvalToPolygon( aCornerBuffer, (wxPoint) a, (wxPoint) b, aWidth, ARC_HIGH_DEF,
|
||||
ERROR_INSIDE );
|
||||
TransformRoundedEndsSegmentToPolygon( aCornerBuffer,
|
||||
wxPoint( a.x, a.y ),
|
||||
wxPoint( b.x, b.y ),
|
||||
nr_sides_per_circle,
|
||||
aWidth );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BOARD_ADAPTER::transformFPShapesToPolygon( const FOOTPRINT* aFootprint, PCB_LAYER_ID aLayer,
|
||||
SHAPE_POLY_SET& aCornerBuffer ) const
|
||||
// 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
|
||||
{
|
||||
for( BOARD_ITEM* item : aFootprint->GraphicalItems() )
|
||||
{
|
||||
if( item->Type() == PCB_FP_SHAPE_T )
|
||||
{
|
||||
FP_SHAPE* outline = (FP_SHAPE*) item;
|
||||
const D_PAD* pad = aPads;
|
||||
|
||||
if( outline->GetLayer() == aLayer )
|
||||
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 )) )
|
||||
{
|
||||
outline->TransformShapeWithClearanceToPolygon( aCornerBuffer, aLayer, 0,
|
||||
ARC_HIGH_DEF, ERROR_INSIDE );
|
||||
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
+156
-144
@@ -2,7 +2,7 @@
|
||||
* 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-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2020 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
|
||||
@@ -22,24 +22,28 @@
|
||||
* 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 <atomic>
|
||||
#include "board_adapter.h"
|
||||
#include "3d_rendering/raytracing/accelerators/accelerator_3d.h"
|
||||
#include "3d_rendering/render_3d_base.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>
|
||||
|
||||
|
||||
class WX_INFOBAR;
|
||||
class wxStatusBar;
|
||||
class BOARD;
|
||||
class RENDER_3D_RAYTRACE;
|
||||
class RENDER_3D_OPENGL;
|
||||
#include <wx/statusbr.h>
|
||||
#include <pcb_base_frame.h>
|
||||
|
||||
|
||||
/**
|
||||
@@ -47,46 +51,32 @@ class RENDER_3D_OPENGL;
|
||||
*/
|
||||
class EDA_3D_CANVAS : public HIDPI_GL_CANVAS
|
||||
{
|
||||
public:
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Create a new 3D Canvas with an 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.
|
||||
* @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,
|
||||
BOARD_ADAPTER& aSettings, CAMERA& aCamera, S3D_CACHE* a3DCachePointer );
|
||||
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();
|
||||
|
||||
/**
|
||||
* Set a dispatcher that processes events and forwards them to tools.
|
||||
*
|
||||
* #DRAW_PANEL_GAL does not take over the ownership. Passing NULL disconnects all event
|
||||
* handlers from the DRAW_PANEL_GAL and parent frame.
|
||||
*
|
||||
* @param aEventDispatcher is the object that will be used for dispatching events.
|
||||
*/
|
||||
void SetEventDispatcher( TOOL_DISPATCHER* aEventDispatcher );
|
||||
void SetStatusBar( wxStatusBar *aStatusBar ) { m_parentStatusBar = aStatusBar; }
|
||||
|
||||
void SetStatusBar( wxStatusBar* aStatusBar )
|
||||
{
|
||||
m_parentStatusBar = aStatusBar;
|
||||
}
|
||||
|
||||
void SetInfoBar( WX_INFOBAR* aInfoBar )
|
||||
{
|
||||
m_parentInfoBar = aInfoBar;
|
||||
}
|
||||
|
||||
void ReloadRequest( BOARD* aBoard = nullptr, S3D_CACHE* aCachePointer = nullptr );
|
||||
void ReloadRequest( BOARD *aBoard = NULL, S3D_CACHE *aCachePointer = NULL );
|
||||
|
||||
/**
|
||||
* Query if there is a pending reload request.
|
||||
*
|
||||
* @return true if it wants to reload, false if there is no reload pending.
|
||||
* @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
|
||||
{
|
||||
@@ -97,187 +87,209 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the current render ( a RENDER_3D_RAYTRACE* or a RENDER_3D_OPENGL* render )
|
||||
*/
|
||||
RENDER_3D_BASE* GetCurrentRender() const { return m_3d_render; }
|
||||
|
||||
/**
|
||||
* Request to render the current view in Raytracing mode.
|
||||
* @brief RenderRaytracingRequest - Request to render the current view in Raytracing mode
|
||||
*/
|
||||
void RenderRaytracingRequest();
|
||||
|
||||
/**
|
||||
* Request a screenshot and output it to the \a aDstImage
|
||||
*
|
||||
* Request a screenshot and output it to the aDstImage
|
||||
* @param aDstImage - Screenshot destination image
|
||||
*/
|
||||
void GetScreenshot( wxImage& aDstImage );
|
||||
void GetScreenshot( wxImage &aDstImage );
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @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 );
|
||||
|
||||
/**
|
||||
* Enable or disable camera animation when switching to a pre-defined view.
|
||||
*/
|
||||
void SetAnimationEnabled( bool aEnable ) { m_animation_enabled = aEnable; }
|
||||
bool GetAnimationEnabled() const { return m_animation_enabled; }
|
||||
|
||||
/**
|
||||
* Set the camera animation moving speed multiplier option.
|
||||
*
|
||||
* @param aMultiplier one of the possible integer options: [1,2,3,4,5].
|
||||
*/
|
||||
void SetMovingSpeedMultiplier( int aMultiplier ) { m_moving_speed_multiplier = aMultiplier; }
|
||||
int GetMovingSpeedMultiplier() const { return m_moving_speed_multiplier; }
|
||||
|
||||
int GetProjectionMode() const { return (int) m_camera.GetProjection(); };
|
||||
void SetProjectionMode( int aMode ) { m_camera.SetProjection( (PROJECTION_TYPE) aMode ); }
|
||||
|
||||
/**
|
||||
* Notify that the render engine was changed.
|
||||
* @brief RenderEngineChanged - Notify that the render engine was changed
|
||||
*/
|
||||
void RenderEngineChanged();
|
||||
|
||||
/**
|
||||
* Update the status bar with the position information.
|
||||
* @brief DisplayStatus - Update the status bar with the position information
|
||||
*/
|
||||
void DisplayStatus();
|
||||
|
||||
/**
|
||||
* Schedule a refresh update of the canvas.
|
||||
*
|
||||
* @param aRedrawImmediately true will request a redraw, false will schedule a redraw
|
||||
* after a short timeout.
|
||||
* @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; }
|
||||
|
||||
/**
|
||||
* Used to forward events to the canvas from popups, etc.
|
||||
* Return a structure containing currently used hotkey mapping.
|
||||
*/
|
||||
void OnEvent( wxEvent& aEvent );
|
||||
EDA_HOTKEY_CONFIG* GetHotkeyConfig() const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Called by a wxPaintEvent event
|
||||
|
||||
/** Called by a wxPaintEvent event
|
||||
*/
|
||||
void OnPaint( wxPaintEvent& aEvent );
|
||||
|
||||
/**
|
||||
* The actual function to repaint the canvas.
|
||||
*
|
||||
* It is usually called by OnPaint() but because it does not use a wxPaintDC it can be
|
||||
* called outside a wxPaintEvent
|
||||
* It is usually called by OnPaint() but because it does not use a wxPaintDC
|
||||
* it can be called outside a wxPaintEvent
|
||||
*/
|
||||
void DoRePaint();
|
||||
|
||||
void OnEraseBackground( wxEraseEvent& event );
|
||||
void OnEraseBackground( wxEraseEvent &event );
|
||||
|
||||
void OnRefreshRequest( wxEvent& aEvent );
|
||||
|
||||
void OnMouseWheel( wxMouseEvent& 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 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 );
|
||||
void OnCloseWindow( wxCloseEvent& event );
|
||||
void OnResize( wxSizeEvent& 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:
|
||||
|
||||
/**
|
||||
*Stop the editing time so it will not timeout.
|
||||
* @brief stop_editingTimeOut_Timer - stop the editing time, so it will not timeout
|
||||
*/
|
||||
void stop_editingTimeOut_Timer();
|
||||
|
||||
|
||||
/**
|
||||
* Reset the editing timer.
|
||||
* @brief restart_editingTimeOut_Timer - reset the editing timer
|
||||
*/
|
||||
void restart_editingTimeOut_Timer();
|
||||
|
||||
/**
|
||||
* 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 );
|
||||
|
||||
/**
|
||||
* This function hits a ray to the board and start a movement.
|
||||
* @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();
|
||||
|
||||
|
||||
/**
|
||||
* Render the pivot cursor.
|
||||
*
|
||||
* @param t time between 0.0 and 1.0.
|
||||
* @param aScale scale to apply on the cursor.
|
||||
* @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 );
|
||||
|
||||
/**
|
||||
* @return true if OpenGL initialization succeeded.
|
||||
* @brief initializeOpenGL
|
||||
* @return if OpenGL initialization succeed
|
||||
*/
|
||||
bool initializeOpenGL();
|
||||
|
||||
/**
|
||||
* Free created targets and openGL context.
|
||||
* @brief releaseOpenGL - free created targets and openGL context
|
||||
*/
|
||||
void releaseOpenGL();
|
||||
|
||||
RAY getRayAtCurrrentMousePosition();
|
||||
private:
|
||||
|
||||
private:
|
||||
TOOL_DISPATCHER* m_eventDispatcher;
|
||||
wxStatusBar* m_parentStatusBar; // Parent statusbar to report progress
|
||||
WX_INFOBAR* m_parentInfoBar;
|
||||
/// current OpenGL context
|
||||
wxGLContext *m_glRC;
|
||||
|
||||
wxGLContext* m_glRC; // Current OpenGL context
|
||||
bool m_is_opengl_initialized;
|
||||
bool m_is_opengl_version_supported;
|
||||
/// Parent statusbar to report progress
|
||||
wxStatusBar *m_parentStatusBar;
|
||||
|
||||
wxTimer m_editing_timeout_timer; // Expires after some time signaling that
|
||||
// the mouse / keyboard movements are over
|
||||
wxTimer m_redraw_trigger_timer; // Used to schedule a redraw event
|
||||
std::atomic_flag m_is_currently_painting; // Avoid drawing twice at the same time
|
||||
/// Time timeout will expires after some time sinalizing that the mouse /
|
||||
/// keyboard movements are over.
|
||||
wxTimer m_editing_timeout_timer;
|
||||
|
||||
bool m_mouse_is_moving; // Mouse activity is in progress
|
||||
bool m_mouse_was_moved;
|
||||
bool m_camera_is_moving; // Camera animation is ongoing
|
||||
bool m_render_pivot; // Render the pivot while camera moving
|
||||
float m_camera_moving_speed; // 1.0f will be 1:1
|
||||
unsigned m_strtime_camera_movement; // Ticktime of camera movement start
|
||||
bool m_animation_enabled; // Camera animation enabled
|
||||
int m_moving_speed_multiplier; // Camera animation speed multiplier option
|
||||
/// This timer will be used to schedule a redraw event
|
||||
wxTimer m_redraw_trigger_timer;
|
||||
|
||||
BOARD_ADAPTER& m_boardAdapter; // Pre-computed 3D info and settings
|
||||
CAMERA& m_camera;
|
||||
RENDER_3D_BASE* m_3d_render;
|
||||
RENDER_3D_RAYTRACE* m_3d_render_raytracing;
|
||||
RENDER_3D_OPENGL* m_3d_render_opengl;
|
||||
/// true if mouse activity is on progress
|
||||
bool m_mouse_is_moving;
|
||||
|
||||
static const float m_delta_move_step_factor; // Step factor to used with cursor on
|
||||
// relation to the current zoom
|
||||
/// true if there was some type of activity, it will be used to render in
|
||||
/// preview mode
|
||||
bool m_mouse_was_moved;
|
||||
|
||||
bool m_opengl_supports_raytracing;
|
||||
bool m_render_raytracing_was_requested;
|
||||
/// true if camera animation is ongoing
|
||||
bool m_camera_is_moving;
|
||||
|
||||
ACCELERATOR_3D* m_accelerator3DShapes; // used for mouse over searching
|
||||
/// activated the render of pivot while camera moving
|
||||
bool m_render_pivot;
|
||||
|
||||
BOARD_ITEM* m_currentRollOverItem;
|
||||
/// 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.
|
||||
@@ -285,7 +297,7 @@ private:
|
||||
* "KI_TRACE_EDA_3D_CANVAS". See the wxWidgets documentation on wxLogTrace for
|
||||
* more information.
|
||||
*/
|
||||
static const wxChar* m_logTrace;
|
||||
static const wxChar *m_logTrace;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* 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-2020 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
@@ -35,26 +35,26 @@
|
||||
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[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[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[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 );
|
||||
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 );
|
||||
@@ -81,27 +81,29 @@ void EDA_3D_CANVAS::render_pivot( float t , float aScale )
|
||||
if( t > 1.0f )
|
||||
t = 1.0f;
|
||||
|
||||
const SFVEC3F &lookAtPos = m_camera.GetLookAtPos_T1();
|
||||
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_camera.GetProjectionMatrix() ) );
|
||||
glLoadMatrixf( glm::value_ptr( m_settings.CameraGet().GetProjectionMatrix() ) );
|
||||
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glLoadIdentity();
|
||||
glLoadMatrixf( glm::value_ptr( m_camera.GetViewMatrix() ) );
|
||||
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;
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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_
|
||||
+23
-51
@@ -2,7 +2,7 @@
|
||||
* 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-2020 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
@@ -31,38 +31,22 @@
|
||||
#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,
|
||||
enum DISPLAY3D_FLG {
|
||||
FL_AXIS=0, FL_ZONE,
|
||||
FL_ADHESIVE, FL_SILKSCREEN, FL_SOLDERMASK, FL_SOLDERPASTE,
|
||||
FL_COMMENTS, FL_ECO,
|
||||
|
||||
FL_FP_ATTRIBUTES_NORMAL,
|
||||
FL_FP_ATTRIBUTES_NORMAL_INSERT,
|
||||
FL_FP_ATTRIBUTES_VIRTUAL,
|
||||
|
||||
FL_USE_SELECTION,
|
||||
FL_HIGHLIGHT_ROLLOVER_ITEM,
|
||||
FL_MODULE_ATTRIBUTES_NORMAL,
|
||||
FL_MODULE_ATTRIBUTES_NORMAL_INSERT,
|
||||
FL_MODULE_ATTRIBUTES_VIRTUAL,
|
||||
|
||||
FL_SHOW_BOARD_BODY,
|
||||
FL_MOUSEWHEEL_PANNING,
|
||||
FL_USE_REALISTIC_MODE,
|
||||
FL_SUBTRACT_MASK_FROM_SILK,
|
||||
FL_CLIP_SILK_ON_VIA_ANNULUS,
|
||||
FL_RENDER_PLATED_PADS_AS_PLATED,
|
||||
|
||||
// OpenGL options
|
||||
FL_RENDER_OPENGL_SHOW_MODEL_BBOX,
|
||||
FL_RENDER_OPENGL_COPPER_THICKNESS,
|
||||
FL_RENDER_OPENGL_AA_DISABLE_ON_MOVE,
|
||||
FL_RENDER_OPENGL_THICKNESS_DISABLE_ON_MOVE,
|
||||
FL_RENDER_OPENGL_VIAS_DISABLE_ON_MOVE,
|
||||
FL_RENDER_OPENGL_HOLES_DISABLE_ON_MOVE,
|
||||
|
||||
// Raytracing options
|
||||
FL_RENDER_RAYTRACING_SHADOWS,
|
||||
@@ -76,50 +60,38 @@ enum DISPLAY3D_FLG
|
||||
};
|
||||
|
||||
|
||||
/// Rotation direction for the 3d canvas
|
||||
enum class ROTATION_DIR
|
||||
{
|
||||
X_CW,
|
||||
X_CCW,
|
||||
Y_CW,
|
||||
Y_CCW,
|
||||
Z_CW,
|
||||
Z_CCW
|
||||
};
|
||||
|
||||
|
||||
/// Camera types
|
||||
enum class CAMERA_TYPE
|
||||
enum CAMERA_TYPE
|
||||
{
|
||||
TRACKBALL
|
||||
CAMERA_TRACKBALL
|
||||
};
|
||||
|
||||
|
||||
/// Grid types
|
||||
enum class GRID3D_TYPE
|
||||
enum GRID3D_TYPE
|
||||
{
|
||||
NONE,
|
||||
GRID_1MM,
|
||||
GRID_2P5MM,
|
||||
GRID_5MM,
|
||||
GRID_10MM
|
||||
GRID3D_NONE,
|
||||
GRID3D_1MM,
|
||||
GRID3D_2P5MM,
|
||||
GRID3D_5MM,
|
||||
GRID3D_10MM
|
||||
};
|
||||
|
||||
|
||||
/// Render engine mode
|
||||
enum class RENDER_ENGINE
|
||||
enum RENDER_ENGINE
|
||||
{
|
||||
OPENGL,
|
||||
RAYTRACING,
|
||||
RENDER_ENGINE_OPENGL_LEGACY,
|
||||
RENDER_ENGINE_RAYTRACING,
|
||||
};
|
||||
|
||||
|
||||
/// Render 3d model shape materials mode
|
||||
enum class MATERIAL_MODE
|
||||
enum MATERIAL_MODE
|
||||
{
|
||||
NORMAL, ///< Use all material properties from model file
|
||||
DIFFUSE_ONLY, ///< Use only diffuse material properties
|
||||
CAD_MODE ///< Use a gray shading based on diffuse material
|
||||
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_
|
||||
|
||||
@@ -30,9 +30,9 @@
|
||||
#ifndef _3D_FASTMATH_H
|
||||
#define _3D_FASTMATH_H
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
// Define this flag to use fast math optimizations
|
||||
|
||||
+39
-30
@@ -2,7 +2,7 @@
|
||||
* 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-2020 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
@@ -33,43 +33,44 @@
|
||||
#include <plugins/3dapi/xv3d_types.h>
|
||||
#include "3d_fastmath.h"
|
||||
|
||||
// https://en.wikipedia.org/wiki/Spherical_coordinate_system
|
||||
/**
|
||||
* https://en.wikipedia.org/wiki/Spherical_coordinate_system
|
||||
*
|
||||
* @brief SphericalToCartesian
|
||||
* @param aInclination θ ∈ [0, π]
|
||||
* @param aAzimuth φ ∈ [0, 2π]
|
||||
* @return Cartesian coordinates
|
||||
* @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 ),
|
||||
return SFVEC3F( sinInc * glm::cos( aAzimuth ),
|
||||
sinInc * glm::sin( aAzimuth ),
|
||||
glm::cos( aInclination ) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @todo This is not correct because it is not a gaussian random.
|
||||
*/
|
||||
inline SFVEC3F UniformRandomHemisphereDirection()
|
||||
// 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 );
|
||||
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 )
|
||||
inline SFVEC3F CosWeightedRandomHemisphereDirection( const SFVEC3F &n )
|
||||
{
|
||||
const float Xi1 = (float) rand() / (float) RAND_MAX;
|
||||
const float Xi2 = (float) rand() / (float) RAND_MAX;
|
||||
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;
|
||||
@@ -98,19 +99,21 @@ inline SFVEC3F CosWeightedRandomHemisphereDirection( const SFVEC3F& n )
|
||||
|
||||
|
||||
/**
|
||||
* @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.
|
||||
* @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 )
|
||||
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 );
|
||||
@@ -130,7 +133,11 @@ inline bool Refract( const SFVEC3F &aInVector, const SFVEC3F &aNormal, float aRi
|
||||
}
|
||||
|
||||
|
||||
inline float mapf( float x, float in_min, float in_max, float out_min, float out_max )
|
||||
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 );
|
||||
|
||||
@@ -147,15 +154,17 @@ inline float RGBtoGray( const SFVEC3F &aColor )
|
||||
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 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 );
|
||||
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;
|
||||
return (aDiffuseColor / SFVEC3F(maxValue) ) * 0.125f + luminance* 0.875f;
|
||||
}
|
||||
|
||||
|
||||
@@ -170,7 +179,7 @@ inline float QuadricEasingInOut( float t )
|
||||
{
|
||||
t = t - 1.0f;
|
||||
|
||||
return -2.0f * ( t * t ) + 1.0f;
|
||||
return -2.0f * (t * t) + 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,471 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* 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,450 +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-2021 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
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Implements a model viewer canvas. The purpose of the model viewer is to render
|
||||
* 3d models that come in the original data from the files without any transformations.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include "3d_rendering/opengl/3d_model.h"
|
||||
#include "eda_3d_model_viewer.h"
|
||||
#include "../3d_rendering/opengl/opengl_utils.h"
|
||||
#include "../3d_cache/3d_cache.h"
|
||||
#include <wx/dcclient.h>
|
||||
#include <base_units.h>
|
||||
#include <gl_context_mgr.h>
|
||||
#include <settings/common_settings.h>
|
||||
#include <pgm_base.h>
|
||||
#include <gal/dpi_scaling.h>
|
||||
|
||||
/**
|
||||
* Scale conversion 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.
|
||||
*
|
||||
* @ingroup trace_env_vars
|
||||
*/
|
||||
const wxChar* EDA_3D_MODEL_VIEWER::m_logTrace = wxT( "KI_TRACE_EDA_3D_MODEL_VIEWER" );
|
||||
|
||||
|
||||
BEGIN_EVENT_TABLE( EDA_3D_MODEL_VIEWER, wxGLCanvas )
|
||||
EVT_PAINT( EDA_3D_MODEL_VIEWER::OnPaint )
|
||||
|
||||
// mouse events
|
||||
EVT_LEFT_DOWN( EDA_3D_MODEL_VIEWER::OnLeftDown )
|
||||
EVT_LEFT_UP( EDA_3D_MODEL_VIEWER::OnLeftUp )
|
||||
EVT_MIDDLE_UP( EDA_3D_MODEL_VIEWER::OnMiddleUp )
|
||||
EVT_MIDDLE_DOWN( EDA_3D_MODEL_VIEWER::OnMiddleDown)
|
||||
EVT_RIGHT_DOWN( EDA_3D_MODEL_VIEWER::OnRightClick )
|
||||
EVT_MOUSEWHEEL( EDA_3D_MODEL_VIEWER::OnMouseWheel )
|
||||
EVT_MOTION( EDA_3D_MODEL_VIEWER::OnMouseMove )
|
||||
|
||||
#ifdef USE_OSX_MAGNIFY_EVENT
|
||||
EVT_MAGNIFY( EDA_3D_MODEL_VIEWER::OnMagnify )
|
||||
#endif
|
||||
|
||||
// other events
|
||||
EVT_ERASE_BACKGROUND( EDA_3D_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
|
||||
|
||||
|
||||
EDA_3D_MODEL_VIEWER::EDA_3D_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 * 4.0f ),
|
||||
m_cacheManager( aCacheManager )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "EDA_3D_MODEL_VIEWER::EDA_3D_MODEL_VIEWER" ) );
|
||||
|
||||
m_ogl_initialized = false;
|
||||
m_reload_is_needed = false;
|
||||
m_ogl_3dmodel = nullptr;
|
||||
m_3d_model = nullptr;
|
||||
m_BiuTo3dUnits = 1.0;
|
||||
|
||||
m_glRC = nullptr;
|
||||
|
||||
COMMON_SETTINGS* settings = Pgm().GetCommonSettings();
|
||||
|
||||
const DPI_SCALING dpi{ settings, this };
|
||||
SetScaleFactor( dpi.GetScaleFactor() );
|
||||
}
|
||||
|
||||
|
||||
EDA_3D_MODEL_VIEWER::~EDA_3D_MODEL_VIEWER()
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "EDA_3D_MODEL_VIEWER::~EDA_3D_MODEL_VIEWER" ) );
|
||||
|
||||
if( m_glRC )
|
||||
{
|
||||
GL_CONTEXT_MANAGER::Get().LockCtx( m_glRC, this );
|
||||
|
||||
delete m_ogl_3dmodel;
|
||||
m_ogl_3dmodel = nullptr;
|
||||
|
||||
GL_CONTEXT_MANAGER::Get().UnlockCtx( m_glRC );
|
||||
GL_CONTEXT_MANAGER::Get().DestroyCtx( m_glRC );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::Set3DModel( const S3DMODEL& a3DModel )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "EDA_3D_MODEL_VIEWER::Set3DModel with a S3DMODEL" ) );
|
||||
|
||||
// Validate a3DModel pointers
|
||||
wxASSERT( a3DModel.m_Materials != nullptr );
|
||||
wxASSERT( a3DModel.m_Meshes != nullptr );
|
||||
wxASSERT( a3DModel.m_MaterialsSize > 0 );
|
||||
wxASSERT( a3DModel.m_MeshesSize > 0 );
|
||||
|
||||
// Delete the old model
|
||||
delete m_ogl_3dmodel;
|
||||
m_ogl_3dmodel = nullptr;
|
||||
|
||||
m_3d_model = nullptr;
|
||||
|
||||
if( ( a3DModel.m_Materials != nullptr ) && ( a3DModel.m_Meshes != nullptr )
|
||||
&& ( a3DModel.m_MaterialsSize > 0 ) && ( a3DModel.m_MeshesSize > 0 ) )
|
||||
{
|
||||
m_3d_model = &a3DModel;
|
||||
m_reload_is_needed = true;
|
||||
}
|
||||
|
||||
Refresh();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::Set3DModel( const wxString& aModelPathName)
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "EDA_3D_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 EDA_3D_MODEL_VIEWER::Clear3DModel()
|
||||
{
|
||||
// Delete the old model
|
||||
m_reload_is_needed = false;
|
||||
|
||||
delete m_ogl_3dmodel;
|
||||
m_ogl_3dmodel = nullptr;
|
||||
|
||||
m_3d_model = nullptr;
|
||||
|
||||
Refresh();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_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 );
|
||||
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 EDA_3D_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 EDA_3D_MODEL_VIEWER::OnPaint( wxPaintEvent& event )
|
||||
{
|
||||
event.Skip( false );
|
||||
|
||||
// SwapBuffer requires the window to be shown before calling
|
||||
if( !IsShownOnScreen() )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "EDA_3D_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 == nullptr )
|
||||
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 = GetNativePixelSize();
|
||||
|
||||
if( !m_ogl_initialized )
|
||||
{
|
||||
m_ogl_initialized = true;
|
||||
ogl_initialize();
|
||||
}
|
||||
|
||||
if( m_reload_is_needed )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "EDA_3D_MODEL_VIEWER::OnPaint m_reload_is_needed" ) );
|
||||
|
||||
m_reload_is_needed = false;
|
||||
m_ogl_3dmodel = new MODEL_3D( *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 matrices
|
||||
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->BeginDrawMulti( true );
|
||||
|
||||
m_ogl_3dmodel->DrawOpaque( false );
|
||||
m_ogl_3dmodel->DrawTransparent( 1.0f, false );
|
||||
|
||||
m_ogl_3dmodel->EndDrawMulti();
|
||||
|
||||
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 );
|
||||
DrawRoundArrow( 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 );
|
||||
DrawRoundArrow( 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 );
|
||||
DrawRoundArrow( 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 EDA_3D_MODEL_VIEWER::OnEraseBackground( wxEraseEvent& event )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "EDA_3D_MODEL_VIEWER::OnEraseBackground" ) );
|
||||
// Do nothing, to avoid flashing.
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::OnMouseWheel( wxMouseEvent& event )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "EDA_3D_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 EDA_3D_MODEL_VIEWER::OnMagnify( wxMouseEvent& event )
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::OnMouseMove( wxMouseEvent& event )
|
||||
{
|
||||
const wxSize& nativeWinSize = GetNativePixelSize();
|
||||
const wxPoint& nativePosition = GetNativePosition( event.GetPosition() );
|
||||
|
||||
m_trackBallCamera.SetCurWindowSize( nativeWinSize );
|
||||
|
||||
if( event.Dragging() )
|
||||
{
|
||||
if( event.LeftIsDown() ) // Drag
|
||||
m_trackBallCamera.Drag( nativePosition );
|
||||
|
||||
// orientation has changed, redraw mesh
|
||||
Refresh( false );
|
||||
}
|
||||
|
||||
m_trackBallCamera.SetCurMousePosition( nativePosition );
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::OnLeftDown( wxMouseEvent& event )
|
||||
{
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::OnLeftUp( wxMouseEvent& event )
|
||||
{
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::OnMiddleDown( wxMouseEvent& event )
|
||||
{
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::OnMiddleUp( wxMouseEvent& event )
|
||||
{
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::OnRightClick( wxMouseEvent& event )
|
||||
{
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
@@ -1,141 +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-2021 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 purpose 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/track_ball.h"
|
||||
#include <gal/hidpi_gl_canvas.h>
|
||||
|
||||
class S3D_CACHE;
|
||||
class MODEL_3D;
|
||||
|
||||
/**
|
||||
* Implement a canvas based on a wxGLCanvas.
|
||||
*/
|
||||
class EDA_3D_MODEL_VIEWER : public HIDPI_GL_CANVAS
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Create 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 #OGL_ATT_LIST::GetAttributesList.
|
||||
*/
|
||||
EDA_3D_MODEL_VIEWER( wxWindow* aParent, const int* aAttribList = nullptr,
|
||||
S3D_CACHE* aCacheManager = nullptr );
|
||||
|
||||
~EDA_3D_MODEL_VIEWER();
|
||||
|
||||
/**
|
||||
* Set this model to be displayed.
|
||||
*
|
||||
* @param a3DModel 3D model data.
|
||||
*/
|
||||
void Set3DModel( const S3DMODEL& a3DModel );
|
||||
|
||||
/**
|
||||
* Set this model to be displayed.
|
||||
*
|
||||
* @param aModelPathName 3D model path name.
|
||||
*/
|
||||
void Set3DModel( const wxString& aModelPathName );
|
||||
|
||||
/**
|
||||
* Unload the displayed 3D model.
|
||||
*/
|
||||
void Clear3DModel();
|
||||
|
||||
private:
|
||||
void ogl_initialize();
|
||||
void ogl_set_arrow_material();
|
||||
|
||||
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()
|
||||
|
||||
/// openGL context
|
||||
wxGLContext* m_glRC;
|
||||
|
||||
/// Camera used in this canvas
|
||||
TRACK_BALL m_trackBallCamera;
|
||||
|
||||
/// Original 3d model data
|
||||
const S3DMODEL* m_3d_model;
|
||||
|
||||
/// Class holder for 3d model to display on openGL
|
||||
MODEL_3D* 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_
|
||||
@@ -0,0 +1 @@
|
||||
#define PLUGINDIR "@CMAKE_INSTALL_FULL_LIBDIR@"
|
||||
@@ -0,0 +1,961 @@
|
||||
/*
|
||||
* 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
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* 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_
|
||||
|
||||
@@ -0,0 +1,383 @@
|
||||
/*
|
||||
* 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 );
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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_
|
||||
@@ -0,0 +1,832 @@
|
||||
/*
|
||||
* 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 );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,300 @@
|
||||
/*
|
||||
* 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_
|
||||
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* 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 ();
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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_
|
||||
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
+7
-11
@@ -2,7 +2,7 @@
|
||||
* 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-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
@@ -33,7 +33,7 @@
|
||||
*
|
||||
* Perlin_Noise
|
||||
* "Here you could find the code for "Perlin noise in C++11",
|
||||
* for more information visit the project webpage:
|
||||
* 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
|
||||
@@ -54,15 +54,14 @@
|
||||
|
||||
class PerlinNoise
|
||||
{
|
||||
// The permutation vector
|
||||
std::vector<int> p;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Initialize with the reference values for the permutation vector.
|
||||
*/
|
||||
// Initialize with the reference values for the permutation vector
|
||||
PerlinNoise();
|
||||
|
||||
/**
|
||||
* Generate a new permutation vector based on the value of seed.
|
||||
*/
|
||||
// Generate a new permutation vector based on the value of seed
|
||||
PerlinNoise( unsigned int seed );
|
||||
|
||||
// Returns between 0.0f and 1.0f
|
||||
@@ -74,9 +73,6 @@ private:
|
||||
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;
|
||||
|
||||
// The permutation vector
|
||||
std::vector<int> p;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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()
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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_
|
||||
@@ -0,0 +1,295 @@
|
||||
/*
|
||||
* 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
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* 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_
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* 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 ccontainer.cpp
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#include "ccontainer.h"
|
||||
#include <stdio.h>
|
||||
|
||||
CGENERICCONTAINER::CGENERICCONTAINER()
|
||||
{
|
||||
m_objects.clear();
|
||||
m_bbox.Reset();
|
||||
}
|
||||
|
||||
void CGENERICCONTAINER::Clear()
|
||||
{
|
||||
if( !m_objects.empty() )
|
||||
{
|
||||
for( LIST_OBJECT::iterator ii = m_objects.begin();
|
||||
ii != m_objects.end();
|
||||
++ii )
|
||||
{
|
||||
delete *ii;
|
||||
*ii = NULL;
|
||||
}
|
||||
|
||||
m_objects.clear();
|
||||
}
|
||||
|
||||
m_bbox.Reset();
|
||||
}
|
||||
|
||||
|
||||
CGENERICCONTAINER::~CGENERICCONTAINER()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
|
||||
void CGENERICCONTAINER::ConvertTo( CONST_VECTOR_OBJECT &aOutVector ) const
|
||||
{
|
||||
aOutVector.resize( m_objects.size() );
|
||||
|
||||
if( !m_objects.empty() )
|
||||
{
|
||||
unsigned int i = 0;
|
||||
|
||||
for( LIST_OBJECT::const_iterator ii = m_objects.begin();
|
||||
ii != m_objects.end();
|
||||
++ii )
|
||||
{
|
||||
wxASSERT( (*ii) != NULL );
|
||||
|
||||
aOutVector[i++] = static_cast<const COBJECT *>(*ii);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CCONTAINER::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const
|
||||
{
|
||||
|
||||
if( !m_bbox.Intersect( aRay ) )
|
||||
return false;
|
||||
|
||||
bool hitted = false;
|
||||
|
||||
for( LIST_OBJECT::const_iterator ii = m_objects.begin();
|
||||
ii != m_objects.end();
|
||||
++ii )
|
||||
{
|
||||
const COBJECT *object = static_cast<const COBJECT *>(*ii);
|
||||
|
||||
if( object->Intersect( aRay, aHitInfo) )
|
||||
hitted = true;
|
||||
}
|
||||
|
||||
return hitted;
|
||||
}
|
||||
|
||||
|
||||
bool CCONTAINER::IntersectP( const RAY &aRay, float aMaxDistance ) const
|
||||
{
|
||||
/*
|
||||
if( !m_bbox.Inside( aRay.m_Origin ) )
|
||||
if( !m_bbox.Intersect( aRay ) )
|
||||
return false;
|
||||
*/
|
||||
for( LIST_OBJECT::const_iterator ii = m_objects.begin();
|
||||
ii != m_objects.end();
|
||||
++ii )
|
||||
{
|
||||
const COBJECT *object = static_cast<const COBJECT *>(*ii);
|
||||
|
||||
if( object->IntersectP( aRay, aMaxDistance ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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 ccontainer.h
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef _CCONTAINER_H_
|
||||
#define _CCONTAINER_H_
|
||||
|
||||
#include "../shapes3D/cobject.h"
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
typedef std::list<COBJECT *> LIST_OBJECT;
|
||||
typedef std::vector<COBJECT *> VECTOR_OBJECT;
|
||||
typedef std::vector<const COBJECT *> CONST_VECTOR_OBJECT;
|
||||
|
||||
class CGENERICCONTAINER
|
||||
{
|
||||
protected:
|
||||
CBBOX m_bbox;
|
||||
LIST_OBJECT m_objects;
|
||||
|
||||
public:
|
||||
CGENERICCONTAINER();
|
||||
|
||||
virtual ~CGENERICCONTAINER();
|
||||
|
||||
void Add( COBJECT *aObject )
|
||||
{
|
||||
if( aObject ) // Only add if it is a valid pointer
|
||||
{
|
||||
m_objects.push_back( aObject );
|
||||
m_bbox.Union( aObject->GetBBox() );
|
||||
}
|
||||
}
|
||||
|
||||
void Clear();
|
||||
|
||||
const LIST_OBJECT &GetList() const { return m_objects; }
|
||||
|
||||
void ConvertTo( CONST_VECTOR_OBJECT &aOutVector ) const;
|
||||
|
||||
const CBBOX &GetBBox() const { return m_bbox; }
|
||||
|
||||
virtual bool Intersect( const RAY &aRay, HITINFO &aHitInfo ) const = 0;
|
||||
virtual bool IntersectP( const RAY &aRay, float aMaxDistance ) const = 0;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
|
||||
class CCONTAINER : public CGENERICCONTAINER
|
||||
{
|
||||
public:
|
||||
bool Intersect( const RAY &aRay, HITINFO &aHitInfo ) const override;
|
||||
bool IntersectP( const RAY &aRay, float aMaxDistance ) const override;
|
||||
};
|
||||
|
||||
#endif // _CCONTAINER_H_
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user